Why: Replace repeated submodule source pointers with consumer-owned language versions and fixed application sources, keeping independent repository edits and existing branches intact. Evidence: SELF task receipts contain startup/sync evidence, real Go and npm consumption, Native overlay/unlink, safe transition/ref preservation, credential boundary and historical build regressions. Exact committed full composition and RDM checks follow this checkpoint; formal acceptance and GATE CI remain pending. Impact: Add isolated build/test composition, source provenance and safe owner refresh, adapt governance and service build callers, remove replaced index links while retaining original Git metadata, and adopt reusable dependency standards. Refs: Documents approved dependency-workspace r1/R1-R15 and U1-U7 implementation plan; feature/dependency-workspace task card.
116 lines
6.2 KiB
Python
116 lines
6.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Prepare selected fixed sources and run explicitly local component checks."""
|
|
import argparse
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
|
|
from workspace.cli import Workspace, process_environment
|
|
from workspace.common import WorkspaceError
|
|
from workspace.state import State
|
|
|
|
SINGLE = {"test-backend": "Agent-System-Backend", "test-backend-pg": "Agent-System-Backend",
|
|
"test-core": "Agent-System-Core", "test-agentcmd": "Agent-Command",
|
|
"test-frontend": "Agent-System-Frontend", "test-ui": "Agent-System-UI",
|
|
"test-multi-instance": "Agent-System-Backend", "eval-deliverables": "Agent-System-Backend",
|
|
"dev-backend": "Agent-System-Backend", "dev-frontend": "Agent-System-Frontend"}
|
|
|
|
|
|
def run(command, cwd, env):
|
|
print("[component-check] " + " ".join(map(str, command)), flush=True)
|
|
result = subprocess.run(command, cwd=cwd, env=env)
|
|
if result.returncode:
|
|
raise WorkspaceError(f"local component command failed ({result.returncode})")
|
|
|
|
|
|
def prepare_local_source(workspace, component):
|
|
"""Repeated local npm checks may reuse only recognized generated directories."""
|
|
record = workspace.state.data["components"].get(component["id"])
|
|
path = workspace.root / component["path"]
|
|
if record and record.get("mode") == "versioned" and (path / "package.json").is_file():
|
|
actual = workspace.git.safe(path, component["repo"], clean=False)
|
|
commit, source = workspace.baseline(component)
|
|
generated = ("node_modules/", "dist/")
|
|
if actual["head"] != commit or actual["branch"] or actual["changes"] or any(not name.startswith(generated) for name in actual["ignored"]):
|
|
raise WorkspaceError(f"local source or ignored unique files require owner coordination: {component['id']}")
|
|
record.update(baseline=commit, source=source)
|
|
workspace.state.save()
|
|
return
|
|
workspace.prepare_one(component)
|
|
|
|
|
|
def check(root, target, overlay):
|
|
root = root.resolve()
|
|
if target in ("test-backend-pg", "test-multi-instance") and not os.environ.get("AGENT_PG_TEST_DSN"):
|
|
raise WorkspaceError("AGENT_PG_TEST_DSN required; real PostgreSQL gate is not skipped")
|
|
if target == "test-backend-pg" and not os.environ.get("AGENT_REDIS_TEST_ADDR"):
|
|
raise WorkspaceError("AGENT_REDIS_TEST_ADDR required; real Redis gate is not skipped")
|
|
workspace = Workspace(root)
|
|
names = [SINGLE[target]] if target in SINGLE else (["Agent-Native", "Agent-Intent", "Agent-Squad"] if target == "test-libs" else ["Agent-System-Backend", "Agent-System-Frontend"])
|
|
selected = [workspace.manifest.select(name)[0] for name in names]
|
|
with workspace.state.operation():
|
|
workspace.state = State(root)
|
|
if any(component["role"] in ("go-library", "npm-library") for component in selected):
|
|
for component in workspace.manifest.select(fixed=True):
|
|
if component["role"] == "application":
|
|
prepare_local_source(workspace, component)
|
|
for component in selected:
|
|
prepare_local_source(workspace, component)
|
|
workspace.snapshot()
|
|
env = process_environment(root)
|
|
if overlay:
|
|
workspace.go.check_owned()
|
|
if not workspace.state.data.get("go_work") or not (root / "go.work").is_file():
|
|
raise WorkspaceError("LOCAL_OVERLAY=1 requires a registered go.work; use component-edit first")
|
|
env["GOWORK"] = str(root / "go.work")
|
|
else:
|
|
env["GOWORK"] = "off"
|
|
print(f"[component-check] local developer sources; GOWORK={env['GOWORK']}; registered edit branches and unsaved code retained", flush=True)
|
|
paths = {component["id"]: root / component["path"] for component in selected}
|
|
if target == "dev":
|
|
print("Backend: make dev-backend [LOCAL_OVERLAY=1]\nFrontend: make dev-frontend\nPrivate module transport is scoped to those processes.")
|
|
return
|
|
path = paths[names[0]]
|
|
if target == "dev-backend":
|
|
run(["go", "run", "./cmd/agent-system", "serve", "--addr", "127.0.0.1:8787", "--data", str(root / "data"), "--plugins", str(root / "plugins")], path, env)
|
|
elif target == "dev-frontend":
|
|
run(["npm", "ci", "--ignore-scripts", "--no-fund", "--no-audit"], path, env)
|
|
run(["npm", "run", "dev"], path, env)
|
|
elif target == "test-multi-instance":
|
|
suite = root / "tests/integration/multi-instance"
|
|
binary = suite / ".build/agent-system"
|
|
binary.parent.mkdir(parents=True, exist_ok=True)
|
|
run(["go", "build", "-mod=readonly", "-o", str(binary), "./cmd/agent-system"], path, env | {"CGO_ENABLED": "0"})
|
|
run(["go", "test", "-mod=readonly", "-count=1", "-timeout=15m", "."], suite, env | {"AGENT_BIN": str(binary)})
|
|
elif target == "eval-deliverables":
|
|
run(["go", "test", "-mod=readonly", "./eval/", "./internal/quality/", "-count=1"], path, env)
|
|
elif target in ("test-frontend", "test-ui"):
|
|
run(["npm", "ci", "--ignore-scripts", "--no-fund", "--no-audit"], path, env)
|
|
if target == "test-ui":
|
|
run(["npm", "exec", "--offline", "--", "tsc", "--noEmit"], path, env)
|
|
run(["npm", "exec", "--offline", "--", "vitest", "run"], path, env)
|
|
run(["node", "scripts/check-knip.mjs"], path, env)
|
|
else:
|
|
for component in selected:
|
|
source = paths[component["id"]]
|
|
modules = component.get("modules", []) if target == "test-libs" else [{"directory": "."}]
|
|
for module in modules:
|
|
directory = source / module.get("directory", ".")
|
|
if target in ("test-libs", "test-agentcmd"):
|
|
run(["go", "vet", "-mod=readonly", "./..."], directory, env)
|
|
run(["go", "test", "-mod=readonly", "-count=1", "./..."], directory, env)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1])
|
|
parser.add_argument("--target", choices=(*SINGLE, "test-libs", "dev"), required=True)
|
|
parser.add_argument("--overlay", action="store_true")
|
|
args = parser.parse_args()
|
|
try:
|
|
check(args.root, args.target, args.overlay)
|
|
except (WorkspaceError, OSError, ValueError) as error:
|
|
print(f"component-check: {error}", file=sys.stderr)
|
|
raise SystemExit(1)
|