1
0
Fork 0
Code Issues Pull requests Projects Releases 2 Packages Wiki Activity Actions Pages

Add deterministic client integration diagnostics

This commit is contained in:
Andraxion 2026-07-29 10:15:27 -04:00
parent eb9355b003
commit fb0df5e4a1
15 changed files with 6193 additions and 18 deletions

View file

@ -9,7 +9,9 @@ import webbrowser
from pathlib import Path
from .application import CanonicalApplicationService, GenericCanonicalApplier
from .client_config import CLIENT_NAMES, generate_client_configuration
from .context import compile_context
from .doctor import run_doctor
from .errors import DocForgeError
from .index import ProjectIndex
from .onboarding import assess_project, scaffold_project
@ -21,13 +23,33 @@ from .viewer_manager import ViewerManagerClient
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="docforge")
parser.add_argument("--project-root", type=Path, required=True)
parser.add_argument("--project-root", type=Path)
parser.add_argument(
"--diagnostics",
action="store_true",
help="Attach bounded request-local stage timings and counters",
)
commands = parser.add_subparsers(dest="command", required=True)
configure = commands.add_parser("configure")
configure.add_argument("client", choices=CLIENT_NAMES)
configure.add_argument("--project", type=Path, required=True)
configure.add_argument("--name")
configure.add_argument(
"--capability-mode",
choices=("read", "proposal", "application"),
default="read",
)
configure.add_argument("--proposal-writer")
configure.add_argument("--canonical-applier")
configure.add_argument("--no-ast", action="store_true")
configure.add_argument("--startup-timeout", type=int, default=30)
configure.add_argument("--tool-timeout", type=int, default=300)
configure.add_argument("--output", type=Path)
doctor = commands.add_parser("doctor")
doctor.add_argument("--client", choices=CLIENT_NAMES, required=True)
doctor.add_argument("--project", type=Path)
doctor.add_argument("--config", type=Path)
doctor.add_argument("--server-name")
onboard = commands.add_parser("onboard")
onboard.add_argument("--language", action="append", default=[])
onboard.add_argument("--scaffold", action="store_true")
@ -92,6 +114,33 @@ def _parser() -> argparse.ArgumentParser:
def _run(arguments: argparse.Namespace) -> dict[str, object]:
if arguments.command == "configure":
project = Project.open(arguments.project)
return generate_client_configuration(
project,
arguments.client,
server_name=arguments.name,
capability_mode=arguments.capability_mode,
proposal_writer=arguments.proposal_writer,
canonical_applier=arguments.canonical_applier,
no_ast=arguments.no_ast,
startup_timeout=arguments.startup_timeout,
tool_timeout=arguments.tool_timeout,
output=arguments.output,
)
if arguments.command == "doctor":
root = arguments.project or arguments.project_root or Path.cwd()
return run_doctor(
Project.open(root),
arguments.client,
config_path=arguments.config,
server_name=arguments.server_name,
)
if arguments.project_root is None:
raise DocForgeError(
"missing_project_root",
"This command requires --project-root",
)
if arguments.command == "onboard":
languages = tuple(arguments.language)
if arguments.scaffold:
@ -250,13 +299,14 @@ def main(argv: list[str] | None = None) -> int:
) as collector:
try:
result = _run(arguments)
code = 0
doctor_state = result.get("doctor_state")
code = 2 if doctor_state == "unhealthy" else (1 if doctor_state == "degraded" else 0)
except DocForgeError as error:
result = {"status": "error", "error": error.as_dict()}
code = 2
if collector is not None:
result["diagnostics"] = collector.as_dict(
outcome="ok" if code == 0 else "error",
outcome="ok" if result.get("status") == "ok" else "error",
)
print(json.dumps(result, sort_keys=True, indent=2))
return code