Files
Agent-System-Dev/scripts/component-check.py
T
weichen 93ac63fb3d Compose immutable dependency sources and preserve branch transitions
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.
2026-10-13 17:18:07 +00:00

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)