feat: self-report a classified exiting{reason} on any startup/load failure - #165
Merged
Conversation
…ilure run() now wraps its whole body (model/architecture/draft/MTP-assistant load, chat-template probe, port bind) in one top-level catch instead of per-site handling. classifyExitReason(_:phase:) maps the thrown error plus a LoadPhase tracked across the load path to one of the daemon's closed reason values: port_conflict (EADDRINUSE on bind), model_load_failed (any load-phase failure, including MalformedChatTemplate), out_of_memory (identifiable allocation failures — most MLX/Metal OOM instead fatalErrors before reaching this path), and binary_error as the catch-all. The existing reason:"requested" SIGTERM/SIGINT path is untouched. Every event now also carries a short `detail` string. Verified manually against a nonexistent model path (model_load_failed) and an already-bound port (port_conflict); docs/AEGIS_INTEGRATION.md documents the reason set. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
run()now wraps its entire startup/load path (architecture probe, main model load,--draft-modelload,--mtp-assistant-modelload, chat-template probe, HTTP port bind) in one top-leveldo/catchinstead of leaving those nine throw sites unhandled.{"event":"exiting","reason":<snake_case>,"detail":<short message>}via the existingemitEvent, then rethrows — process exit status is unchanged.classifyExitReason(_:phase:)maps the error + aLoadPhasetracked through the load path to one of the daemon's closedreasonvalues (daemon/spec/engine-protocol.mdin Aegis-AI):port_conflict—IOErrorwitherrnoCode == EADDRINUSEwhile binding.model_load_failed— any failure while inarchitectureProbe/mainModelLoad/draftModelLoad/mtpAssistantLoad/chatTemplateProbe, or anyMalformedChatTemplateregardless of phase.out_of_memory— allocation failures identifiable from the error's message text (most MLX/Metal OOM instead callsfatalErrorbefore reaching this path — out of scope, noted in the doc).binary_error— catch-all for anything else.reason:"requested"SIGTERM/SIGINT path is untouched.docs/AEGIS_INTEGRATION.mddocuments the full reason set and the newdetailfield.Test plan
swift build -c release— clean build, no new warnings from this change.swift test --filter ExitReasonClassificationTests— 6/6 passing, new unit coverage forclassifyExitReason.--modelpath →{"event":"exiting","reason":"model_load_failed","detail":"fileNotFound(\"main\")"}.--portalready bound (IPv4 127.0.0.1) →{"event":"exiting","reason":"port_conflict","detail":"bind(descriptor:ptr:bytes:): Address already in use) (errno: 48)"}.reason:"requested"SIGTERM/SIGINT path is unchanged.🤖 Generated with Claude Code