Commit graph Crafter.Debug/interfaces/Crafter.Debug.Core.cppm
Author SHA1 Message Date
37e0d9b9ae
feat(discovery): find live instances across sandboxes; build info
Each app writes $HOME/.cache/crafter-debug/instances/<id>.json (0600,
in a 0700 directory) and holds an flock on <id>.lock while it lives.
Every `flatpak run` is its own pid namespace, so pids collide and can
neither name an instance nor tell whether it lives; a random id names
it and the lock says it lives, since flock works across sandboxes on
the shared filesystem. An app killed without its destructor leaves its
files with the lock free, and the next listing removes them. The lock
is created under a temporary name, locked, then renamed, as in
Crafter.Review's LifetimeLock, so it is never seen unlocked while its
app lives. Inside a Flatpak the record also carries the sandbox's
instance id (for `flatpak enter`) and the host pid of its init (to end
the whole sandbox from the host).

project.cpp now generates :BuildInfo per core variant: a hash of the
library's sources and the path of the client built with it. App and
client share the core, so they report the same id exactly when built
from the same sources; this is the safety net under building the
client in the same pass as the app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 01:56:31 +01:00
bd64c44fc5
feat(session): serve requests without blocking a thread, pause and step
The app's end of the connection, independent of the transport, which
reaches it through Detail::Exchange: one request's way back, safe from
any thread and never blocking.

- What needs only the session's own state (hello, status, list, log,
  pause, resume) is answered on the transport thread. What touches the
  app (calls, get, set, trace, screenshot) queues for the next Pump and
  runs on the app's thread between frames. Waits and steps reply from
  the Pump that sees them satisfied, events from the thread that emits
  them. No request ever holds a thread while it waits.
- A request whose timeout passes before Pump is answered Timeout and
  is guaranteed not to have run, so an agent never wonders whether a
  command went through; an Async result arrives on the Pump it is
  ready; requests left when the Session ends are answered ShuttingDown.
- Advance() for frame loops and Paused()/TakeSteps() for fixed-step
  loops hold what the app gates on them; pausing an app that gates
  nothing is refused instead of silently doing nothing. pause --when
  stops the frame its condition holds; pause --on-check stops before
  the next Advance in the frame a check fails, optionally raising
  SIGTRAP for an attached debugger.
- A wait that times out says what its condition's paths were; a log
  follower gets matching entries in order, from the backlog on, and is
  dropped when it cannot keep up.
- Request parameters go through Codec, so a mistyped request gets the
  same did-you-mean replies a mistyped command does. The session sets
  PR_SET_PTRACER_ANY so a debugger the agent starts can attach.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 01:53:15 +01:00
89a12bcd61
feat(core): Value, reflection, codecs and results, shared by app and client
Crafter.Debug.Core is what the app side and the crafter-debug client
both need, without the session:

- Value: a JSON value with its own parser and printer, so no consumer
  interface sees a JSON library. Integers stay integers and whole
  doubles stay doubles; NaN and the infinities, which JSON cannot
  spell, are written as strings rather than hidden, because a debugger
  must not lose a NaN; invalid UTF-8 is replaced so output always
  parses. Objects keep insertion order, the order an agent reads.
- Reflect: aggregate members and names through structured-binding
  packs and source_location, taken from Crafter.DB, plus scoped-enum
  names by probing a range of values. Self-tested with static_asserts
  so a compiler that changes function_name()'s shape fails the build.
- Codec<T>: encode, decode and describe for bool, integers, floating
  point, strings, enums, optional, vector, array, string-keyed maps,
  Value, Required<T> and every aggregate. Decode reports every
  problem in a call with its path and, for a typo, the likely intended
  name, and never throws: a bad call cannot take an app down, which a
  wrongly typed parameter could in 3DForts' hand-written from_json.
- Result, Error and Async: handler results, including ones that take
  frames to arrive, so callers need no ready:false polling.

project.cpp now builds Crafter.Debug.Core as its own library, used by
both the app library and the client.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 01:31:58 +01:00