Permit Node/libuv read-only type inspection only on committed child
descriptors while offline socket and connect remain denied.
Recheck queued input after audit and around response release. Late
pipelined frames now poison the channel instead of crossing the gate.
Combine maintainer/wallet-status-and-apple-repairs (18e75af8) with
maintainer/guest-channel-layer (00d7c473) into a single validated
integration branch for Ghost deployment testing.
Merge resolution decisions:
- Apple container runtime (the known conflict zone) auto-merged
textually and was verified semantically against both parents:
the maintainer hard-disable survives (lifecycle_operational()
returns false unconditionally, apple_container_session_runtime.hpp),
the sampler/finalizer jthread lifecycle seam and the finalizer
catch-all well-formed terminal state (a96ab1e) are intact, and
null_terminated=false strict_json_options is preserved. Velinus's
observation-intent integration lands adapted on the repaired base:
prepare_observation_service is only reachable from start(), which
denies before side effects when the lifecycle is disabled, so the
observation service never constructs on the disabled Apple path.
The gated test from PR #25 (every control method refuses before
side effect; record counts unchanged) survives.
- GLOVE_GUEST_OBSERVATION_* env names kept; observation socket/token
volumes still mount only when observation_service->active().
- guest_channel layer, host-registered schema admission
(channel_descriptor/channel_host), SO_PEERCRED/LOCAL_PEERCRED, LRU
replay cache, bounded retry, fail-closed recovery, and
channel_identifier_grammar.hpp land as-is; session_registry files
did not conflict with PR #24's side.
- Wallet status files: PR #25's delta did not touch them, so the
harness-neutral renames (wallet_status_projection_channel) stand
unchanged.
Validation (umask 0022): dev/asan/tsan presets build clean and
CTest 80/80 each (control_apple_container_session_runtime
env-gated/skipped as expected); clang-format (llvm@22) applied to
changed sources; git diff --check clean. No push.
Generalizes the PR #23 guest observation plumbing into a schema-agnostic
specialized-channel layer while keeping all harness policy out of core.
Generalized admission (F2/HIGH):
- New channel_descriptor/channel_host interface (include/glove/control/
guest_channel.hpp): hosts register {channel_id, schema_id,
body_validator, bounds{max_items, max_body_bytes, max_ttl_ms,
max_skew_ms}, on_exchange} at registry construction; core keeps only
structural invariants (identifier charset, digest hex, TTL/skew
arithmetic, capacity, idempotency) and delegates body semantics to
registered validators.
- The closed two-schema check in session_registry internals is removed:
glove_observation_schema, glove_sxxx_proposal_* constants and the
fixed SXXX digest move out of session_registry_impl.hpp. The Sage
schemas are now registered by the harness adapter
(apple_detail::sage_guest_channel_host) and gloved_main wires the host
into the registry; schema strings appear only in harness-adapter and
test-fixture registration examples.
- enqueue_observation_intent binds intents to the session's PARSED
runtime_id; the hardcoded sage_guest_runtime equality checks are
removed from session_registry.cpp, session_registry_recovery.cpp and
valid_record_shape. Replay of a now-unregistered schema fails closed
(open_or_create rejects stores carrying unadmitted intents), and
enqueue without an admission table is rejected. The observation
socket server takes runtime_id from configuration instead of
hardcoding "sage-guest". The observation body hash domain becomes the
harness-neutral "glove.observation-body.v1" (pre-merge delta; no
on-disk compatibility is preserved).
Recovery fix (F1/HIGH):
- same_session_snapshot now neutralizes state, running_at_ms and
policy_revision before comparing frozen intent/disposition snapshots
against the bound session record, so lifecycle progression and policy
revision advances never read as a binding crossing; every other
frozen-field difference still does. Exposed for tests. Regression
tests cover running->stopping and stopping->exited transitions plus a
late post-exit disposition end to end (destroy/reopen), and a
snapshot-identity unit test pins the neutralization (and proves
non-neutralized fields still cross). Note: an empirical probe showed
the previously-claimed failure does not reproduce under ordered
journal replay because intent/disposition records freeze the session
record they were appended from; the neutralization is applied as the
defensive fix the memo requires and is now pinned by tests.
Hardening:
- F3: peer-uid verification (SO_PEERCRED / LOCAL_PEERCRED) on observation
socket accepts, configurable expected uid, rejecting unexpected peers
before any frame is read.
- F4: the replay cache is a bounded LRU (configurable capacity), so the
old fixed 1024 cap can no longer permanently kill the channel; the
durable registry remains the authoritative idempotency layer.
- F5: transient wait/accept errors (EINTR/EAGAIN/ECONNABORTED/EMFILE/
ENFILE/ENOBUFS/ENOMEM) are retried inside serve_one_for with a bounded
backoff ladder; only persistent or fatal errors surface. The Apple
worker loop absorbs persistent failures up to a consecutive-failure
bound and emits an audit event (new audit action "observation") on
repeated failures instead of dying on the first hiccup.
- F6: env/mount names generalized to GLOVE_GUEST_OBSERVATION_SOCKET /
GLOVE_GUEST_OBSERVATION_TOKEN_FILE and the in-container token path to
/home/agent/.glove-observation-token (Apple runtime, docs).
Apple boundary: the soft lifecycle_operational() definition is unchanged;
the lifecycle-disabled lane now additionally asserts start_session/
stop_session deny with method_not_found and leave the registry untouched
(denial before side effects; the observation service only constructs
inside a lifecycle-gated start).
Docs: architecture.md and session-policy.md describe the guest
specialized-channel admission model and the peer-uid/env naming.
Validation (umask 0022):
- cmake --preset dev/asan/tsan + build + ctest: 100% (76/76) in each
configuration; asan/tsan are warnings-as-errors builds.
- git diff --check clean; changed files clang-formatted with Homebrew
llvm@22 against the repo .clang-format.
- No fuzz target exists for the queue/registry (fuzz/ covers plans,
bundles, manifests, MCP codec, jsonpath only), so no fuzz corpus run.
- control_remote_validation_executor is a pre-existing load-sensitive
sleep-race test; it flakes identically on the unmodified pr23-head
baseline under CPU load (verified 1/6 both trees) and always passes
isolated.
Files: 23 changed (+~1500/-~360), including new guest_channel.{hpp,cpp}.
Signed-off-by: 0xkite <me@hack4kites.dev>
Preserve known non-skill metadata in projection commitments, reject duplicate and oversized bundles, close Codex exec grammar ambiguity, and keep raw-bundle requirements explicit. Keep layer-2 Sage materialization tests out of this layer.
Validated by the exact layer-1 build and 75-test suite; Apple lifecycle remains a separately skipped layer-2 concern.
Signed-off-by: 0xkite <me@hack4kitesdev.dev>
Mixed libraries were failing start because any non-skill entry aborted the
projection. The managed sandbox bypass also has to sit after `exec` so
headless Codex can run inside Glove.
Model and PTY cannot self-report pass or failure. Glove now runs
each refinement-eval-v1 session through a declarative evaluator that
checks bounded fixture assertions (termination cause, exit code, max
latency, required and forbidden transcript literals) against audited
resource events, then binds the evaluated outcome inside the
authenticated receipt digest. Capability advances to version 1 with
the evaluator landed.
Keep credentials and network access behind authenticated, audited brokers while binding launch adapters, immutable closures, recovery identities, receipts, and cleanup to the approved plan. Add Apple Container and Linux release lanes without weakening the outer sandbox.
Detect and bind operator-installed harnesses through explicit, digest-bound runtime policy. Keep macOS and Linux shipping lanes capability-aware and fail closed when isolation evidence is absent.