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.
This commit is contained in:
@@ -64,6 +64,7 @@ in `govoplan-records/docs/EAKTE_ARCHITECTURE.md`.
|
||||
| Evidence collection and promotion | [Target Maturity Evidence Runbook](operations/TARGET_MATURITY_EVIDENCE_RUNBOOK.md) |
|
||||
| Package publication and consumption | [Package Registry Releases](operations/PACKAGE_REGISTRY_RELEASES.md) |
|
||||
| Release-console operation | [Release Console](operations/RELEASE_CONSOLE.md) |
|
||||
| Repeated development, verification and evidence commands | [Developer Command Suite](operations/DEVKIT.md) |
|
||||
| Module compatibility and install behavior | [Module Contracts and Installs](operations/MODULE_CONTRACTS_AND_INSTALLS.md) |
|
||||
| Security-audit toolchain | [Security Audit](operations/SECURITY_AUDIT.md) |
|
||||
|
||||
@@ -75,6 +76,8 @@ in `govoplan-records/docs/EAKTE_ARCHITECTURE.md`.
|
||||
meta, module, deployment, and website content.
|
||||
- [Gitea Issues](project/GITEA_ISSUES.md) defines labels, templates, import, and
|
||||
state-update conventions.
|
||||
- [UI Review Program](project/UI_REVIEW_PROGRAM.md) defines the principle-led,
|
||||
per-module review process and links the canonical Gitea review inventory.
|
||||
|
||||
## Evidence And Archive
|
||||
|
||||
|
||||
Executable
+300
@@ -0,0 +1,300 @@
|
||||
# Developer command suite
|
||||
|
||||
`./devkit` is the maintained entry point for repeated development work. It uses
|
||||
ordinary local programs, not an AI service. People, CI and coding agents use the
|
||||
same commands and results. It composes existing GovOPlaN checks and release
|
||||
services rather than defining parallel product rules.
|
||||
|
||||
## Start here
|
||||
|
||||
From the Meta checkout:
|
||||
|
||||
```sh
|
||||
./devkit commands
|
||||
./devkit doctor --repo core
|
||||
./devkit context --changed
|
||||
./devkit check --profile quick --repo campaign --dry-run
|
||||
./devkit coverage --profile ui --repo campaign
|
||||
./devkit check --profile quick --repo campaign
|
||||
./devkit latest
|
||||
./devkit review campaign
|
||||
```
|
||||
|
||||
Use `--help` on each command. `--json` (or `--format json`) returns structured
|
||||
results; the default summary intentionally omits full logs and source contents.
|
||||
Global options work before or after the command. `--workspace-root` is the parent
|
||||
directory of the registered repositories, not the Core checkout. Unknown
|
||||
repository filters fail rather than silently widening/narrowing scope.
|
||||
|
||||
The launcher prefers Meta's `.venv/bin/python`, or the explicit `PYTHON`
|
||||
executable, with `python3` as the no-venv fallback. Checks resolve `NODE` and
|
||||
`NPM` from explicit environment settings or `PATH`; no username-specific Node
|
||||
installation path is required. Doctor reports repairs but never installs
|
||||
packages, changes configuration, kills an occupied port or starts a server.
|
||||
|
||||
## Command contracts
|
||||
|
||||
| Command | Purpose | Effects |
|
||||
| --- | --- | --- |
|
||||
| `context [--changed] [--repo NAME]` | Offline Git state, instruction/documentation paths and review links | Reads only; upstream counts are not freshly fetched |
|
||||
| `doctor [--repo NAME] [--profile PROFILE]` | Interpreter, dependency, browser and test-resource preflight | Reads only; repair suggestions are not executed |
|
||||
| `check --profile PROFILE` | Registered checks with explanations, bounded logs and a receipt | Runs trusted tests/builds; `--dry-run` only plans |
|
||||
| `coverage --profile PROFILE [--repo NAME]` | Declared suite dispositions and explicit coverage limits | Reads only; not execution evidence |
|
||||
| `runs [--limit 10] [--before RUN]`, `latest` | Discover recent runs without looking up state-directory paths | Reads only; malformed latest evidence is not replaced with an older pass |
|
||||
| `status RUN`, `summary RUN` | Stage counts and failure log locations | Reads only |
|
||||
| `logs RUN --stage STAGE --tail 40 [--final-only]` | Provisional live output or a hash-verified final stage log | Reads only; provisional output never proves a pass |
|
||||
| `resume RUN` | Replan the previous check selection and reuse eligible successful stages | Runs remaining checks, creating a new receipt |
|
||||
| `recover RUN [--apply]` | Recover an abandoned check-run record after acquiring its OS lock | No test replay; apply changes only the local record |
|
||||
| `review MODULE` | Source inventory, principle revision, issue links, check plan and walkthrough checklist | Does not perform or complete a module review |
|
||||
| `docs audit [--repo NAME] [--changed]` | Owning manifest/help/translation checks and visible-label gaps | Local checks only; never translates or edits content |
|
||||
| `issues note …` | Preview and explicitly append deduplicated evidence | Remote comment creation only with `--apply` |
|
||||
| `release …` | Existing durable release planning/execution/recovery | Explicit `--apply`, request IDs and existing step confirmations |
|
||||
| `git …` | Frozen, explicit-path maintenance commit and exact branch push | Preview first; mutations require `--apply`; no stage-all, force or tags |
|
||||
|
||||
Git maintenance is a separate, selected-path workflow; see
|
||||
[Git maintenance](DEVKIT_MAINTENANCE.md). Issue notes and module bundles are
|
||||
documented in [Evidence and review commands](DEVKIT_EVIDENCE.md). The complete
|
||||
release command syntax, limitations and examples are in
|
||||
[Headless release operations](DEVKIT_RELEASE.md).
|
||||
|
||||
## Check profiles and their limits
|
||||
|
||||
- `quick`: existing manifest/interface invariants, import/help guards and selected
|
||||
module source/structure tests. It does not compile component suites or run the
|
||||
full browser matrix.
|
||||
- `ui`: quick/source contracts plus the shared Core component batch, compiled
|
||||
once in an isolated directory. This is not a full visual/usability review.
|
||||
- `backend`: existing manifest/interface checks and selected repository backend
|
||||
test suites. Shared backend-test state is serialized.
|
||||
- `full`: the canonical `tools/checks/check-focused.sh`, including optional-module
|
||||
build permutations and integrated browser conformance. Repository filters do
|
||||
not reduce this required cross-module completion gate.
|
||||
|
||||
`--changed` includes uncommitted work, commits ahead of the locally cached
|
||||
upstream and repositories with commits but no configured upstream.
|
||||
Missing/unreadable repositories remain visible as errors. For the
|
||||
GovOPlaN profiles, Core or Meta changes conservatively select every registered
|
||||
consumer; other changes expand through declared interface consumers. This is
|
||||
not complete semantic dependency analysis. Use the full gate for cross-module
|
||||
completion as required by `AGENTS.md`.
|
||||
|
||||
The module catalog reuses declared direct-Node tests and established structural
|
||||
script names. Arbitrary shell chains are not guessed or rewritten. Unsupported
|
||||
declared scripts remain visible with a reason; only exact known Core component
|
||||
aliases are covered by the shared component runner. Invalid package metadata is
|
||||
an error, not an empty test inventory.
|
||||
|
||||
`coverage` inventories declared suites as `planned`, `covered_elsewhere`,
|
||||
`excluded` or `unsupported`, naming their covering stage where applicable. The
|
||||
same inventory accompanies check dry runs and saved receipts. **Full means the
|
||||
canonical focused gate, not every test in every package.** Its inventory follows
|
||||
explicit canonical commands conservatively; it does not infer arbitrary nested
|
||||
shell commands or npm hooks. Add new deterministic checks to the owning
|
||||
package/canonical gate and the catalog's tests as appropriate. Coverage planning
|
||||
does not execute the scripts it inventories or assert that they passed. See
|
||||
[Coverage and validation details](DEVKIT_COVERAGE.md) for examples and boundaries.
|
||||
|
||||
Independent checks can run with `--jobs 1..8` (default 2). Shared resources use
|
||||
OS locks for the current user, including across runs with different evidence
|
||||
directories. Browser/port locks are shared across that user's workspaces. Full runs
|
||||
reserve the shared WebUI/backend/browser resources. Standalone Core component
|
||||
commands use isolated temporary build directories; `npm run test:components --
|
||||
page-layout documentation-help` compiles once for that batch. Managed temporary
|
||||
output is cleaned; no user worktree is reset or restored.
|
||||
|
||||
## Evidence, interruption and safe reuse
|
||||
|
||||
A check announces its run ID and saves a `preparing` receipt before source and
|
||||
environment fingerprinting. Progress on stderr shows elapsed time, stage counts
|
||||
and active stages; it also distinguishes `checking` from final snapshot
|
||||
verification (`finalizing`). `--json` keeps stdout as one final JSON result and
|
||||
emits structured progress events on stderr; `--quiet` suppresses these events.
|
||||
Use `latest`, `status RUN` and `logs RUN --stage STAGE` from another terminal
|
||||
while a check runs. Counts are stages, not a guessed percentage of test effort.
|
||||
|
||||
Live snapshots are private, bounded, explicitly provisional and not accepted for
|
||||
reuse or issue evidence. A completed stage log can be hash-verified before the
|
||||
whole run finishes, but only the final run snapshot verifies the overall result.
|
||||
`--final-only` rejects unfinished logs. Run history supports cursor pagination
|
||||
(up to 100 rows per page), bounds directory scanning, and never deletes evidence.
|
||||
An explicitly selected `--project` also filters run discovery by project file.
|
||||
|
||||
Default records are private below
|
||||
`$XDG_STATE_HOME/govoplan/devkit/workspace-<identity>/runs/<run>/` (fallback
|
||||
`~/.local/state`). `--state-dir` selects another base; workspace scoping still
|
||||
applies. Status changes are atomically persisted with restrictive file modes;
|
||||
symlinked evidence paths are rejected. A record contains source/environment/plan
|
||||
fingerprints, stage reasons, status, exit code, timing and log identities.
|
||||
|
||||
Stages distinguish pending, running, passed, failed, timed out, blocked, skipped,
|
||||
stale and interrupted. A skipped or unexecuted stage is never a pass. A source or
|
||||
environment change during verification marks the overall result **stale**, even
|
||||
when individual subprocesses returned zero. Such a result is not passing evidence.
|
||||
|
||||
`resume RUN` replans the current selection and compares each phase independently.
|
||||
Matching **verified checkpoints** are reused; changed/new phases and phases
|
||||
without a checkpoint run again. A checkpoint binds the exact command and working
|
||||
directory, declared repository inputs, transitive data-dependency identities,
|
||||
devkit implementation/schema, tool/dependency metadata and environment. Logs must
|
||||
retain their recorded hashes; a missing or changed cached log fails closed.
|
||||
The summary reports how many checkpoints were reused; JSON records `input_scope`,
|
||||
`cache_key`, `checkpoint_verified`, `reused_from` and the reuse/rerun reason.
|
||||
|
||||
Each checkpoint is saved while its resource locks remain held, only after exit
|
||||
zero, a verified final log, and matching before/after inputs and environment.
|
||||
A phase that changes its own inputs is stale, even if another phase later restores
|
||||
those bytes. Final verification rechecks all passed/reused phases against current
|
||||
inputs before the new aggregate can pass. An interrupted, failed or stale run may
|
||||
donate an independently verified matching checkpoint, but never becomes passing
|
||||
evidence itself. Old receipts remain readable: legacy monolithic logs and receipts
|
||||
without these checkpoints cannot be retroactively split or reused as verified phases.
|
||||
|
||||
After a hard crash, `recover RUN` shows the abandoned owner and guidance. Inspect the
|
||||
recorded commands and manually stop any surviving test/build processes before
|
||||
using `recover RUN --apply --confirm-processes-stopped`. The command verifies the
|
||||
run lock is free before marking the record interrupted. A free parent lock alone
|
||||
does **not** prove children stopped after a hard kill. Recovery does not replay
|
||||
processes or infer that a partially completed operation succeeded.
|
||||
|
||||
### Canonical phases and narrower inputs
|
||||
|
||||
The full gate has seven explicit phases: `preflight`, `tooling`, `backend`,
|
||||
`core-ui`, `module-builds`, `browser`, and `module-ui`. Devkit stage IDs are
|
||||
`focused.<phase>`. The authoritative Bash bodies remain in
|
||||
`tools/checks/check-focused.sh`; the bounded metadata in
|
||||
`tools/checks/focused-phases.json` names their order and resources. The direct
|
||||
shell command still runs every phase in the original fail-fast order. For inspection:
|
||||
|
||||
```sh
|
||||
tools/checks/check-focused.sh --list-phases
|
||||
./devkit check --profile full --jobs 1
|
||||
./devkit resume RUN_ID --jobs 1
|
||||
```
|
||||
|
||||
For example, a browser failure no longer forces successful backend/build phases
|
||||
to run again if their inputs still match. Standalone `--phase browser` is available
|
||||
for diagnostics, but is not a substitute for the complete gate or its receipt.
|
||||
|
||||
Scopes are whole repositories, not inferred file globs. A trusted check may declare
|
||||
`"inputs": {"repos": ["canonical-repository-name"]}`; no declaration means the whole
|
||||
registered workspace. Dry runs show that boundary. Native source-discovery checks
|
||||
retain broad scopes where cross-module dependencies cannot safely be narrowed.
|
||||
Changes outside an explicit scope do not invalidate it, but tool/environment
|
||||
changes remain conservatively global. Scope declarations are a correctness
|
||||
contract: include every source repository that the check reads, not only its cwd.
|
||||
Native discovery ownership/presence is rechecked at phase boundaries, so a newly
|
||||
appearing module or WebUI directory invalidates the in-flight environment identity.
|
||||
Unregistered native sibling sources disable reuse with an explicit coverage note;
|
||||
register them before relying on cached results. Ordinary generated files inside
|
||||
existing source directories do not change this directory-shape identity.
|
||||
|
||||
Every snapshot rereads repository presence, HEAD, index/flags and tracked plus
|
||||
non-ignored untracked membership, including assume-unchanged files. File hashes
|
||||
use a bounded **in-process-only** memo with file identity/ctime/mtime/size checks
|
||||
before and after an open file descriptor; no persistent mtime cache is trusted.
|
||||
In-repository regular-file symlink targets are included; escaping or directory
|
||||
symlinks fail closed. Ignored files, undeclared external data and service state
|
||||
are not source evidence and need explicit verification.
|
||||
|
||||
Environment probes stream bounded regular-file contents and reject concurrent
|
||||
replacement, growth and symlink retargeting. Stable venv executable and dependency
|
||||
directory symlinks remain supported without changing the executable path; absent
|
||||
optional metadata remains optional. Environment identities are not persistently
|
||||
cached and remain deliberately global.
|
||||
|
||||
These checkpoints cache **verification results, not output artifacts**. The full
|
||||
gate's phases were audited so later phases do not require an earlier phase's
|
||||
retained build output. A custom setup/build that produces files consumed later
|
||||
must declare `"reuse": "never"`; its consumers must use `deps`. Until output
|
||||
manifests/restoration exist, do not assume a cached successful build recreates
|
||||
deleted ignored artifacts.
|
||||
|
||||
Check output is drained without unbounded memory growth. Stored output retains
|
||||
the beginning and actual final tail within an 8 MiB bound per stage, with a small
|
||||
truncation marker and an omitted-byte count; output truncation does not change
|
||||
the subprocess exit result. `logs` exposes at most 200 lines and 16 KiB. Live
|
||||
snapshots retain at most 64 KiB after redaction. Incomplete live lines and cut
|
||||
retention-boundary lines are withheld to avoid exposing fragments of secrets;
|
||||
very long single-line output may therefore be absent from live views.
|
||||
Known environment credentials and common authorization patterns are
|
||||
redacted as display hygiene. **Never pass credentials as check arguments or print
|
||||
them from tests.** Redaction is not a general secret-classification guarantee.
|
||||
JSON command output is a redacted presentation; the receipt file at the reported
|
||||
path is the canonical local record. Cancellation and deadlines terminate the
|
||||
owned process group; a parent leaving running descendants does not pass.
|
||||
During source/environment fingerprinting, cancellation is observed between
|
||||
probes; the current bounded probe may finish first. Cancellation during final
|
||||
verification is recorded as interrupted, never as a passing run.
|
||||
Deliberately detached processes are outside that group: this is not a sandbox.
|
||||
|
||||
These local hash-bound records detect accidental changes; they are not signed
|
||||
attestations, a security certification, proof of complete test coverage, or
|
||||
permission to publish. External service state and undeclared dependencies still
|
||||
need explicit verification. No automated result closes a Gitea issue or marks a
|
||||
module reviewed. Detailed logs remain local unless deliberately shared. Old run
|
||||
directories are not automatically deleted; review retention before removing any
|
||||
evidence referenced by an issue.
|
||||
|
||||
## Reuse in another project
|
||||
|
||||
The runner, repository context, doctor and evidence primitives are usable with an
|
||||
explicit local JSON project manifest. The example at
|
||||
`tools/devkit/examples/project.json` registers ordinary Python tests and a Git
|
||||
whitespace check; the format is described by
|
||||
`tools/devkit/project.schema.json`.
|
||||
|
||||
```sh
|
||||
/path/to/govoplan/devkit --workspace-root /path/to/project \
|
||||
--project /path/to/project/devkit-project.json check --profile quick --dry-run
|
||||
```
|
||||
|
||||
Repository paths and check working directories must remain inside the selected
|
||||
workspace. Check arguments are arrays, not shell-evaluated strings. The supported
|
||||
tool placeholders are `{python}`, `{node}`, `{npm}` and `{workspace}`. Check
|
||||
dependencies form an acyclic graph; resources serialize incompatible tasks.
|
||||
`deps` declares actual data dependencies: consumers rerun whenever a dependency
|
||||
runs again. `after` declares only fail-fast execution ordering: a failed predecessor
|
||||
skips the follower, but a successfully rerun independent predecessor does not
|
||||
invalidate the follower's inputs. Both edge types are validated together for
|
||||
cycles, missing IDs and overlap. `reuse` is `verified` by default or `never` for
|
||||
setup/output-producing checks. Repository `inputs` names are canonical, unique,
|
||||
nonempty and validated even for unselected checks.
|
||||
The complete custom manifest is validated, including unselected checks/profiles:
|
||||
unknown fields, misspellings, invalid bounds/types and unresolved dependencies
|
||||
fail early. This prevents silently ignored resource or timeout declarations.
|
||||
|
||||
Portable `doctor` always requires its Python runtime, plus tools needed by the
|
||||
selected checks and their dependencies and tools explicitly configured in the
|
||||
manifest. Without `--profile`, all declared profiles are considered. Unused
|
||||
Node/npm are marked `not_required` and do not block Python-only projects. Declare
|
||||
indirect tool dependencies explicitly: arbitrary script contents are not
|
||||
analyzed. Native GovOPlaN retains its Python/Node/npm requirements.
|
||||
Only use project manifests and scripts you trust: running a registered test is
|
||||
ordinary code execution, not a sandbox. Platform-specific release and Docs
|
||||
commands reject generic project manifests; put another project's checks in its
|
||||
own profiles rather than pretending its release policy is GovOPlaN's.
|
||||
|
||||
The initial runtime targets POSIX environments with Python 3.11+ and OS advisory
|
||||
locks; it does not claim Windows support. No globally installed service or Codex
|
||||
plugin is needed. Keep this implementation versioned and reuse it; avoid copying
|
||||
diverging helper implementations into each project.
|
||||
|
||||
Devkit is not a complete build system: it does not infer semantic dependencies,
|
||||
restore output artifacts, sandbox checks, or share signed remote caches. Repository
|
||||
scopes intentionally stop short of file/glob narrowing; environment identities
|
||||
remain global. These are explicit boundaries, not claims of exhaustive coverage.
|
||||
|
||||
## Development and conformance
|
||||
|
||||
```sh
|
||||
./.venv/bin/python -m pytest -q tests/test_devkit_*.py
|
||||
./.venv/bin/python -m pytest -q tests/test_focused_phases.py
|
||||
node --test tests/test-devkit-display-labels.mjs
|
||||
./.venv/bin/python -m unittest tests.test_documentation_structure
|
||||
```
|
||||
|
||||
The focused gate includes the Python command-suite regression tests. Fixture
|
||||
tests use temporary repositories/processes and mocked issue/release transports;
|
||||
they do not commit user work, send mail, publish artifacts or change live issues.
|
||||
Documentation is part of each command change: update `--help`, this guide and the
|
||||
corresponding targeted contract tests together.
|
||||
Executable
+72
@@ -0,0 +1,72 @@
|
||||
# Check configuration and suite coverage
|
||||
|
||||
`devkit coverage` explains what a selected plan intends to run. It does not run
|
||||
tests, start servers, or report successful verification:
|
||||
|
||||
```sh
|
||||
./devkit coverage --profile quick --repo campaign
|
||||
./devkit coverage --profile ui --repo portal --json
|
||||
./devkit coverage --profile full --json
|
||||
./devkit --project /path/to/project.json coverage --profile quick
|
||||
```
|
||||
|
||||
The inventory accounts for declared `test` and `test:*` scripts in each
|
||||
registered repository's root and `webui/package.json`, discovered UI structural
|
||||
checks, and explicitly configured project checks. It is a suite inventory, not
|
||||
an enumeration of every test function or recursive dependency. Unselected suites
|
||||
remain visible; every row has a disposition and reason:
|
||||
|
||||
| Disposition | Meaning |
|
||||
| --- | --- |
|
||||
| `planned` | A selected stage directly invokes the suite. |
|
||||
| `covered_elsewhere` | An exact equivalent invocation or an explicitly selected shared batch owns it; the covering stage is named. |
|
||||
| `excluded` | The suite is outside the actual selected plan. |
|
||||
| `unsupported` | Scoped discovery cannot safely interpret or locate the command; no command is guessed or executed. |
|
||||
|
||||
`full` means the existing canonical `check-focused.sh` gate. It does **not**
|
||||
mean every package script or every component suite. Coverage reads the current
|
||||
script's explicit npm/Node commands inside its seven registered marked phase
|
||||
bodies, without executing shell code or inferring arbitrary functions, nested
|
||||
scripts, npm hooks, branches or here-document contents. Each covered suite names
|
||||
the `focused.<phase>` that owns it. The
|
||||
current gate names four of the sixteen Core component suites: layout primitives,
|
||||
page layout, DataGrid actions/sizing, and Mail components. The other twelve stay
|
||||
explicitly excluded from that gate's component batch. `ui` runs the shared
|
||||
sixteen-suite batch once; `quick` does not compile component tests.
|
||||
|
||||
Only Core's exact known component aliases receive that shared-batch treatment.
|
||||
A different repository using the same filename, an unknown alias, or a compound
|
||||
command containing the runner is not silently credited or launched. Ordinary
|
||||
scoped source discovery accepts bounded direct `node`/`node --test` commands
|
||||
targeting regular package-owned `.mjs` files in `scripts` or `tests`; shell
|
||||
chains, extra flags, missing targets and symlinked targets are not rewritten.
|
||||
An explicit invocation already present in the canonical full gate remains part
|
||||
of that gate, even when the narrower discovery profile does not support it.
|
||||
|
||||
Coverage rows retain a command hash and, for supported commands, redacted argv.
|
||||
Unsupported shell bodies are not copied into the inventory. This is display
|
||||
hygiene, not permission to put secrets into project commands. Coverage is
|
||||
attached to check plans/receipts; it never turns an excluded suite into a pass.
|
||||
|
||||
## Portable-project validation
|
||||
|
||||
The runtime validates custom project metadata against the published
|
||||
[`project.schema.json`](../../tools/devkit/project.schema.json) using a small
|
||||
dependency-free validator. All checks and profiles are validated before
|
||||
selection, including checks the chosen profile does not execute. Unknown nested
|
||||
fields such as `resource` or `timout_seconds`, malformed types, oversized values,
|
||||
duplicate references, missing dependencies, unknown profiles and dependency
|
||||
cycles fail with controlled errors. Repository aliases and resolved paths must
|
||||
be unambiguous and confined to the workspace. Check `cwd` defaults to `.` when
|
||||
omitted; configured paths cannot escape the workspace.
|
||||
|
||||
Package JSON is bounded to 1 MiB and 512 scripts; duplicate JSON keys, excessive
|
||||
nesting and malformed script objects fail before planning. Command strings are
|
||||
bounded to 8,192 characters. This validates configuration, not the safety of its
|
||||
code: run only project manifests and test scripts you trust.
|
||||
|
||||
Checks may declare repository-scoped `inputs`, true data `deps`, order-only
|
||||
`after`, and `reuse: "never"` for setup/output-producing work. Unknown repositories,
|
||||
empty/duplicate scopes, overlapping edge types and cycles fail before execution.
|
||||
Missing inputs deliberately fall back to all registered repositories. See
|
||||
[checkpoint and input contracts](DEVKIT.md#canonical-phases-and-narrower-inputs).
|
||||
Executable
+171
@@ -0,0 +1,171 @@
|
||||
# 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
|
||||
```
|
||||
Executable
+97
@@ -0,0 +1,97 @@
|
||||
# Selected-path Git maintenance
|
||||
|
||||
The optional `git` namespace of `tools/devkit/devkit.py` is a deliberately
|
||||
narrow maintenance workflow. It is not a replacement for normal Git, the
|
||||
release executor, required human review, or Gitea's canonical issue state.
|
||||
|
||||
From the Meta repository, preview and then save a plan for explicit files:
|
||||
|
||||
```sh
|
||||
python3 tools/devkit/devkit.py git plan --repo core --path webui/src/example.ts --message "Fix the reviewed example"
|
||||
python3 tools/devkit/devkit.py git plan --repo core --path webui/src/example.ts --message "Fix the reviewed example" --apply
|
||||
```
|
||||
|
||||
Use the saved `git-…` plan ID for the remaining commands. Each mutation needs
|
||||
its own `--apply`; an unqualified command only previews the operation:
|
||||
|
||||
```sh
|
||||
python3 tools/devkit/devkit.py git commit git-PLAN_ID
|
||||
python3 tools/devkit/devkit.py git commit git-PLAN_ID --apply
|
||||
python3 tools/devkit/devkit.py git push git-PLAN_ID
|
||||
python3 tools/devkit/devkit.py git push git-PLAN_ID --apply
|
||||
python3 tools/devkit/devkit.py git status git-PLAN_ID
|
||||
```
|
||||
|
||||
The immutable local plan binds the registered repository, HEAD, branch, origin
|
||||
fetch/push URL hashes, Git configuration, complete index identity, explicit
|
||||
selected file paths, working-tree hashes, expected Git blobs, and commit message.
|
||||
Raw remote URLs and file contents are not stored. A changed input blocks the
|
||||
operation; inspect it and create another plan instead of weakening the check.
|
||||
Receipts are private local records with integrity checks, not signed approval
|
||||
or a security attestation.
|
||||
|
||||
Commit captures each selected file once, verifies the captured bytes and Git
|
||||
blob against the plan, and builds an isolated index/tree from the frozen HEAD
|
||||
plus only those blobs. Git's normal identity rules create the commit object;
|
||||
an atomic branch compare-and-swap publishes it only if the planned parent is
|
||||
still current. Active hooks/signing remain refused rather than bypassed.
|
||||
An editor racing with this operation cannot substitute newer working-tree
|
||||
bytes: those edits remain uncommitted, and the helper never overwrites files.
|
||||
|
||||
The real index is protected by Git's standard index lock. Only selected entries
|
||||
are updated from a prepared private copy; unrelated staging and index flags are
|
||||
preserved. If the index changes independently, its new data is not overwritten
|
||||
and the receipt requires reconciliation. The resulting parent, message,
|
||||
changed paths, blobs/modes and unrelated index entries are verified.
|
||||
Git refs and index files are separately atomic, not one filesystem transaction.
|
||||
Independent writers that ignore the standard index lock can still change refs
|
||||
during publication. The helper rechecks the exact recorded candidate before
|
||||
index recovery and before recording success; it refuses an uncertain result
|
||||
instead of adopting a newer HEAD or claiming that competing work was its own.
|
||||
Directories, noncanonical paths, implicit globs, staging-all, amend,
|
||||
force-push and extra-tag publication are not supported. A selected file with
|
||||
different staged and working-tree changes is refused; decide explicitly which
|
||||
version to commit using normal Git first.
|
||||
|
||||
Push requires the recorded commit to remain current, an unchanged origin and
|
||||
one standard-transport push destination. It requests a normal, non-forced push
|
||||
of that commit to the recorded branch and checks the remote branch afterward.
|
||||
The push preview does not contact a remote. A normal push may run the remote's
|
||||
usual CI or server-side hooks; this is an external effect of the separately
|
||||
authorized push, not of planning or committing.
|
||||
|
||||
Local active hooks (including index-change hooks), filter/encoding attributes,
|
||||
signing, external fsmonitor/SSH configuration, Git environment overrides,
|
||||
in-progress merge/rebase/cherry-pick operations, submodules, symlinks and
|
||||
assume-unchanged/skip-worktree entries, split indexes and replacement/graft
|
||||
history are deliberately
|
||||
unsupported. The helper
|
||||
refuses these cases instead of disabling hooks, signatures or filters. An
|
||||
unused globally installed filter definition alone does not block maintenance;
|
||||
active attributes are checked across tracked files as well as selected files.
|
||||
Custom remote receive-pack/upload-pack/helper commands, recursive submodule
|
||||
pushes and partial-clone lazy fetch are also refused. Of inherited `GIT_*`
|
||||
variables, only `GIT_OPTIONAL_LOCKS`, `GIT_TERMINAL_PROMPT` and `GIT_PAGER` are
|
||||
allowed (every command explicitly passes `--no-pager`, so the pager is inert);
|
||||
namespace, identity, alternate-index/object-directory and unknown overrides
|
||||
are not silently removed. Git subprocesses have bounded input/output and
|
||||
deadlines; cancellation terminates their owned process group, including
|
||||
transport helpers. Network failures can still leave a remote effect uncertain,
|
||||
which is why receipts require explicit reconciliation rather than blind retry.
|
||||
|
||||
An interruption or uncertain failure is recorded before any retry. Use
|
||||
`git reconcile git-PLAN_ID` to preview, then add `--apply` to verify an
|
||||
already-existing result. Reconciliation never makes a commit or push. It may
|
||||
finish the selected real-index update after an interrupted commit publication,
|
||||
but only when the original index fingerprint still matches; independent staged
|
||||
work is preserved and requires normal Git resolution. For an
|
||||
uncertain push it may read the frozen remote, but only with `--apply`. If no
|
||||
planned commit is current, the helper reports that state and requires a fresh
|
||||
plan after inspection. A forcibly killed process may leave its private scratch
|
||||
index or an owned Git index lock; the helper never guesses that an existing
|
||||
lock is safe to delete. Blob/commit preparation can leave unreferenced Git
|
||||
objects for ordinary Git garbage collection. It never automatically resets,
|
||||
restores, deletes, or rolls back user work.
|
||||
|
||||
The maintenance tests use disposable local repositories and local bare remotes.
|
||||
They never commit or push the user's workspace repositories.
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
# Headless durable releases
|
||||
|
||||
The devkit `release` commands use the **same release application, request
|
||||
validation, run store and bounded executors** as the
|
||||
[release console](RELEASE_CONSOLE.md). They invoke its ASGI application inside
|
||||
the current process, with an ephemeral internal token. No listening socket,
|
||||
background server, browser session or externally supplied console URL is used.
|
||||
The development environment's FastAPI/HTTPX dependencies load only when a
|
||||
release command runs; ordinary devkit help does not import them.
|
||||
|
||||
This is a GovOPlaN-specific provider. Repository and origin authority still comes
|
||||
from the release service's registered catalog. `--project` is explicitly rejected
|
||||
for release commands; a portable project configuration must not silently override
|
||||
that authority. A different workspace path does not authorize arbitrary release
|
||||
repositories, remotes, commands, signing policies or source bindings.
|
||||
|
||||
The default compact output includes the overall status, selected repository
|
||||
states and versions, source-preflight readiness, bounded gate findings and the
|
||||
recommended next action. Run inspection also shows step-state counts and the
|
||||
first outstanding steps. These are projections of the service response, not new
|
||||
readiness checks. Use `--json` for the complete existing plan or receipt; compact
|
||||
output deliberately omits executor commands, arguments and source bindings.
|
||||
|
||||
## Commands and boundaries
|
||||
|
||||
| Command | Purpose | Effect boundary |
|
||||
| --- | --- | --- |
|
||||
| `release status` | Current release dashboard | Offline by default; explicit remote/catalog flags enable their checks |
|
||||
| `release plan` | Selective repository/version plan | Inspection only; does not create a run |
|
||||
| `release list` | Bounded run history, with `--limit` and `--cursor` | Existing workspace-scoped store |
|
||||
| `release show RUN_ID` | Exact verified run, steps, receipts and required confirmations | No release execution |
|
||||
| `release create` | Freeze a selected repository/version plan | Preview by default; `--apply` persists a run |
|
||||
| `release preview RUN_ID STEP_ID` | Frozen step and its current constraints | No step claim; catalog publication additionally uses the existing validated-candidate preview |
|
||||
| `release execute RUN_ID STEP_ID` | One available durable step | Preview by default; `--apply`, explicit request ID and the step's exact confirmation are required |
|
||||
| `release resume RUN_ID` | Mark persisted running attempts interrupted | Requires `--apply`; never assumes an effect succeeded |
|
||||
| `release retry RUN_ID STEP_ID` | Prepare an eligible failed/read-only-interrupted step | Requires `--apply`; does not execute it |
|
||||
| `release reconcile RUN_ID STEP_ID` | Record a proven uncertain-write outcome | Requires `--apply`, `--confirm RECONCILE` and an explicit outcome |
|
||||
|
||||
Create and transition commands require caller-chosen `--request-id` values.
|
||||
Retain the same ID for an uncertain replay of the **same** command; changing
|
||||
inputs under an existing ID fails closed. No command automatically retries a
|
||||
mutation. These commands perform one explicit transition, not an implicit
|
||||
"release everything" loop.
|
||||
|
||||
Read commands do not commit, tag, push, publish or apply database migrations.
|
||||
The existing private run store can initialize its lock directory or upgrade a
|
||||
legacy record while inspecting it; this does not advance release steps.
|
||||
`--include-migrations` requests the existing audits, never migration application.
|
||||
`--online`, `--remote-tags` and `--public-catalog` are explicit network-check
|
||||
choices. A generic step preview describes frozen intent; it is not a claim that
|
||||
live preflight, remote identity or release acceptance has passed.
|
||||
|
||||
## Example: review, freeze and execute one step
|
||||
|
||||
Run the devkit through the workspace `./devkit` entrypoint. These examples put
|
||||
global options before `release`:
|
||||
|
||||
```sh
|
||||
./devkit --workspace-root /path/to/workspace --format json release plan \
|
||||
--repo-version govoplan-files=0.1.9
|
||||
|
||||
./devkit --workspace-root /path/to/workspace release create \
|
||||
--repo-version govoplan-files=0.1.9 --request-id files-release-create-0001
|
||||
|
||||
./devkit --workspace-root /path/to/workspace release create \
|
||||
--repo-version govoplan-files=0.1.9 --request-id files-release-create-0001 --apply
|
||||
|
||||
./devkit --workspace-root /path/to/workspace release show RUN_ID
|
||||
./devkit --workspace-root /path/to/workspace release preview RUN_ID STEP_ID
|
||||
./devkit --workspace-root /path/to/workspace release execute RUN_ID STEP_ID \
|
||||
--request-id files-release-step-0001 --confirm REQUIRED_CONFIRMATION --apply
|
||||
```
|
||||
|
||||
`RUN_ID`, `STEP_ID` and `REQUIRED_CONFIRMATION` stand for the actual values
|
||||
returned by the frozen run. For read-only preflight/alignment/install-verification
|
||||
steps, omit `--confirm` when the service reports an empty confirmation. Metadata,
|
||||
commit, release-lock, source-tag, source-push, candidate-generation and catalog
|
||||
publication steps keep the existing `UPDATE`, `COMMIT`, `LOCK`, `TAG`, `PUBLISH`,
|
||||
`GENERATE` and `PUSH` confirmations respectively. Prerequisite ordering is enforced
|
||||
by the same store; a later step cannot be forced through this adapter.
|
||||
|
||||
Version selection supports repeated `--repo-version REPO=VERSION`, or repeated
|
||||
`--repo REPO` with `--target-version VERSION`. Every created run needs explicit
|
||||
versions for all selected repositories. Conflicting version assignments are
|
||||
rejected. Planning is selective; repositories are never silently selected merely
|
||||
because their worktrees are dirty.
|
||||
|
||||
## Candidate publication and recovery
|
||||
|
||||
Use the frozen run's `catalog:selective-generator` and
|
||||
`catalog:validate-sign-publish` steps, not the disabled legacy mutation endpoints.
|
||||
Generation accepts repeated `--signing-key KEY_ID=PRIVATE_KEY_FILE`; these are
|
||||
operator-owned key-file references, never inline key material. Signing arguments
|
||||
are not emitted in devkit JSON or persisted by the adapter. Publication consumes
|
||||
the candidate receipt created by that run, not an arbitrary candidate directory.
|
||||
The existing source/runtime trust, immutable tag/remote identity, private
|
||||
candidate checks and exact commit-delta checks remain authoritative.
|
||||
|
||||
After an interrupted write, inspect the run and the actual local/remote effect.
|
||||
Use `resume --apply` if an attempt was left running. Then use `reconcile` with
|
||||
`effect_absent`, `effect_succeeded` or `unresolved`, `--confirm RECONCILE`, a new
|
||||
reconciliation request ID and `--apply`. Successful reconciliation still performs
|
||||
the service's independent receipt checks. An unresolved effect must not be
|
||||
retried or papered over by generating a new request ID. A failed/read-only
|
||||
attempt may use `retry --apply` and a new explicit execute attempt only when
|
||||
the existing lifecycle makes that safe.
|
||||
|
||||
## State and limitations
|
||||
|
||||
Every successful response exposes `state_location` and `candidate_location`.
|
||||
Without `--state-dir`, the adapter uses the console's existing default private,
|
||||
workspace-fingerprinted state directory. With `--state-dir PATH`, it uses
|
||||
`PATH/release-console/workspace-<fingerprint>/release-runs`. Workspaces cannot
|
||||
read or resume one another's runs. Existing ownership, symlink, permission,
|
||||
retention and record-integrity checks are unchanged.
|
||||
|
||||
Release preparation can commit only the recognized, receipt-bound metadata
|
||||
changes its executors produced. This command does **not** stage arbitrary source
|
||||
changes, use `git add -A`, force-push, retarget tags or enable the disabled generic
|
||||
prepare/sync/push endpoints. Normal selected-path maintenance requires its own
|
||||
explicit reviewed-change workflow; it is not silently folded into release.
|
||||
@@ -354,8 +354,17 @@ such as `0.2.0` or `0.2.0-alpha1`, but requires the first three version numbers
|
||||
to move forward.
|
||||
|
||||
Plain repository pushes are separate from catalog publication. `Preview Push`
|
||||
shows the selected repository push commands. `Push Selected` requires `PUSH` in
|
||||
the repository push confirmation field.
|
||||
shows the selected repository push commands, but generic push, sync and prepare
|
||||
mutation endpoints are disabled: they require a separate durable, receipt-bound
|
||||
maintenance workflow and cannot be enabled by typing a confirmation. Source
|
||||
release branch/tag publication uses the durable release-run steps described
|
||||
above; do not route ordinary dirty worktrees through the legacy all-repository
|
||||
stage/commit/tag helper.
|
||||
|
||||
The [headless devkit release commands](DEVKIT_RELEASE.md) invoke this same
|
||||
application in-process without starting a server. They expose selective planning,
|
||||
bounded status/history, create/show/preview/execute and explicit recovery while
|
||||
retaining the same request IDs, confirmations, source bindings and receipts.
|
||||
|
||||
The source release panel retains `Preview Tag + Publish` as a non-mutating
|
||||
inspection. Its legacy `Create Tags` and `Publish Tags` controls stay visible
|
||||
|
||||
Executable
+164
@@ -0,0 +1,164 @@
|
||||
# Product-wide UI review program
|
||||
|
||||
The [central Gitea epic](https://git.add-ideas.de/GovOPlaN/govoplan/issues/56)
|
||||
coordinates the review; its linked module issues are the canonical backlog,
|
||||
progress and evidence log. The [issue inventory](ui-review-issue-inventory.json)
|
||||
is a discovery/link snapshot, **not a second progress tracker**. All reviews were
|
||||
initialized pending. Implementing a shared component or moving a help icon does
|
||||
not by itself complete a module review.
|
||||
|
||||
The visual and interaction rules live in Core's
|
||||
[UI design principles](https://git.add-ideas.de/GovOPlaN/govoplan-core/src/branch/main/docs/UI_DESIGN_PRINCIPLES.md).
|
||||
This document defines how to apply and verify those principles across repositories;
|
||||
it does not fork their definitions. The usual [Gitea issue contract](GITEA_ISSUES.md)
|
||||
still applies. At the user's request, this cross-product program is coordinated in
|
||||
Meta; shared primitives and their implementation remain owned by Core.
|
||||
|
||||
## Scope and initial inventory
|
||||
|
||||
The September 2026 source/catalog baseline contains **77 review tracks**:
|
||||
|
||||
- **73 implemented scopes:** Core/shared shell and 72 manifest-backed modules.
|
||||
- **4 registered placeholders:** Appointments, Ledger, XÖV and XTA/OSCI. They have
|
||||
README-only repositories at initialization. Their separate readiness tracks
|
||||
remain pending for future interfaces; they are not counted as implemented or
|
||||
reviewed modules.
|
||||
|
||||
Meta and the public website are not business-module review scopes. Module IDs
|
||||
come from actual manifests, not repository-name guesses: for example,
|
||||
`govoplan-campaign` owns `campaigns` and `govoplan-dist-lists` owns `dist_lists`.
|
||||
The inventory is derived from `repositories.json`, trusted module manifests and
|
||||
the owning repository's source files. Changes to the catalog must be reconciled
|
||||
with the central epic rather than silently dropping a module.
|
||||
|
||||
A module with no standalone WebUI is still in scope. Review its configuration
|
||||
and administrator experience, contributed operator/public surfaces, widgets,
|
||||
documentation, permissions, errors and interactions exposed through other
|
||||
modules. A missing standalone page is not evidence of conformance. A reviewer
|
||||
may mark a particular principle not applicable only with a concrete explanation
|
||||
and source/runtime evidence. A placeholder likewise needs an explicit future-UI
|
||||
gate, not a fabricated page inventory or an automatic green review.
|
||||
|
||||
## Work order and ownership
|
||||
|
||||
Prioritize user-visible defects, usability and consistent interactions before
|
||||
broader features. Start with Core/shared-shell contracts and Campaign's complete
|
||||
workflow, then Files, Mail, Templates, Notifications, Docs/Help, Dashboard, Quick
|
||||
Access and Views. The remaining queue is ordered by observed defects, shared
|
||||
dependencies and risk. This is a starting order, not a claim that those reviews
|
||||
have started or finished; the central issue records the current focus.
|
||||
|
||||
For Campaign, use a compact, read-only campaign settings overview with explicit,
|
||||
scoped edit dialogs. Large recipient or attachment grids may use the UI-02 bulk
|
||||
editing exception: clearly entered edit mode, explicit Save and Cancel, dirty
|
||||
navigation protection, and no silent loss or accidental save. This direction
|
||||
must be implemented and verified in the Campaign review, not marked complete by
|
||||
the program bootstrap.
|
||||
|
||||
Fix a repeated problem in the owning shared primitive or semantic contract first,
|
||||
then migrate consumers and verify representative actual-module fixtures. Keep
|
||||
module business behavior in its own repository and preserve optional module
|
||||
boundaries. Do not replace concrete user evidence with a generic fixture alone.
|
||||
Parallel reviewers may own different modules, but they must coordinate shared
|
||||
Core files and browser fixtures instead of racing the same resources.
|
||||
|
||||
## Per-module review workflow
|
||||
|
||||
1. **Inventory.** Verify and extend the issue's source-derived seed: navigation,
|
||||
pages, nested routes, dialogs, labels/forms, tables/trees, admin/system/tenant/
|
||||
user settings, public/operator interfaces, widgets and optional-module
|
||||
contributions. Follow actual module entrypoints and runtime contributions;
|
||||
filename heuristics and manifest routes are a starting point, not an exhaustive
|
||||
runtime audit. Note roles, permission boundaries and installed optional modules.
|
||||
2. **Observe.** Exercise realistic narrow and wide viewports, German and English,
|
||||
keyboard navigation and focus, empty/loading/error/success states, clean/dirty
|
||||
edit modes, reload, navigation away and return, and restoration of personal
|
||||
preferences. Include realistic row counts, long labels, horizontal overflow,
|
||||
pagination and two-way column resizing with fixed columns between text fields.
|
||||
3. **Record.** Keep a findings/TODO/done ledger in the module issue. Every finding
|
||||
names the surface, reproduction, expected principle, impact, owner and linked
|
||||
implementation/evidence. A source inventory, planned fix or green generic
|
||||
test is not a completed finding. State product decisions and manual checks
|
||||
explicitly with enough context to resolve them.
|
||||
4. **Implement.** Prefer reusable shared primitives and action/page contracts.
|
||||
Keep display mode readable and editing intentional. Preserve authorization,
|
||||
server validation, save/cancel behavior and data integrity. Never send mail,
|
||||
delete records, change live configuration or trigger other irreversible effects
|
||||
merely to obtain UI evidence; use authorized fixtures or a safe test context.
|
||||
5. **Verify.** Run proportionate unit, structure and actual-module browser tests.
|
||||
Record commands, results, source revision and safe runtime evidence. Update the
|
||||
owning module's manifest-driven EN/DE documentation for behavior changes; run
|
||||
`tools/checks/check-manifest-shapes.py` and relevant cross-module checks.
|
||||
6. **Conclude honestly.** Complete the principle matrix, evidence and manual
|
||||
checks. Link unresolved follow-ups and blockers; do not close a supposedly
|
||||
complete review while required work is still pending. Closing an issue requires
|
||||
explicit reviewed scope and the applicable design-principle revision.
|
||||
|
||||
## Principle ledger and back-propagation
|
||||
|
||||
Use the stable IDs from Core in each issue. The initial revision covers UI-01
|
||||
heading/label help placement; UI-02 display-first/scoped editing; UI-03 actions;
|
||||
UI-04 table/card geometry; UI-05 loading/error/progress; UI-06 tree interaction;
|
||||
UI-07 accessibility and German; UI-08 data integrity; and UI-09 propagation of
|
||||
revised principles. Core remains the authoritative definition.
|
||||
|
||||
Each module maintains this matrix, initially entirely pending:
|
||||
|
||||
| Principle/revision | Applicable surfaces / justified N/A | Applied / remaining work | Evidence | Exception / owner / follow-up |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| UI-01 … UI-09 | Pending inventory | Pending review | Not yet recorded | None approved |
|
||||
|
||||
Whenever a principle is added or changed:
|
||||
|
||||
1. Update Core's rule with its rationale, stable ID and revision/change reference.
|
||||
2. List **all already-reviewed modules**, not just the current implementation's
|
||||
consumers. Check whether the changed rule applies to each.
|
||||
3. Record unchanged conformance with evidence, or reopen the review / create a
|
||||
linked follow-up with owner, exact affected surfaces and required checks.
|
||||
4. Update the central epic's propagation ledger. Previously reviewed modules with
|
||||
outstanding applicable work are **follow-up required**, not silently green.
|
||||
5. Resolve the propagation sweep only after every affected module has current
|
||||
evidence or an explicit, owned and justified exception. Exceptions do not
|
||||
silently change the shared rule.
|
||||
|
||||
Suggested central ledger:
|
||||
|
||||
| Principle change | Already-reviewed modules checked | Conformant evidence | Reopened / follow-up required | Exceptions / owner | Sweep state |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| Initial UI-01–UI-09 baseline | None reviewed at initialization | None | All module reviews pending | None approved | Pending |
|
||||
|
||||
## Safe inventory/bootstrap automation
|
||||
|
||||
`tools/gitea/gitea-ui-review-program.py` derives the current scopes from the
|
||||
catalog and source manifests, inventories routes and UI source entrypoints,
|
||||
then deduplicates issues by a stable hidden marker and normalized exact title.
|
||||
It includes closed issues in duplicate checks and never reopens, closes or
|
||||
overwrites existing module issues. Ambiguous or unmanaged duplicates stop the
|
||||
operation for review. Existing issue bodies, labels and review progress are
|
||||
preserved. A failed POST is not automatically retried; a subsequent run checks
|
||||
the marker again before deciding whether another create is needed.
|
||||
|
||||
Dry-run is the default. An authenticated dry-run performs only Gitea reads:
|
||||
|
||||
```sh
|
||||
.venv/bin/python tools/gitea/gitea-ui-review-program.py \
|
||||
--env-file /home/zemion/.config/gitea/gitea.env --epic 56
|
||||
```
|
||||
|
||||
Creating missing review issues requires explicit `--apply`. Initial population
|
||||
of the central epic's module-link block additionally requires
|
||||
`--initialize-links`; it is accepted only for the untouched bootstrap placeholder.
|
||||
Later runs must not rewrite checkboxes or human-maintained progress. Existing
|
||||
complete links are verified read-only. The token is loaded through the shared
|
||||
Gitea helpers and is never emitted in reports. A scoped `--ipv4` option works
|
||||
around host-specific IPv6 connectivity while retaining HTTPS certificate and
|
||||
hostname verification.
|
||||
|
||||
The tool emits a JSON result to stdout with source counts and issue links. The
|
||||
checked-in inventory is a reviewed initialization snapshot of that result;
|
||||
refreshing links does not authorize replacing live review status with the
|
||||
snapshot. Test the automation offline with:
|
||||
|
||||
```sh
|
||||
.venv/bin/python -m pytest tests/test_ui_review_program.py -q
|
||||
```
|
||||
Executable
+866
@@ -0,0 +1,866 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"snapshot_purpose": "Issue discovery links; live Gitea issues own review state and evidence.",
|
||||
"epic": {
|
||||
"repository": "govoplan",
|
||||
"number": 56,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan/issues/56"
|
||||
},
|
||||
"scope_count": 77,
|
||||
"manifest_modules": 72,
|
||||
"implemented_scopes": 73,
|
||||
"catalogued_placeholders": 4,
|
||||
"created": 77,
|
||||
"missing": 0,
|
||||
"issues": [
|
||||
{
|
||||
"scope_id": "core",
|
||||
"name": "Core / shared shell",
|
||||
"repository": "govoplan-core",
|
||||
"kind": "core",
|
||||
"ui_source_count": 111,
|
||||
"number": 301,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-core/issues/301",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "access",
|
||||
"name": "Access",
|
||||
"repository": "govoplan-access",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 18,
|
||||
"number": 23,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-access/issues/23",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "addresses",
|
||||
"name": "Addresses",
|
||||
"repository": "govoplan-addresses",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 26,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-addresses/issues/26",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "admin",
|
||||
"name": "Admin",
|
||||
"repository": "govoplan-admin",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 9,
|
||||
"number": 11,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-admin/issues/11",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "approvals",
|
||||
"name": "Approvals",
|
||||
"repository": "govoplan-approvals",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 4,
|
||||
"number": 5,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-approvals/issues/5",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "assets",
|
||||
"name": "Assets",
|
||||
"repository": "govoplan-assets",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-assets/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "audit",
|
||||
"name": "Audit",
|
||||
"repository": "govoplan-audit",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 10,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-audit/issues/10",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "booking",
|
||||
"name": "Booking",
|
||||
"repository": "govoplan-booking",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-booking/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "calendar",
|
||||
"name": "Calendar",
|
||||
"repository": "govoplan-calendar",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 10,
|
||||
"number": 26,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-calendar/issues/26",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "campaigns",
|
||||
"name": "Campaigns",
|
||||
"repository": "govoplan-campaign",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 60,
|
||||
"number": 103,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-campaign/issues/103",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "cases",
|
||||
"name": "Cases",
|
||||
"repository": "govoplan-cases",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 4,
|
||||
"number": 8,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-cases/issues/8",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "certificates",
|
||||
"name": "Certificates",
|
||||
"repository": "govoplan-certificates",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-certificates/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "committee",
|
||||
"name": "Committee",
|
||||
"repository": "govoplan-committee",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 3,
|
||||
"number": 5,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-committee/issues/5",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "connectors",
|
||||
"name": "Connectors",
|
||||
"repository": "govoplan-connectors",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 3,
|
||||
"number": 20,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-connectors/issues/20",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "consultation",
|
||||
"name": "Consultation",
|
||||
"repository": "govoplan-consultation",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-consultation/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "contracts",
|
||||
"name": "Contracts",
|
||||
"repository": "govoplan-contracts",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-contracts/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "dashboard",
|
||||
"name": "Dashboard",
|
||||
"repository": "govoplan-dashboard",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 5,
|
||||
"number": 6,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-dashboard/issues/6",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "dataflow",
|
||||
"name": "Dataflow",
|
||||
"repository": "govoplan-dataflow",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 5,
|
||||
"number": 24,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-dataflow/issues/24",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "datasources",
|
||||
"name": "Datasources",
|
||||
"repository": "govoplan-datasources",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 10,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-datasources/issues/10",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "decisions",
|
||||
"name": "Decisions",
|
||||
"repository": "govoplan-decisions",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 2,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-decisions/issues/2",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "dist_lists",
|
||||
"name": "Distribution Lists",
|
||||
"repository": "govoplan-dist-lists",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 2,
|
||||
"number": 10,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-dist-lists/issues/10",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "dms",
|
||||
"name": "DMS",
|
||||
"repository": "govoplan-dms",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 3,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-dms/issues/3",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "docs",
|
||||
"name": "Docs",
|
||||
"repository": "govoplan-docs",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 2,
|
||||
"number": 23,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-docs/issues/23",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "encryption",
|
||||
"name": "Encryption",
|
||||
"repository": "govoplan-encryption",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 7,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-encryption/issues/7",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "erp",
|
||||
"name": "ERP",
|
||||
"repository": "govoplan-erp",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 2,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-erp/issues/2",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "evaluation",
|
||||
"name": "Evaluation",
|
||||
"repository": "govoplan-evaluation",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-evaluation/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "facilities",
|
||||
"name": "Facilities",
|
||||
"repository": "govoplan-facilities",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-facilities/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "files",
|
||||
"name": "Files",
|
||||
"repository": "govoplan-files",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 8,
|
||||
"number": 48,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-files/issues/48",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "fit_connect",
|
||||
"name": "FIT-Connect",
|
||||
"repository": "govoplan-fit-connect",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 2,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-fit-connect/issues/2",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "forms",
|
||||
"name": "Forms",
|
||||
"repository": "govoplan-forms",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 2,
|
||||
"number": 7,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-forms/issues/7",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "forms_runtime",
|
||||
"name": "Forms Runtime",
|
||||
"repository": "govoplan-forms-runtime",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 6,
|
||||
"number": 7,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-forms-runtime/issues/7",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "grants",
|
||||
"name": "Grants",
|
||||
"repository": "govoplan-grants",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-grants/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "helpdesk",
|
||||
"name": "Helpdesk",
|
||||
"repository": "govoplan-helpdesk",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-helpdesk/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "identity",
|
||||
"name": "Identity",
|
||||
"repository": "govoplan-identity",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 5,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-identity/issues/5",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "identity_trust",
|
||||
"name": "Identity Trust",
|
||||
"repository": "govoplan-identity-trust",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 4,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-identity-trust/issues/4",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "idm",
|
||||
"name": "IDM",
|
||||
"repository": "govoplan-idm",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 3,
|
||||
"number": 14,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-idm/issues/14",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "inspections",
|
||||
"name": "Inspections",
|
||||
"repository": "govoplan-inspections",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-inspections/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "learning",
|
||||
"name": "Learning",
|
||||
"repository": "govoplan-learning",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-learning/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "mail",
|
||||
"name": "Mail",
|
||||
"repository": "govoplan-mail",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 6,
|
||||
"number": 25,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-mail/issues/25",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "mandates",
|
||||
"name": "Mandates",
|
||||
"repository": "govoplan-mandates",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 2,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-mandates/issues/2",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "notifications",
|
||||
"name": "Notifications",
|
||||
"repository": "govoplan-notifications",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 3,
|
||||
"number": 7,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-notifications/issues/7",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "ops",
|
||||
"name": "Ops",
|
||||
"repository": "govoplan-ops",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 2,
|
||||
"number": 5,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-ops/issues/5",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "organizations",
|
||||
"name": "Organizations",
|
||||
"repository": "govoplan-organizations",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 4,
|
||||
"number": 9,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-organizations/issues/9",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "parties",
|
||||
"name": "Parties",
|
||||
"repository": "govoplan-parties",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 2,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-parties/issues/2",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "payments",
|
||||
"name": "Payments",
|
||||
"repository": "govoplan-payments",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 3,
|
||||
"number": 3,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-payments/issues/3",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "permits",
|
||||
"name": "Permits",
|
||||
"repository": "govoplan-permits",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-permits/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "policy",
|
||||
"name": "Policy",
|
||||
"repository": "govoplan-policy",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 3,
|
||||
"number": 14,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-policy/issues/14",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "poll",
|
||||
"name": "Poll",
|
||||
"repository": "govoplan-poll",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 5,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-poll/issues/5",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "portal",
|
||||
"name": "Portal",
|
||||
"repository": "govoplan-portal",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 2,
|
||||
"number": 4,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-portal/issues/4",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "postbox",
|
||||
"name": "Postbox",
|
||||
"repository": "govoplan-postbox",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 4,
|
||||
"number": 29,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-postbox/issues/29",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "procurement",
|
||||
"name": "Procurement",
|
||||
"repository": "govoplan-procurement",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-procurement/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "projects",
|
||||
"name": "Projects",
|
||||
"repository": "govoplan-projects",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 4,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-projects/issues/4",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "quick_access",
|
||||
"name": "Quick Access",
|
||||
"repository": "govoplan-quick-access",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 2,
|
||||
"number": 3,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-quick-access/issues/3",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "records",
|
||||
"name": "Records",
|
||||
"repository": "govoplan-records",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 4,
|
||||
"number": 10,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-records/issues/10",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "reporting",
|
||||
"name": "Reporting",
|
||||
"repository": "govoplan-reporting",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 3,
|
||||
"number": 11,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-reporting/issues/11",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "resources",
|
||||
"name": "Resources",
|
||||
"repository": "govoplan-resources",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-resources/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "rest",
|
||||
"name": "REST Connector",
|
||||
"repository": "govoplan-rest",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-rest/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "risk_compliance",
|
||||
"name": "Risk Compliance",
|
||||
"repository": "govoplan-risk-compliance",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 10,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-risk-compliance/issues/10",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "scheduling",
|
||||
"name": "Scheduling",
|
||||
"repository": "govoplan-scheduling",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 4,
|
||||
"number": 10,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-scheduling/issues/10",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "search",
|
||||
"name": "Search",
|
||||
"repository": "govoplan-search",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 4,
|
||||
"number": 6,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-search/issues/6",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "services",
|
||||
"name": "Services",
|
||||
"repository": "govoplan-services",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 2,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-services/issues/2",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "soap",
|
||||
"name": "SOAP Connector",
|
||||
"repository": "govoplan-soap",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-soap/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "tasks",
|
||||
"name": "Tasks",
|
||||
"repository": "govoplan-tasks",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 3,
|
||||
"number": 5,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-tasks/issues/5",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "templates",
|
||||
"name": "Templates",
|
||||
"repository": "govoplan-templates",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 8,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-templates/issues/8",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "tenancy",
|
||||
"name": "Tenancy",
|
||||
"repository": "govoplan-tenancy",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 2,
|
||||
"number": 7,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-tenancy/issues/7",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "tickets",
|
||||
"name": "Tickets",
|
||||
"repository": "govoplan-tickets",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 3,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-tickets/issues/3",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "transparency",
|
||||
"name": "Transparency",
|
||||
"repository": "govoplan-transparency",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-transparency/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "views",
|
||||
"name": "Views",
|
||||
"repository": "govoplan-views",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 3,
|
||||
"number": 6,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-views/issues/6",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "voting",
|
||||
"name": "Voting",
|
||||
"repository": "govoplan-voting",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 2,
|
||||
"number": 8,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-voting/issues/8",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "wiki",
|
||||
"name": "Wiki",
|
||||
"repository": "govoplan-wiki",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 1,
|
||||
"number": 2,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-wiki/issues/2",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "workflow",
|
||||
"name": "Workflow",
|
||||
"repository": "govoplan-workflow",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 6,
|
||||
"number": 17,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-workflow/issues/17",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "workflow_engine",
|
||||
"name": "Workflow Engine",
|
||||
"repository": "govoplan-workflow-engine",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 4,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-workflow-engine/issues/4",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "xrechnung",
|
||||
"name": "XRechnung",
|
||||
"repository": "govoplan-xrechnung",
|
||||
"kind": "manifest",
|
||||
"ui_source_count": 0,
|
||||
"number": 3,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-xrechnung/issues/3",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "catalog:govoplan-appointments",
|
||||
"name": "Appointments",
|
||||
"repository": "govoplan-appointments",
|
||||
"kind": "placeholder",
|
||||
"ui_source_count": 0,
|
||||
"number": 2,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-appointments/issues/2",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "catalog:govoplan-ledger",
|
||||
"name": "Ledger",
|
||||
"repository": "govoplan-ledger",
|
||||
"kind": "placeholder",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-ledger/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "catalog:govoplan-xoev",
|
||||
"name": "Xoev",
|
||||
"repository": "govoplan-xoev",
|
||||
"kind": "placeholder",
|
||||
"ui_source_count": 0,
|
||||
"number": 2,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-xoev/issues/2",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
},
|
||||
{
|
||||
"scope_id": "catalog:govoplan-xta-osci",
|
||||
"name": "Xta Osci",
|
||||
"repository": "govoplan-xta-osci",
|
||||
"kind": "placeholder",
|
||||
"ui_source_count": 0,
|
||||
"number": 1,
|
||||
"url": "https://git.add-ideas.de/GovOPlaN/govoplan-xta-osci/issues/1",
|
||||
"state_at_verification": "open",
|
||||
"operation": "created"
|
||||
}
|
||||
],
|
||||
"snapshot_date": "2026-09-08",
|
||||
"initial_review_status": "pending for every scope; this snapshot does not track subsequent issue progress"
|
||||
}
|
||||
Reference in New Issue
Block a user