feat(devkit): add resumable workspace automation and UI review tooling
Dependency Audit / dependency-audit (push) Successful in 1m45s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Successful in 11m30s

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:
2026-09-09 02:03:17 +02:00
parent 14b19fbead
commit 2ffdb23f69
67 changed files with 17306 additions and 94 deletions
+270 -76
View File
@@ -1,13 +1,151 @@
#!/usr/bin/env bash
set -euo pipefail
# The JSON catalog is the only phase order/metadata authority. Check commands
# remain in the marked functions below; devkit invokes this script, not copies.
META_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
ROOT="${GOVOPLAN_CORE_ROOT:-$META_ROOT/../govoplan-core}"
FOCUSED_MODE=run
FOCUSED_PHASE=""
FOCUSED_JSON=0
focused_usage() {
echo "Usage: check-focused.sh [--phase ID] | --list-phases [--json]"
echo "Without --phase, run every canonical phase in catalog order (fail fast)."
}
while [[ $# -gt 0 ]]; do
case "$1" in
--phase)
if [[ "$FOCUSED_MODE" != run || -n "$FOCUSED_PHASE" || $# -lt 2 || -z "$2" || "$2" == --* ]]; then
echo "check-focused: --phase requires one ID and cannot be combined with listing." >&2
exit 2
fi
FOCUSED_PHASE="$2"
shift 2
;;
--list-phases)
if [[ "$FOCUSED_MODE" != run || -n "$FOCUSED_PHASE" ]]; then
echo "check-focused: duplicate or incompatible phase selection." >&2
exit 2
fi
FOCUSED_MODE=list
shift
;;
--json)
if [[ "$FOCUSED_JSON" == 1 ]]; then
echo "check-focused: duplicate --json." >&2
exit 2
fi
FOCUSED_JSON=1
shift
;;
--help|-h)
focused_usage
exit 0
;;
*)
echo "check-focused: unknown argument: $1" >&2
focused_usage >&2
exit 2
;;
esac
done
if [[ "$FOCUSED_JSON" == 1 && "$FOCUSED_MODE" != list ]]; then
echo "check-focused: --json is supported only with --list-phases." >&2
exit 2
fi
# Metadata-only operations need standard Python, not an installed product venv,
# Node, npm, a Core checkout, or any temporary/state directory.
FOCUSED_METADATA_PYTHON="$(command -v python3)" || {
echo "check-focused: Python 3 is required to read phase metadata." >&2
exit 127
}
FOCUSED_SELECTION="$(
PYTHONDONTWRITEBYTECODE=1 "$FOCUSED_METADATA_PYTHON" -I -S - \
"$META_ROOT/tools/checks/focused-phases.json" "$FOCUSED_MODE" "$FOCUSED_PHASE" "$FOCUSED_JSON" <<'PY'
import json
import os
from pathlib import Path
import re
import stat
import sys
try:
path = Path(sys.argv[1])
descriptor = os.open(path, os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0) | getattr(os, "O_NONBLOCK", 0))
with os.fdopen(descriptor, "rb") as handle:
status = os.fstat(handle.fileno())
if not stat.S_ISREG(status.st_mode) or status.st_size > 1024 * 1024:
raise ValueError("phase metadata must be a bounded regular file")
encoded = handle.read(1024 * 1024 + 1)
if len(encoded) > 1024 * 1024:
raise ValueError("phase metadata exceeds its size bound")
def unique(pairs):
result = {}
for key, value in pairs:
if key in result:
raise ValueError("duplicate phase metadata key")
result[key] = value
return result
catalog = json.loads(encoded, object_pairs_hook=unique)
if not isinstance(catalog, dict) or set(catalog) != {"schema_version", "phases"} or type(catalog["schema_version"]) is not int or catalog["schema_version"] != 1:
raise ValueError("unsupported phase metadata schema")
phases = catalog["phases"]
if not isinstance(phases, list) or not 1 <= len(phases) <= 32:
raise ValueError("phase catalog requires 132 definitions")
seen = set()
fields = {"id", "title", "cwd", "order_after", "depends_on", "resources", "outputs", "notes"}
for phase in phases:
if not isinstance(phase, dict) or set(phase) != fields:
raise ValueError("invalid phase metadata fields")
identity = phase["id"]
if not isinstance(identity, str) or not re.fullmatch(r"[a-z][a-z0-9-]{0,63}", identity) or identity in seen:
raise ValueError("invalid or duplicate phase ID")
if not isinstance(phase["title"], str) or not phase["title"].strip() or len(phase["title"]) > 256 or any(ord(char) < 32 for char in phase["title"]):
raise ValueError("invalid phase title")
if phase["cwd"] not in {"core", "meta", "core-webui", "access-webui"}:
raise ValueError("unsupported phase working directory")
for field in ("order_after", "depends_on", "resources", "outputs", "notes"):
values = phase[field]
if not isinstance(values, list) or len(values) > 64 or any(not isinstance(value, str) or not value or len(value) > 4096 or "\0" in value for value in values):
raise ValueError("invalid phase list: " + field)
if len(set(values)) != len(values):
raise ValueError("duplicate phase list value: " + field)
if (set(phase["order_after"]) | set(phase["depends_on"])) - seen:
raise ValueError("phase prerequisites must precede their consumer")
seen.add(identity)
mode, selected, as_json = sys.argv[2:]
if selected and selected not in seen:
raise ValueError("unknown phase: " + selected)
if mode == "list":
print(json.dumps(catalog, indent=2) if as_json == "1" else "\n".join(phase["id"] + "\t" + phase["title"] for phase in phases))
else:
print("\n".join(phase["id"] for phase in phases if not selected or phase["id"] == selected))
except (OSError, ValueError, TypeError, RecursionError) as exc:
print("check-focused: " + str(exc), file=sys.stderr)
raise SystemExit(2)
PY
)"
if [[ "$FOCUSED_MODE" == list ]]; then
printf '%s\n' "$FOCUSED_SELECTION"
exit 0
fi
focused_setup() {
WORKSPACE_ROOT="${GOVOPLAN_WORKSPACE_ROOT:-$(dirname "$META_ROOT")}"
export GOVOPLAN_WORKSPACE_ROOT="$WORKSPACE_ROOT"
ROOT="${GOVOPLAN_CORE_ROOT:-$WORKSPACE_ROOT/govoplan-core}"
ROOT="$(cd "$ROOT" && pwd)"
VENV_ROOT="${GOVOPLAN_VENV_ROOT:-$META_ROOT/.venv}"
PYTHON="${PYTHON:-$VENV_ROOT/bin/python}"
NODE="/home/zemion/.nvm/versions/node/v22.22.3/bin"
NPM="$NODE/npm"
NODE="$(command -v "${NODE:-node}")" || { echo "check-focused: Node is unavailable; run ./devkit doctor." >&2; exit 127; }
NPM="$(command -v "${NPM:-npm}")" || { echo "check-focused: npm is unavailable; run ./devkit doctor." >&2; exit 127; }
NODE_BIN="$(dirname "$NODE")"
WEBUI_BIN="$ROOT/webui/node_modules/.bin"
NPM_USERCONFIG="$(mktemp "${TMPDIR:-/tmp}/govoplan-npmrc.XXXXXXXX")"
@@ -19,7 +157,7 @@ trap 'rm -f "$NPM_USERCONFIG"' EXIT
exit 127
}
export PATH="$WEBUI_BIN:$NODE:$PATH"
export PATH="$WEBUI_BIN:$NODE_BIN:$PATH"
export NPM_CONFIG_USERCONFIG="$NPM_USERCONFIG"
export GOVOPLAN_NPM_USERCONFIG="$NPM_USERCONFIG"
unset npm_config_tmp NPM_CONFIG_TMP
@@ -27,28 +165,41 @@ unset npm_config_tmp NPM_CONFIG_TMP
# Validate the current sibling checkouts even when a newly added module has not
# yet been installed into an existing development virtualenv.
SOURCE_PYTHONPATH=""
for source_dir in "$META_ROOT"/../govoplan*/src; do
for source_dir in "$WORKSPACE_ROOT"/govoplan*/src; do
[ -d "$source_dir" ] || continue
SOURCE_PYTHONPATH="${SOURCE_PYTHONPATH:+$SOURCE_PYTHONPATH:}$source_dir"
done
export PYTHONPATH="${SOURCE_PYTHONPATH}${PYTHONPATH:+:$PYTHONPATH}"
}
focused_phase_preflight() {
# devkit-phase: preflight begin
cd "$ROOT"
GOVOPLAN_CORE_ROOT="$ROOT" PYTHON="$PYTHON" CHECK_TESTCLIENT_DEPRECATIONS=1 bash "$META_ROOT/tools/checks/check-dependency-hygiene.sh"
"$PYTHON" "$META_ROOT/tools/checks/check-contracts.py" --no-impact
PYTHONDONTWRITEBYTECODE=1 "$PYTHON" "$META_ROOT/tools/checks/check-manifest-shapes.py" --require-architecture
PYTHONDONTWRITEBYTECODE=1 "$PYTHON" "$META_ROOT/tools/checks/check-dsar-coverage.py"
"$NODE/node" "$META_ROOT/tests/test-jsx-value-imports.mjs"
"$NODE/node" "$META_ROOT/tools/checks/check-jsx-value-imports.mjs"
"$NODE/node" "$META_ROOT/../govoplan-files/webui/scripts/test-archive-client.mjs"
"$NODE" "$META_ROOT/tests/test-jsx-value-imports.mjs"
"$NODE" "$META_ROOT/tools/checks/check-jsx-value-imports.mjs"
"$NODE" "$META_ROOT/tests/test-heading-help.mjs"
"$NODE" "$META_ROOT/tools/checks/check-heading-help.mjs"
"$NODE" --test "$META_ROOT/tests/test-devkit-display-labels.mjs"
"$NODE" --test "$ROOT/webui/tests/component-test-runner.test.mjs"
"$NODE" "$WORKSPACE_ROOT/govoplan-files/webui/scripts/test-archive-client.mjs"
# devkit-phase: preflight end
}
focused_phase_tooling() {
# devkit-phase: tooling begin
cd "$META_ROOT"
"$PYTHON" tools/inventory/platform-interface-inventory.py --strict-declarations --strict-endpoints
"$PYTHON" tools/inventory/platform-interface-inventory.py --workspace-root "$WORKSPACE_ROOT" --strict-declarations --strict-endpoints
"$PYTHON" tools/repo/sync-module-package-workflows.py --check
"$PYTHON" tools/release/generate-developer-meta-package.py --check
"$PYTHON" tools/checks/check-webui-package-facades.py
"$PYTHON" -m unittest tests.test_webui_package_facades
"$PYTHON" -m pytest -q tests/test_ui_review_program.py "$META_ROOT"/tests/test_devkit_*.py
"$PYTHON" -m pytest -q tests/test_focused_phases.py
"$PYTHON" -m unittest tests.test_module_package_workflows tests.test_package_registry_release
"$PYTHON" -m unittest tests.test_deployment_installer tests.test_webui_release_dependency_retries
"$PYTHON" -m pytest -q tests/test_release_meta_source_tag.py tests/test_release_source_tag_batch.py tests/test_release_meta_preparation.py
@@ -59,14 +210,20 @@ cd "$META_ROOT"
"$PYTHON" -m unittest tests.test_configuration_package_artifacts
"$PYTHON" -m unittest tests.test_institutional_governance_journey
"$PYTHON" -m unittest tests.test_institutional_service_journey
# devkit-phase: tooling end
}
focused_phase_backend() {
# devkit-phase: backend begin
cd "$ROOT"
"$PYTHON" - <<'PY'
import ast
import pathlib
import os
import sys
repos_root = pathlib.Path("/mnt/DATA/git")
repos_root = pathlib.Path(os.environ["GOVOPLAN_WORKSPACE_ROOT"])
roots = [
repo / "src"
for repo in sorted(repos_root.glob("govoplan*"))
@@ -107,107 +264,127 @@ PY
"$PYTHON" -m unittest tests.test_ownership_history_migration tests.test_ownership tests.test_ownership_api
"$PYTHON" -m unittest tests.test_navigation_preferences tests.test_api_smoke.ApiSmokeTests.test_navigation_separator_layout_survives_system_tenant_and_personal_saves
"$PYTHON" -m pytest -q \
/mnt/DATA/git/govoplan-files/tests/test_managed_archives.py \
/mnt/DATA/git/govoplan-files/tests/test_archive_work.py \
/mnt/DATA/git/govoplan-files/tests/test_archive_staging.py \
/mnt/DATA/git/govoplan-files/tests/test_upload_response_batching.py \
/mnt/DATA/git/govoplan-files/tests/test_archive_performance.py
"${WORKSPACE_ROOT}/govoplan-files/tests/test_managed_archives.py" \
"${WORKSPACE_ROOT}/govoplan-files/tests/test_archive_work.py" \
"${WORKSPACE_ROOT}/govoplan-files/tests/test_archive_staging.py" \
"${WORKSPACE_ROOT}/govoplan-files/tests/test_upload_response_batching.py" \
"${WORKSPACE_ROOT}/govoplan-files/tests/test_archive_performance.py"
"$PYTHON" -m pytest -q \
/mnt/DATA/git/govoplan-files/tests/test_archive_workers.py \
/mnt/DATA/git/govoplan-files/tests/test_archive_inspection_bounds.py \
/mnt/DATA/git/govoplan-files/tests/test_archives.py
"$PYTHON" -m pytest -q /mnt/DATA/git/govoplan-access/tests/test_external_function_mapping_migration.py
"$PYTHON" -m pytest -q /mnt/DATA/git/govoplan-access/tests
"$PYTHON" -m pytest -q /mnt/DATA/git/govoplan-templates/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-connectors/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-datasources/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-dataflow/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-workflow-engine/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-workflow/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-views/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-quick-access/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-dashboard/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-postbox/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-portal/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-payments/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-forms/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-forms-runtime/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-cases/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-committee/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-voting/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-approvals/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-identity-trust/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-encryption/tests
"$PYTHON" -m pytest -q /mnt/DATA/git/govoplan-wiki/tests
"${WORKSPACE_ROOT}/govoplan-files/tests/test_archive_workers.py" \
"${WORKSPACE_ROOT}/govoplan-files/tests/test_archive_inspection_bounds.py" \
"${WORKSPACE_ROOT}/govoplan-files/tests/test_archives.py"
"$PYTHON" -m pytest -q "${WORKSPACE_ROOT}/govoplan-access/tests/test_external_function_mapping_migration.py"
"$PYTHON" -m pytest -q "${WORKSPACE_ROOT}/govoplan-access/tests"
"$PYTHON" -m pytest -q "${WORKSPACE_ROOT}/govoplan-templates/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-connectors/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-datasources/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-dataflow/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-workflow-engine/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-workflow/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-views/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-quick-access/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-dashboard/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-postbox/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-portal/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-payments/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-forms/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-forms-runtime/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-cases/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-committee/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-voting/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-approvals/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-identity-trust/tests"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-encryption/tests"
"$PYTHON" -m pytest -q "${WORKSPACE_ROOT}/govoplan-wiki/tests"
"$PYTHON" -m pytest -q \
/mnt/DATA/git/govoplan-campaign/tests/test_approval_gate.py \
/mnt/DATA/git/govoplan-campaign/tests/test_editor_state_security.py \
/mnt/DATA/git/govoplan-campaign/tests/test_mail_profile_boundary.py \
/mnt/DATA/git/govoplan-campaign/tests/test_independent_configuration_repairs.py \
/mnt/DATA/git/govoplan-campaign/tests/test_incremental_review_persistence.py \
/mnt/DATA/git/govoplan-campaign/tests/test_reviewed_build_mock.py \
/mnt/DATA/git/govoplan-campaign/tests/test_delivery_policy_settings.py \
/mnt/DATA/git/govoplan-campaign/tests/test_synchronous_delivery_policy.py \
/mnt/DATA/git/govoplan-campaign/tests/test_workerless_recovery.py \
/mnt/DATA/git/govoplan-campaign/tests/test_imap_batch_integration.py \
/mnt/DATA/git/govoplan-campaign/tests/test_testbed_claim_recovery.py \
/mnt/DATA/git/govoplan-campaign/tests/test_campaign_optimistic_concurrency.py \
/mnt/DATA/git/govoplan-campaign/tests/test_archive_encryption_governance.py \
/mnt/DATA/git/govoplan-policy/tests/test_campaign_archive_encryption.py \
/mnt/DATA/git/govoplan-policy/tests/test_archive_encryption_api.py
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_approval_gate.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_editor_state_security.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_mail_profile_boundary.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_independent_configuration_repairs.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_incremental_review_persistence.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_reviewed_build_mock.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_delivery_policy_settings.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_synchronous_delivery_policy.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_workerless_recovery.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_imap_batch_integration.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_testbed_claim_recovery.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_campaign_optimistic_concurrency.py" \
"${WORKSPACE_ROOT}/govoplan-campaign/tests/test_archive_encryption_governance.py" \
"${WORKSPACE_ROOT}/govoplan-policy/tests/test_campaign_archive_encryption.py" \
"${WORKSPACE_ROOT}/govoplan-policy/tests/test_archive_encryption_api.py"
"$PYTHON" "$META_ROOT/tools/checks/check-datasource-composition.py"
"$PYTHON" "$META_ROOT/tools/checks/check-sanctions-screening-composition.py"
"$PYTHON" -m pytest -q /mnt/DATA/git/govoplan-mail/tests/test_campaign_protocol_authorization.py /mnt/DATA/git/govoplan-mail/tests/test_campaign_imap_batch.py
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-mail/tests
"$PYTHON" -m pytest -q "${WORKSPACE_ROOT}/govoplan-mail/tests/test_campaign_protocol_authorization.py" "${WORKSPACE_ROOT}/govoplan-mail/tests/test_campaign_imap_batch.py"
"$PYTHON" -m unittest discover -s "${WORKSPACE_ROOT}/govoplan-mail/tests"
"$PYTHON" -m unittest tests.test_api_smoke.ApiSmokeTests.test_mailbox_message_listing_reports_total_count
"$PYTHON" -m unittest \
tests.test_api_smoke.ApiSmokeTests.test_managed_attachment_patterns_preview_build_and_mock_send \
tests.test_api_smoke.ApiSmokeTests.test_reports_and_job_review_are_scoped_to_the_selected_version \
tests.test_api_smoke.ApiSmokeTests.test_worker_loss_becomes_unknown_and_requires_reconciliation_before_retry
# devkit-phase: backend end
}
focused_phase_core_ui() {
# devkit-phase: core-ui begin
cd "$ROOT/webui"
"$NPM" run test:api-client-cache
"$NPM" run test:auth-action-state
"$NPM" run test:dependency-security
"$NPM" run test:layout-primitives
"$NPM" run test:mail-components
"$NPM" run test:components -- layout-primitives page-layout data-grid-actions mail-components
"$NODE" --test tests/breadcrumb-bar.test.mjs
"$NPM" run test:module-capabilities
"$NPM" run test:module-permutations
"$NPM" run test:conformance
# devkit-phase: core-ui end
}
cd /mnt/DATA/git/govoplan-access/webui
focused_phase_module_builds() {
# devkit-phase: module-builds begin
cd "$ROOT/webui"
"$NPM" run test:module-permutations
# devkit-phase: module-builds end
}
focused_phase_browser() {
# devkit-phase: browser begin
cd "$ROOT/webui"
"$NPM" run test:conformance
# devkit-phase: browser end
}
focused_phase_module_ui() {
# devkit-phase: module-ui begin
cd "${WORKSPACE_ROOT}/govoplan-access/webui"
"$NPM" run test:passwords
"$WEBUI_BIN/tsc" -p /mnt/DATA/git/govoplan-payments/webui/tsconfig.json
"$WEBUI_BIN/tsc" -p "${WORKSPACE_ROOT}/govoplan-payments/webui/tsconfig.json"
cd /mnt/DATA/git/govoplan-payments/webui
cd "${WORKSPACE_ROOT}/govoplan-payments/webui"
"$NPM" run test:interface-pattern
cd /mnt/DATA/git/govoplan-dataflow/webui
cd "${WORKSPACE_ROOT}/govoplan-dataflow/webui"
"$NPM" run test:structure
cd /mnt/DATA/git/govoplan-datasources/webui
cd "${WORKSPACE_ROOT}/govoplan-datasources/webui"
"$NPM" run typecheck
cd /mnt/DATA/git/govoplan-workflow/webui
cd "${WORKSPACE_ROOT}/govoplan-workflow/webui"
"$NPM" run typecheck
cd /mnt/DATA/git/govoplan-dashboard/webui
cd "${WORKSPACE_ROOT}/govoplan-dashboard/webui"
"$NPM" run test:dashboard-layout
cd /mnt/DATA/git/govoplan-approvals/webui
cd "${WORKSPACE_ROOT}/govoplan-approvals/webui"
"$NPM" run test:workspace-layout
cd /mnt/DATA/git/govoplan-postbox/webui
cd "${WORKSPACE_ROOT}/govoplan-postbox/webui"
"$NPM" run test:ui-structure
cd /mnt/DATA/git/govoplan-mail/webui
cd "${WORKSPACE_ROOT}/govoplan-mail/webui"
"$NPM" run test:mail-ui
cd /mnt/DATA/git/govoplan-files/webui
cd "${WORKSPACE_ROOT}/govoplan-files/webui"
"$NPM" run test:managed-archive
cd /mnt/DATA/git/govoplan-campaign/webui
cd "${WORKSPACE_ROOT}/govoplan-campaign/webui"
"$NPM" run test:policy-ui
"$NPM" run test:template-preview
"$NPM" run test:review-workflow
@@ -215,8 +392,25 @@ cd /mnt/DATA/git/govoplan-campaign/webui
"$NPM" run test:campaign-collaboration
"$NPM" run test:campaign-work
cd /mnt/DATA/git/govoplan-policy/webui
cd "${WORKSPACE_ROOT}/govoplan-policy/webui"
"$NPM" run test:archive-encryption
cd /mnt/DATA/git/govoplan-wiki/webui
cd "${WORKSPACE_ROOT}/govoplan-wiki/webui"
"$NPM" run test:interface-pattern
# devkit-phase: module-ui end
}
# Validate every selected implementation before setup can create a temp npmrc.
while IFS= read -r phase_id; do
if ! declare -F "focused_phase_${phase_id//-/_}" >/dev/null; then
echo "check-focused: missing phase implementation: $phase_id" >&2
exit 2
fi
done <<< "$FOCUSED_SELECTION"
while IFS= read -r phase_id; do
(
focused_setup
"focused_phase_${phase_id//-/_}"
)
done <<< "$FOCUSED_SELECTION"