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:
Executable
+133
@@ -0,0 +1,133 @@
|
||||
"""Recorded documentation checks built from existing owning-module contracts."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import uuid
|
||||
|
||||
from .catalog import stage
|
||||
from .common import state_root
|
||||
from .workspace import load_project, selected_repositories
|
||||
|
||||
|
||||
LIMITATIONS = [
|
||||
"Static baseline, marker coverage and known display slots do not prove complete workflow or linguistic coverage.",
|
||||
"Computed labels, configured documentation providers and runtime module/permission combinations still require manual review.",
|
||||
"Audit findings do not edit documentation, translate text, publish evidence or close a review issue.",
|
||||
]
|
||||
|
||||
|
||||
def build_doc_stages(args) -> list[dict]:
|
||||
workspace = Path(args.workspace_root).resolve()
|
||||
project = load_project(workspace, getattr(args, "project", None))
|
||||
if getattr(args, "project", None):
|
||||
raise ValueError(
|
||||
"The docs audit currently targets GovOPlaN manifest/locale contracts. Register another project's documentation checks in its check profiles."
|
||||
)
|
||||
selected = selected_repositories(
|
||||
project, getattr(args, "repo", []), changed=getattr(args, "changed", False)
|
||||
)
|
||||
if getattr(args, "changed", False) and not selected:
|
||||
return []
|
||||
meta = next(repo.path for repo in project.repositories if repo.name == "govoplan")
|
||||
core = next(
|
||||
repo.path for repo in project.repositories if repo.name == "govoplan-core"
|
||||
)
|
||||
output = (
|
||||
state_root(workspace, getattr(args, "state_dir", None))
|
||||
/ "artifacts"
|
||||
/ f"docs-{uuid.uuid4().hex}"
|
||||
)
|
||||
reason = "Reuse the existing owning-module documentation and translation checks"
|
||||
labels = [
|
||||
"{node}",
|
||||
str(meta / "tools/devkit/audit-display-labels.mjs"),
|
||||
"--workspace-root",
|
||||
str(workspace),
|
||||
]
|
||||
for repo in selected:
|
||||
labels.extend(["--repo", repo.name])
|
||||
stages = [
|
||||
stage(
|
||||
"docs.manifests",
|
||||
"Static user/admin documentation and manifest contracts",
|
||||
[
|
||||
"{python}",
|
||||
str(meta / "tools/checks/check-manifest-shapes.py"),
|
||||
"--workspace-root",
|
||||
str(workspace),
|
||||
"--require-architecture",
|
||||
],
|
||||
meta,
|
||||
reason=reason,
|
||||
timeout_seconds=600,
|
||||
),
|
||||
stage(
|
||||
"docs.interface-inventory",
|
||||
"Existing EN/DE markers, high-risk help and interface declarations",
|
||||
[
|
||||
"{python}",
|
||||
str(meta / "tools/inventory/platform-interface-inventory.py"),
|
||||
"--workspace-root",
|
||||
str(workspace),
|
||||
"--strict",
|
||||
"--strict-declarations",
|
||||
"--strict-endpoints",
|
||||
"--output-dir",
|
||||
str(output),
|
||||
],
|
||||
meta,
|
||||
reason="Shared inventory remains workspace-wide; --repo narrows only the additional plain-label audit",
|
||||
timeout_seconds=600,
|
||||
),
|
||||
stage(
|
||||
"docs.translation-structure",
|
||||
"Existing translation key/structural-value guard",
|
||||
["{node}", str(core / "webui/scripts/audit-i18n-structural.mjs")],
|
||||
core / "webui",
|
||||
reason=reason,
|
||||
),
|
||||
stage(
|
||||
"docs.plain-display-labels",
|
||||
"Plain display labels and owning catalog registration",
|
||||
labels,
|
||||
meta,
|
||||
reason="Supplement the marker inventory with known display slots; dynamic cases are review candidates",
|
||||
timeout_seconds=600,
|
||||
),
|
||||
]
|
||||
# These constraints belong to the saved evidence, not only the immediate
|
||||
# CLI response. The publisher already validates bounded coverage_notes.
|
||||
stages[0]["coverage_notes"] = list(LIMITATIONS)
|
||||
return stages
|
||||
|
||||
|
||||
def audit(args) -> dict:
|
||||
from .runner import run_checks
|
||||
|
||||
result = run_checks(args, build_doc_stages(args))
|
||||
result["limitations"] = list(LIMITATIONS)
|
||||
result.setdefault("_exit_code", 0)
|
||||
summary = result.setdefault("summary", [])
|
||||
summary.extend(note for note in LIMITATIONS if note not in summary)
|
||||
return result
|
||||
|
||||
|
||||
def register(subparsers) -> None:
|
||||
docs = subparsers.add_parser(
|
||||
"docs", help="Audit existing documentation and translation contracts"
|
||||
)
|
||||
commands = docs.add_subparsers(dest="docs_command", required=True)
|
||||
command = commands.add_parser(
|
||||
"audit", help="Run recorded checks; never edit or generate translations"
|
||||
)
|
||||
command.add_argument(
|
||||
"--repo",
|
||||
action="append",
|
||||
default=[],
|
||||
help="Repository/alias for plain-label checks; shared checks stay workspace-wide",
|
||||
)
|
||||
command.add_argument("--changed", action="store_true")
|
||||
command.add_argument("--jobs", type=int, default=2)
|
||||
command.add_argument("--dry-run", action="store_true")
|
||||
command.set_defaults(handler=audit, profile="docs")
|
||||
Reference in New Issue
Block a user