From aace40dd72fb98656c366aea9ca54f231459f76b Mon Sep 17 00:00:00 2001 From: YEONGUK LEE Date: Thu, 15 Oct 2026 10:42:04 +0900 Subject: [PATCH 1/5] docs(antigravity): record #307 startup and receiver-bridge evidence Curate the 2026-10-13 isolated macOS observations for #307 under experiments/antigravity-startup/, which is excluded from the wheel and sdist. The README separates pre-input observability, post-first-input SessionStart bootstrap, hook context limits, the receiver-started bridge delivery and the cross-process direct agentapi counterexample, and marks unestablished items. The probe scripts are copied unchanged as reproduction scaffolding; no test executes them. Historical observations only; no new live test, runtime change, stable CLI promotion or first-input support claim. Refs #307 --- experiments/antigravity-startup/README.md | 255 ++++++++++++++++++ .../antigravity-startup/execution_probe.py | 82 ++++++ experiments/antigravity-startup/hook_probe.py | 71 +++++ .../antigravity-startup/native_probe.py | 72 +++++ 4 files changed, 480 insertions(+) create mode 100644 experiments/antigravity-startup/README.md create mode 100644 experiments/antigravity-startup/execution_probe.py create mode 100644 experiments/antigravity-startup/hook_probe.py create mode 100644 experiments/antigravity-startup/native_probe.py diff --git a/experiments/antigravity-startup/README.md b/experiments/antigravity-startup/README.md new file mode 100644 index 00000000..27e99aca --- /dev/null +++ b/experiments/antigravity-startup/README.md @@ -0,0 +1,255 @@ +# Antigravity startup and receiver-bridge evidence (#307) + +Status: **historical investigation record**. Issue: +https://github.com/abruption/session-peer/issues/307 + +This directory curates observations made on **2026-10-13** in an isolated, +owned macOS session. Nothing here is a new test, and nothing here is a live +test of the v1.1.2 preparation on `main`. It does not promote any Antigravity +behavior to stable CLI support, does not claim first-input (pre-input) +delivery support, and does not change runtime code, hooks, settings or +permission policy. `experiments/` is excluded from the wheel and sdist. + +The existing owner bridge (started from the receiving TUI's own tool runner, +#85) and a hypothetical new startup/autostart feature are different things. +Evidence for the first is not evidence for the second. + +Mac/Linux validation of CLI 1.3.3 after explicit registration is tracked +separately in #304 / PR #305 (`docs/validation/85-antigravity.md`) and is not +repeated here. + +## Sources and evidence classes + +| Source | What it is | +| --- | --- | +| Issue #307 comment, 2026-10-13 | Operator summary of the first (unpinned) run | +| Local experiment report, 2026-10-13 | Uncommitted operator report from the original experiment worktree; this README is a curated, sanitized restatement of it | +| `hook_probe.py`, `native_probe.py`, `execution_probe.py` | Probe scaffolding copied byte-for-byte from that worktree (no personal paths or identifiers embedded) | + +Evidence classes used below: + +- **Reported result**: structured fields (exit code, `status`, `submitted`, + `consumptionConfirmed`, ...) as recorded in the operator report. Raw native + or send stdout/stderr is **not** in this repository. For the receiver-side + send, the message/input binding was kept privately as a **reconstruction** + from the executed command and a private manifest, explicitly not labeled raw + send stdout. For the first run, only a reduced result was retained. +- **On-screen observation**: text the operator saw in the owned TUI's PTY + output. This is a test receipt, not a structured receipt; + `consumptionConfirmed` stayed `false` in every send. +- **Body-free metadata**: hook-event records containing only event name, + process/parent IDs, validated owner PID/start time, conversation ID and + timestamps (`execution_probe.py`), plus `lsof` presence-FD checks. No message + bodies, hook payloads, environment values, credentials or transcripts were + recorded. The private records themselves are not committed. + +Whether any probe was deleted and later reconstructed is **unknown**: the +source materials do not say so. What they do say is that the execution observer +was revised during the receiver-side control (see below), so not every record +was produced by the committed `execution_probe.py`. + +## Versions + +| Item | Value | +| --- | --- | +| Host | macOS 27.0.1, arm64 (only platform tested) | +| Python | 3.15.0 | +| session-peer runtime under test | published v1.1.1, `b48144bdf2ad1569031562136f5a60e33780020e`, unchanged | +| Model shown by TUI | Gemini 3.8 Flash (High) | +| First run, TUI display | **1.3.3** at startup and at exit | +| First run, post-test `agy --version` | **1.3.4**, same installed executable path | +| Follow-ups, pinned private copy | 1.3.4, SHA-256 `9da414c0624c27aa2969a86030a070b5341c0657700512eba70b21725ce253f5` | + +**Version confound (first run).** The TUI displayed 1.3.3, but the installed +executable reported 1.3.4 after the test. The experiment did not invoke an +update. The reason and replacement time are not established, and the +`agentapi` wrapper executes that path, so the delegate version during the +first-run send is **unknown**. The first-run send is not an exact-version 1.3.3 +or 1.3.4 result. + +The follow-ups ran the owned TUI and direct `agentapi` probes from a private +copy of the public native executable (basename `agy`); the installed wrapper and +home were not changed. For the receiver-side control, the pinned TUI binary and +the installed binary used by the unchanged `agentapi` wrapper had matching 1.3.4 +hashes immediately before and after the send. Even so, each result below is one +observation on one host, not a version-wide guarantee. + +## Findings + +### (a) Pre-input: no externally observable conversation ID or hook + +With a temporary workspace-local `.agents/hooks.json` (SessionStart) in a +trusted, dedicated test folder, the TUI reached its first idle prompt with no +user input and the probe's result file did not exist. In the pinned follow-up +the result was still absent at two idle checkpoints, 05:22:11 UTC and 05:22:34 +UTC (23 seconds apart). + +This only shows that **no conversation ID or hook execution was externally +observable at those idle checkpoints**. It does not show that the TUI has no +internal conversation ID before input, and it is not a universal timing +guarantee or a long-duration idle test. + +### (b) SessionStart runs after the first input, before model invocation + +After one harmless first prompt (requesting a fixed `READY` marker, no tools), +SessionStart ran and supplied a valid conversation ID. The hook started the +unchanged runtime bridge without asking the model to run a tool; its native +ancestor/presence checks passed, it returned `ready: true`, and the +registration was discoverable exactly once. The TUI visibly returned the +`READY` marker. + +So the hook can act as a **post-first-input bootstrap**. Upstream's "before +first model invocation" wording +([Hooks](https://antigravity.google/docs/hooks/)) does not mean "before first +user input". A listening bridge is not proof of delivery authority. + +### (c) The hook lacks the normal language-server context + +Only boolean availability of four context variable names was retained (no +values): + +| Variable | In hook (first run and pinned follow-up) | In native tool runner (pinned control) | +| --- | --- | --- | +| `ANTIGRAVITY_CONVERSATION_ID` | present | present | +| `ANTIGRAVITY_TRAJECTORY_ID` | absent | present | +| `ANTIGRAVITY_LS_ADDRESS` | absent | present | +| `ANTIGRAVITY_CSRF_TOKEN` | absent | present | + +Reported send outcomes: + +- **First run (unpinned)**: one generation-pinned bridge send from the hook- + started bridge returned exit 1, `status: unknown`, `submitted: false`, + `consumptionConfirmed: false`, `retryAllowed: false`. No ACK was visible + during bounded observation. The legacy `submitted: false` on an unknown + outcome is not proof of no effect. No retry, new conversation or fallback. + The bridge discards native diagnostics and the reduced result did not keep + the exit-code/timeout discriminator, so the cause is **unclassified** for + this run. +- **Pinned 1.3.4, from the hook** (`native_probe.py --phase hook`): exit 1, no + timeout, fixed `ANTIGRAVITY_LS_ADDRESS` variable-name diagnostic matched (a + name match, not the exact error sentence). +- **Pinned 1.3.4, read-only ordinary-shell control**: an own-conversation + metadata query exited 1 with the exact fixed text `ANTIGRAVITY_LS_ADDRESS is + not set`. +- **Pinned 1.3.4, native tool-runner positive control** + (`native_probe.py --phase tool`, approved once via the normal permission + prompt, not always-allow; distinct marker, not a retry): exit 0, no timeout. + The model visibly referred to the new marker afterward, but **no final exact + ACK** was obtained before the bounded test was interrupted (the operator + prompt and the injected message also asked for conflicting output; this is a + test limitation). This is a direct-native control, not a full session-peer + bridge round trip. + +Together these identify a practical environment/context boundary: the hook did +not have the authority that the legitimate tool runner had. They do **not** +establish the internal authentication protocol, and they do not authorize +copying or manufacturing the missing context. SessionStart cannot be described +as a working first-input listener on this evidence. + +### (d) Positive: receiver-started bridge delivered to the owner + +A separate owned receiver B was started with the pinned 1.3.4 binary. From B's +legitimate native tool runner, one approved command (`execution_probe.py +--start-bridge`) started the unchanged v1.1.1 receiver bridge; it returned +ready and B returned to idle. An external shell then made exactly one ordinary, +generation-pinned session-peer send to that bridge. + +- Reported result: exit 0, `status: submitted`, `submitted: true`, + `nativeExitCode: 0`, `consumptionConfirmed: false`. +- On-screen observation: B visibly answered the exact fresh test marker, in its + owned PTY output and again in its exit redraw (no transcript file was read). + This is an on-screen ACK, not a structured receipt; the CLI's + `consumptionConfirmed` contract is unchanged and no automatic return message + exists. +- Body-free metadata: the post-send PreInvocation/PostInvocation/Stop records + had B as parent and as the validated native owner, with B's conversation ID; + a separate `lsof` check confirmed B's presence FD and working directory. This + places execution in B, not merely a native exit zero. + +Observer revision: between B's setup and the send, the observer was refined. +Initial records used successful owner validation without an `ownerVerified` +field; later records include it, and a failed owner validation no longer +suppresses read-only event observations (bridge setup still requires +validation). The committed `execution_probe.py` matches the later observer +SHA-256 `64a393ff372fe8c54cf62d268d6bb89c6b25c90593c37edaf35a3eb6d220631c`; +do not attribute the initial records to this exact source. + +This is one macOS receiver-side round trip from the explicit-registration path, +not a startup feature and not a Linux/Windows or long-term stability claim. + +### (e) Counterexample: direct agentapi from another TUI runs in the caller + +A fresh receiver B2 was left idle with no bridge. A separate cooperating sender +A invoked direct `agentapi send-message` from **A's** tool runner against B2's +exact conversation ID. Sender-side reported result: one native send, exit 0, no +timeout. (An earlier, different marker was declined at the approval prompt +before execution and was not retried.) + +- Body-free metadata: B2's workspace hook recorded PreInvocation, + PostInvocation and Stop for B2's conversation, but all three had **A's process + as parent**, and native owner validation failed for them. Concurrent `lsof` + checks showed B2 still held its own presence FD while A held its own and not + B2's. Process start times and executable paths were cross-checked against + private manifests. A separate observation of A holding other handles whose + paths contained B2's ID at a different instant does not establish persistent + storage overlap. +- On-screen observation: B2 stayed idle for 93.88 seconds. One later operator + query asked whether a new marker had arrived, without supplying or resending + it; B2 answered `NONE`, and that query's hook events were parented by B2. + +So a matching conversation ID plus native exit zero does not prove execution in +the already-open TUI. The target owner did not receive the message. Native +persistence, store-conflict and resume behavior were **not established**; no +database or history was modified directly. Creating a new agentapi execution in +another process, or a new conversation, is not a substitute for reaching the +owner of the target TUI ([Sidecars](https://antigravity.google/docs/sidecars/) +advertises Antigravity 2.0 availability, not CLI sidecar autostart). + +## Not established / unverified + +- Delivery to an idle TUI before its first user input. +- Any legitimate way for SessionStart (or another hook) to obtain agentapi + authority; the internal authentication protocol. +- Cause of the first-run unknown send (unclassified), and the delegate version + at that time. +- A complete session-peer bridge round trip on 1.3.4 started from a hook. +- Structured receipt: all ACKs above are on-screen observations; + `consumptionConfirmed` was always `false`. +- Linux, Windows, later native versions, the v1.1.2 preparation, automatic + bridge recovery, long idle periods and long-term stability. +- Whether the initial probes were ever deleted and reconstructed (not stated in + the source materials). + +## Probe scaffolding + +These scripts are reproduction scaffolding, not automated tests, not a +production transport and not a general-purpose runner. Nothing in the test +suite executes them. Running them requires an owned TUI, an explicitly approved +workspace and an operator; do not install them as global hooks. + +| Script | Role | Notes | +| --- | --- | --- | +| `hook_probe.py` | SessionStart hook: records context-variable booleans and starts the unchanged bridge (TTL 120 s, 2 requests) | `--output-dir PRIVATE_SCRATCH --runtime ABSOLUTE_SCRIPT`; scratch must be owner-only (mode 0700); result file mode 0600 | +| `native_probe.py` | One direct native `agentapi send-message`, keeping only a fixed diagnostic class and exit code | `--phase hook` or `tool`; 15 s deadline but no byte cap on native output; expects a private `agy` copy in the scratch dir | +| `execution_probe.py` | Body-free hook-event observer and receiver-side bridge setup (`--start-bridge`, TTL 600 s, 2 requests) | Appends to a private mode-0600 JSONL file | + +The private results contain owned conversation and process IDs that are needed +only for exact-target testing and cleanup and must never be committed. The +request cap is not permission to retry an unknown result. Production ancestor, +UID, presence and start-time checks are used unchanged; no credentials are read +or copied. + +## Cleanup recorded in the source report + +Every owned bridge was stopped (`stopped: true` where reported), every owned TUI +exited with status zero, owned PIDs were confirmed absent, and the temporary +workspace hooks, their newly created empty parent directories, private result +records and executable copies were removed. Native conversation history, +unrelated sessions, global settings and the installed wrapper were not changed. + +## Next gates (from #307) + +A follow-up must pin TUI and delegate versions, keep bounded non-secret native +outcome classification, and separately establish startup timing, legitimate +hook authority and actual receipt, without copying credentials or weakening +owner checks. Issue #307 stays open until those acceptance gates are met. diff --git a/experiments/antigravity-startup/execution_probe.py b/experiments/antigravity-startup/execution_probe.py new file mode 100644 index 00000000..34278f67 --- /dev/null +++ b/experiments/antigravity-startup/execution_probe.py @@ -0,0 +1,82 @@ +"""Body-free owned-native execution observations and receiver-side bridge setup.""" +import argparse +import importlib.util +import json +import os +from pathlib import Path +import select +import subprocess +import sys +import time +import uuid + +def main(): + p = argparse.ArgumentParser() + p.add_argument('--scratch', required=True) + p.add_argument('--runtime', required=True) + p.add_argument('--event', choices=['SessionStart', 'PreInvocation', 'PostInvocation', 'Stop']) + p.add_argument('--start-bridge', action='store_true') + a = p.parse_args() + scratch = Path(a.scratch) + if scratch.stat().st_uid != os.getuid() or scratch.stat().st_mode & 0o077: + raise ValueError('private scratch required') + spec = importlib.util.spec_from_file_location('tested_runtime', a.runtime) + rt = importlib.util.module_from_spec(spec) + spec.loader.exec_module(rt) + if a.start_bridge: + thread = str(uuid.UUID(os.environ['ANTIGRAVITY_CONVERSATION_ID'])) + else: + payload = sys.stdin.buffer.read(65537) + if len(payload) > 65536: + raise ValueError('hook payload too large') + thread = str(uuid.UUID(json.loads(payload)['conversationId'])) + home = Path('~/.gemini/antigravity-cli').expanduser().resolve() + # Do not weaken production ownership/presence checks or import credentials. + try: + owner = rt.agy_owner(home, thread) + owner_verified = True + except Exception: + if a.start_bridge: + raise + # Observation must survive a cross-conversation owner mismatch. Only + # the bridge setup requires successful native owner validation. + owner = {'pid': None, 'start': None} + owner_verified = False + record = {'event': a.event or 'BridgeSetup', 'pid': os.getpid(), + 'ppid': os.getppid(), 'ownerPid': owner['pid'], + 'ownerStart': owner['start'], 'ownerVerified': owner_verified, + 'conversationId': thread, + 'monotonic': time.monotonic(), 'utcSeconds': time.time()} + fd = os.open(scratch / 'execution-events.jsonl', os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o600) + with os.fdopen(fd, 'a') as out: + out.write(json.dumps(record) + '\n') + if a.start_bridge: + bridge = subprocess.Popen([sys.executable, a.runtime, 'antigravity-bridge', + 'serve', '--thread', thread, '--ttl', '600', '--max-requests', '2'], + stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, start_new_session=True) + ready = {} + if select.select([bridge.stdout], [], [], 8)[0]: + line = bridge.stdout.readline(16385) + try: + ready = json.loads(line) + except (ValueError, UnicodeDecodeError): + pass + bridge.stdout.close() + if ready.get('ready') is not True: + if bridge.poll() is None: + bridge.terminate() + bridge.wait(timeout=5) + raise RuntimeError('bridge readiness not established') + record.update({'ready': True, 'bridgePid': bridge.pid, + 'generation': ready['generation'], 'antigravityHome': str(home), + 'eventsPath': str(scratch / 'execution-events.jsonl')}) + fd = os.open(scratch / 'bridge-manifest.json', os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) + with os.fdopen(fd, 'w') as out: + json.dump(record, out) + print('Receiver bridge ready. No message has been sent by this setup.') + else: + print('{}') + +if __name__ == '__main__': + main() diff --git a/experiments/antigravity-startup/hook_probe.py b/experiments/antigravity-startup/hook_probe.py new file mode 100644 index 00000000..105a34a9 --- /dev/null +++ b/experiments/antigravity-startup/hook_probe.py @@ -0,0 +1,71 @@ +"""Opt-in test-only SessionStart probe; never persist the raw hook payload/env.""" +import argparse +import json +import os +from pathlib import Path +import select +import subprocess +import sys +import time +import uuid + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--output-dir', required=True) + parser.add_argument('--runtime', required=True) + args = parser.parse_args() + output = Path(args.output_dir) + # Operator-created private scratch only, not a shared log or repository. + if output.stat().st_uid != os.getuid() or output.stat().st_mode & 0o077: + raise ValueError('private output directory required') + raw = sys.stdin.buffer.read(65537) + if len(raw) > 65536: + raise ValueError('hook input too large') + data = json.loads(raw) + thread = str(uuid.UUID(data['conversationId'])) + record = { + 'observedMonotonic': time.monotonic(), + 'conversationId': thread, + 'hookPid': os.getpid(), + 'hookParentPid': os.getppid(), + 'contextPresent': { + name: bool(os.environ.get(name)) for name in ( + 'ANTIGRAVITY_LS_ADDRESS', 'ANTIGRAVITY_CSRF_TOKEN', + 'ANTIGRAVITY_CONVERSATION_ID', 'ANTIGRAVITY_TRAJECTORY_ID', + ) + }, + } + # Inherit the legitimate hook environment; never read or copy token values. + # Unchanged runtime must prove ancestor/presence itself; no replacement owner. + proc = subprocess.Popen( + [sys.executable, args.runtime, 'antigravity-bridge', 'serve', + '--thread', thread, '--ttl', '120', '--max-requests', '2'], + stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, start_new_session=True, + ) + record['bridgePid'] = proc.pid + if select.select([proc.stdout], [], [], 5)[0]: + line = proc.stdout.readline(16385) + try: + response = json.loads(line) + except (ValueError, UnicodeDecodeError): + response = {} + record['bridgeReady'] = response.get('ready') is True + record['bridgeReason'] = response.get('error', {}).get('reason') + else: + record['bridgeReady'] = False + record['bridgeReason'] = 'probe_readiness_timeout' + record['bridgeExit'] = proc.poll() + if not record['bridgeReady'] and proc.poll() is None: + proc.terminate() + proc.wait(timeout=5) + proc.stdout.close() + fd = os.open(output / 'hook-result.json', os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) + with os.fdopen(fd, 'w') as handle: + json.dump(record, handle) + print('{}') + + +if __name__ == '__main__': + main() diff --git a/experiments/antigravity-startup/native_probe.py b/experiments/antigravity-startup/native_probe.py new file mode 100644 index 00000000..59bea988 --- /dev/null +++ b/experiments/antigravity-startup/native_probe.py @@ -0,0 +1,72 @@ +"""Owned-session-only native diagnostic; raw native output never leaves memory.""" +import argparse +import importlib.util +import json +import os +from pathlib import Path +import subprocess +import sys +import time +import uuid + +def main(): + p = argparse.ArgumentParser() + p.add_argument('--scratch', required=True) + p.add_argument('--runtime', required=True) + p.add_argument('--thread') + p.add_argument('--phase', choices=['hook', 'tool'], default='hook') + a = p.parse_args() + scratch = Path(a.scratch) + if scratch.stat().st_uid != os.getuid() or scratch.stat().st_mode & 0o077: + raise ValueError('private scratch required') + if a.phase == 'tool' and not a.thread: + thread = str(uuid.UUID(os.environ['ANTIGRAVITY_CONVERSATION_ID'])) + elif a.thread: + thread = str(uuid.UUID(a.thread)) + else: + raw = sys.stdin.buffer.read(65537) + if len(raw) > 65536: + raise ValueError('hook input too large') + thread = str(uuid.UUID(json.loads(raw)['conversationId'])) + spec = importlib.util.spec_from_file_location('tested_runtime', a.runtime) + runtime = importlib.util.module_from_spec(spec) + spec.loader.exec_module(runtime) + # Production ancestor, UID, presence, and start-time checks are not weakened. + owner = runtime.agy_owner(Path('~/.gemini/antigravity-cli').expanduser(), thread) + result = {'phase': a.phase, 'conversationId': thread, 'ownerPid': owner['pid'], + 'ownerValidated': True, 'observedMonotonic': time.monotonic(), + 'contextPresent': {name: name in os.environ for name in ( + 'ANTIGRAVITY_LS_ADDRESS', 'ANTIGRAVITY_CSRF_TOKEN', + 'ANTIGRAVITY_CONVERSATION_ID', 'ANTIGRAVITY_TRAJECTORY_ID')}} + token = 'ACK AGY307-PINNED-' + a.phase.upper() + argv = [str(scratch / 'agy'), 'agentapi', 'send-message', + '--title=session-peer-isolated-probe', '--', thread, + 'User-authorized isolated native delivery test. Reply exactly ' + token + + '. Do not use tools or edit files.'] + try: + done = subprocess.run(argv, stdin=subprocess.DEVNULL, capture_output=True, + timeout=15) + result['nativeExit'] = done.returncode + result['timedOut'] = False + combined = done.stdout + b'\n' + done.stderr + # Persist fixed classes only, never diagnostics or credential values. + result['knownDiagnostic'] = next((label for literal, label in ( + (b'ANTIGRAVITY_LS_ADDRESS is not set', 'ls_address_not_set'), + (b'a tool context is required to send a message', 'tool_context_required'), + (b'invalid agentapi principal', 'invalid_agentapi_principal'), + (b'ANTIGRAVITY_LS_ADDRESS', 'ls_address_diagnostic'), + (b'ANTIGRAVITY_CSRF_TOKEN', 'csrf_diagnostic'), + (b'connection refused', 'connection_refused'), + ) if literal in combined), 'none_matched') + except subprocess.TimeoutExpired: + result['nativeExit'] = None + result['timedOut'] = True + result['knownDiagnostic'] = 'not_classified' + fd = os.open(scratch / (a.phase + '-result.json'), + os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) + with os.fdopen(fd, 'w') as handle: + json.dump(result, handle) + print('{}' if a.phase == 'hook' else 'Owned native probe completed; diagnostics retained privately.') + +if __name__ == '__main__': + main() From a623335c85aa3d6c38dc6451ccce6f455408215b Mon Sep 17 00:00:00 2001 From: YEONGUK LEE Date: Thu, 15 Oct 2026 10:46:55 +0900 Subject: [PATCH 2/5] docs(antigravity): qualify archived evidence provenance and probe limits --- experiments/antigravity-startup/README.md | 41 ++++++++++++++++------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/experiments/antigravity-startup/README.md b/experiments/antigravity-startup/README.md index 27e99aca..7d2863f2 100644 --- a/experiments/antigravity-startup/README.md +++ b/experiments/antigravity-startup/README.md @@ -43,10 +43,13 @@ Evidence classes used below: bodies, hook payloads, environment values, credentials or transcripts were recorded. The private records themselves are not committed. -Whether any probe was deleted and later reconstructed is **unknown**: the -source materials do not say so. What they do say is that the execution observer -was revised during the receiver-side control (see below), so not every record -was produced by the committed `execution_probe.py`. +The private collaborator manifest explicitly identifies an initial probe as +deleted and later reconstructed from the recorded command, with no original +source hash. It separately identifies the joint sender probe as the exact source +used in that joint run. Copying these three files unchanged from the review +worktree establishes snapshot equality, not their identity with every historical +execution. The execution observer was also revised during the receiver-side +control (see below); not every record came from the committed version. ## Versions @@ -217,8 +220,8 @@ advertises Antigravity 2.0 availability, not CLI sidecar autostart). `consumptionConfirmed` was always `false`. - Linux, Windows, later native versions, the v1.1.2 preparation, automatic bridge recovery, long idle periods and long-term stability. -- Whether the initial probes were ever deleted and reconstructed (not stated in - the source materials). +- Exact initial-execution source custody for reconstructed probes; no missing + original hash is inferred from a later snapshot comparison. ## Probe scaffolding @@ -227,6 +230,13 @@ production transport and not a general-purpose runner. Nothing in the test suite executes them. Running them requires an owned TUI, an explicitly approved workspace and an operator; do not install them as global hooks. +These historical scripts are not a reviewed future-run recipe. In particular, +native markers are fixed rather than fresh nonces, native output capture has no +byte cap, and bridge readiness/cleanup and output-file handling are not hardened +against every partial-output, symlink or same-user race. Do not rerun them to +infer a fresh receipt without a separately reviewed, bounded harness and new +operator authorization. No rerun was performed for this documentation change. + | Script | Role | Notes | | --- | --- | --- | | `hook_probe.py` | SessionStart hook: records context-variable booleans and starts the unchanged bridge (TTL 120 s, 2 requests) | `--output-dir PRIVATE_SCRATCH --runtime ABSOLUTE_SCRIPT`; scratch must be owner-only (mode 0700); result file mode 0600 | @@ -236,16 +246,21 @@ workspace and an operator; do not install them as global hooks. The private results contain owned conversation and process IDs that are needed only for exact-target testing and cleanup and must never be committed. The request cap is not permission to retry an unknown result. Production ancestor, -UID, presence and start-time checks are used unchanged; no credentials are read -or copied. +UID, presence and start-time checks are used unchanged. Legitimate context is +inherited by the native child; availability checks retain booleans, not token +values. This is not a claim that subprocess environment inheritance transfers no +authority. Credential values are not intentionally logged, exported or persisted. ## Cleanup recorded in the source report -Every owned bridge was stopped (`stopped: true` where reported), every owned TUI -exited with status zero, owned PIDs were confirmed absent, and the temporary -workspace hooks, their newly created empty parent directories, private result -records and executable copies were removed. Native conversation history, -unrelated sessions, global settings and the installed wrapper were not changed. +The source reports cleanup of the owned bridges (`stopped: true` where reported), +TUIs and disposable workspaces/hooks/executable copies, with owned PIDs checked +absent at that time. Selected private metadata, manifests and reconstructed +evidence were retained for review, not committed here; this is not a claim that +all private records were deleted or that current processes were rechecked. +Native conversation history and unrelated sessions were preserved. Any temporary +workspace-trust change was reported restored; this documentation work did not +change global settings or the installed wrapper. ## Next gates (from #307) From 950b07242333fb277caf4d2d0ad266301fdced30 Mon Sep 17 00:00:00 2001 From: YEONGUK LEE Date: Thu, 15 Oct 2026 10:48:05 +0900 Subject: [PATCH 3/5] docs(antigravity): date historical upstream wording --- experiments/antigravity-startup/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/experiments/antigravity-startup/README.md b/experiments/antigravity-startup/README.md index 7d2863f2..d57dfa81 100644 --- a/experiments/antigravity-startup/README.md +++ b/experiments/antigravity-startup/README.md @@ -101,8 +101,8 @@ ancestor/presence checks passed, it returned `ready: true`, and the registration was discoverable exactly once. The TUI visibly returned the `READY` marker. -So the hook can act as a **post-first-input bootstrap**. Upstream's "before -first model invocation" wording +So the hook can act as a **post-first-input bootstrap**. The upstream wording +quoted in the 2026-10-13 report, "before first model invocation" ([Hooks](https://antigravity.google/docs/hooks/)) does not mean "before first user input". A listening bridge is not proof of delivery authority. @@ -205,8 +205,10 @@ the already-open TUI. The target owner did not receive the message. Native persistence, store-conflict and resume behavior were **not established**; no database or history was modified directly. Creating a new agentapi execution in another process, or a new conversation, is not a substitute for reaching the -owner of the target TUI ([Sidecars](https://antigravity.google/docs/sidecars/) -advertises Antigravity 2.0 availability, not CLI sidecar autostart). +owner of the target TUI. The [Sidecars](https://antigravity.google/docs/sidecars/) +page cited in the historical report described Antigravity 2.0 availability; +that was not CLI sidecar-autostart evidence. These linked pages were not newly +checked for current availability by this archive-only change. ## Not established / unverified From 8d246f0032b11ed81bc3d70b020496e646ceef45 Mon Sep 17 00:00:00 2001 From: YEONGUK LEE Date: Thu, 15 Oct 2026 10:50:54 +0900 Subject: [PATCH 4/5] docs(antigravity): bound receipt and hook timing claims --- experiments/antigravity-startup/README.md | 25 ++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/experiments/antigravity-startup/README.md b/experiments/antigravity-startup/README.md index d57dfa81..2f3e8463 100644 --- a/experiments/antigravity-startup/README.md +++ b/experiments/antigravity-startup/README.md @@ -26,6 +26,10 @@ repeated here. | Local experiment report, 2026-10-13 | Uncommitted operator report from the original experiment worktree; this README is a curated, sanitized restatement of it | | `hook_probe.py`, `native_probe.py`, `execution_probe.py` | Probe scaffolding copied byte-for-byte from that worktree (no personal paths or identifiers embedded) | +The Hooks and Sidecars links below are historical references cited by the +2026-10-13 reports. Neither page was newly checked for current availability by +this archive-only change. + Evidence classes used below: - **Reported result**: structured fields (exit code, `status`, `submitted`, @@ -39,9 +43,11 @@ Evidence classes used below: `consumptionConfirmed` stayed `false` in every send. - **Body-free metadata**: hook-event records containing only event name, process/parent IDs, validated owner PID/start time, conversation ID and - timestamps (`execution_probe.py`), plus `lsof` presence-FD checks. No message + timestamps and owner-validation booleans (`execution_probe.py`), plus `lsof` presence-FD checks. No message bodies, hook payloads, environment values, credentials or transcripts were recorded. The private records themselves are not committed. + The private bridge manifest additionally stores bridge PID, generation and + local absolute paths; it must not be committed either. The private collaborator manifest explicitly identifies an initial probe as deleted and later reconstructed from the recorded command, with no original @@ -92,7 +98,7 @@ observable at those idle checkpoints**. It does not show that the TUI has no internal conversation ID before input, and it is not a universal timing guarantee or a long-duration idle test. -### (b) SessionStart runs after the first input, before model invocation +### (b) SessionStart was observed after the first input After one harmless first prompt (requesting a fixed `READY` marker, no tools), SessionStart ran and supplied a valid conversation ID. The hook started the @@ -105,6 +111,8 @@ So the hook can act as a **post-first-input bootstrap**. The upstream wording quoted in the 2026-10-13 report, "before first model invocation" ([Hooks](https://antigravity.google/docs/hooks/)) does not mean "before first user input". A listening bridge is not proof of delivery authority. +The probes did not independently timestamp model invocation start; invocation +ordering here is the upstream contract quoted in that historical report. ### (c) The hook lacks the normal language-server context @@ -118,6 +126,11 @@ values): | `ANTIGRAVITY_LS_ADDRESS` | absent | present | | `ANTIGRAVITY_CSRF_TOKEN` | absent | present | +These are the retained booleans, not raw values. `hook_probe.py` checks whether a +value is nonempty; `native_probe.py` checks whether the name exists. Empty-value +state is not available from the native probe, so the two criteria must not be +treated as identical authority checks. + Reported send outcomes: - **First run (unpinned)**: one generation-pinned bridge send from the hook- @@ -201,14 +214,16 @@ before execution and was not retried.) it; B2 answered `NONE`, and that query's hook events were parented by B2. So a matching conversation ID plus native exit zero does not prove execution in -the already-open TUI. The target owner did not receive the message. Native +the already-open TUI. No target-owner receipt was observed within the bounded +test; the invocation was parented by the caller's process. The later query +returned `NONE`, which does not rule out unobserved late delivery or history +effects. Native persistence, store-conflict and resume behavior were **not established**; no database or history was modified directly. Creating a new agentapi execution in another process, or a new conversation, is not a substitute for reaching the owner of the target TUI. The [Sidecars](https://antigravity.google/docs/sidecars/) page cited in the historical report described Antigravity 2.0 availability; -that was not CLI sidecar-autostart evidence. These linked pages were not newly -checked for current availability by this archive-only change. +that was not CLI sidecar-autostart evidence. ## Not established / unverified From 5dc4d9a380b127c119d408e0ac20a616f8e9c4dc Mon Sep 17 00:00:00 2001 From: YEONGUK LEE Date: Thu, 15 Oct 2026 10:53:45 +0900 Subject: [PATCH 5/5] docs(antigravity): scope archived conclusions to observed runs --- experiments/antigravity-startup/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/experiments/antigravity-startup/README.md b/experiments/antigravity-startup/README.md index 2f3e8463..68f78e87 100644 --- a/experiments/antigravity-startup/README.md +++ b/experiments/antigravity-startup/README.md @@ -5,7 +5,7 @@ https://github.com/abruption/session-peer/issues/307 This directory curates observations made on **2026-10-13** in an isolated, owned macOS session. Nothing here is a new test, and nothing here is a live -test of the v1.1.2 preparation on `main`. It does not promote any Antigravity +test of the v1.1.2 runtime on `main`. It does not promote any Antigravity behavior to stable CLI support, does not claim first-input (pre-input) delivery support, and does not change runtime code, hooks, settings or permission policy. `experiments/` is excluded from the wheel and sdist. @@ -107,7 +107,8 @@ ancestor/presence checks passed, it returned `ready: true`, and the registration was discoverable exactly once. The TUI visibly returned the `READY` marker. -So the hook can act as a **post-first-input bootstrap**. The upstream wording +In this historical run, the hook started the bridge **after the first input**. +The upstream wording quoted in the 2026-10-13 report, "before first model invocation" ([Hooks](https://antigravity.google/docs/hooks/)) does not mean "before first user input". A listening bridge is not proof of delivery authority. @@ -156,8 +157,8 @@ Reported send outcomes: test limitation). This is a direct-native control, not a full session-peer bridge round trip. -Together these identify a practical environment/context boundary: the hook did -not have the authority that the legitimate tool runner had. They do **not** +Together these identify an observed environment/context boundary: the hook did +not provide the working native-send context observed in the tool runner. They do **not** establish the internal authentication protocol, and they do not authorize copying or manufacturing the missing context. SessionStart cannot be described as a working first-input listener on this evidence. @@ -193,7 +194,7 @@ do not attribute the initial records to this exact source. This is one macOS receiver-side round trip from the explicit-registration path, not a startup feature and not a Linux/Windows or long-term stability claim. -### (e) Counterexample: direct agentapi from another TUI runs in the caller +### (e) Counterexample: the direct agentapi invocation was parented by the caller A fresh receiver B2 was left idle with no bridge. A separate cooperating sender A invoked direct `agentapi send-message` from **A's** tool runner against B2's @@ -217,8 +218,7 @@ So a matching conversation ID plus native exit zero does not prove execution in the already-open TUI. No target-owner receipt was observed within the bounded test; the invocation was parented by the caller's process. The later query returned `NONE`, which does not rule out unobserved late delivery or history -effects. Native -persistence, store-conflict and resume behavior were **not established**; no +effects. Native persistence, store-conflict and resume behavior were **not established**; no database or history was modified directly. Creating a new agentapi execution in another process, or a new conversation, is not a substitute for reaching the owner of the target TUI. The [Sidecars](https://antigravity.google/docs/sidecars/) @@ -235,7 +235,7 @@ that was not CLI sidecar-autostart evidence. - A complete session-peer bridge round trip on 1.3.4 started from a hook. - Structured receipt: all ACKs above are on-screen observations; `consumptionConfirmed` was always `false`. -- Linux, Windows, later native versions, the v1.1.2 preparation, automatic +- Linux, Windows, later native versions, the v1.1.2 runtime, automatic bridge recovery, long idle periods and long-term stability. - Exact initial-execution source custody for reconstructed probes; no missing original hash is inferred from a later snapshot comparison.