Antigravity terminal lifecycle, charter, read-once

Task 9946 · Queued · Coder · created · updated

Original request (verbatim): "Close the gap between Claude, Codex, Antigravity and Pi. More universal code, less provider specific" Settled inputs: PRD (Task 9932) and Architecture (Task 9933) of this epic. Approach (architecture §1): lifecycle events run in Jaah-owned code in front of every session (ACP: `jaah-acp-host`, `apps/jaahd/acp/host.py`; terminal: node daemon + vendor CLI events); tool events run in-band through ONE neutral dispatcher `tools/hook_bridge_core.py::dispatch`. Adapters contribute only declarations (event names, tool-name map, placement literals, error text patterns, question prefix), never a copy of the logic. Requirement R1 (verbatim): "Each of these mechanisms has exactly ONE provider-neutral implementation home that every provider uses; an adapter contributes only vendor literals and capability declarations, never its own copy of the logic: (a) hook/guard rendering & chaining, (b) hook-context injection into the model, (c) charter placement as system/built-in instructions, (d) session-start rule list (guard brief), (e) read-once guard reset signal, (f) prompt-submit and session-end lifecycle events, (g) StopFailure / API-error self-heal, (h) project-memory hooks, (i) token/cost (spend) reading, (j) usage-window (quota) reading, (k) the operator question / structured interview channel." R5 (verbatim): "Availability: every closed capability is ON by default on the dev control plane (`dev.jaah.ai`) — no new switch that ships OFF; if a switch is unavoidable it defaults ON and is wired in the real deployment." Closing-test naming contract (architecture §4): every degradation key this child closes gets a test named `test_closes_<key with - as _>` (e.g. `test_closes_no_hook_context`); C9 refuses to remove a key without it. Do NOT remove catalogue degradation keys in this child — the close-out child removes them; this child delivers the behaviour and the closing test. ## Scope (this child) PRECONDITION / HOLD (architecture §4, human precondition I4 — the AskUserQuestion pause below IS the hold): this child measures a live agy 1.2.11 *terminal* session in a scratch `agy1` console session opened through the console on dev (`https://app.dev.jaah.ai`). First check the dev Accounts page: if `agy1` is not "available", raise ONE AskUserQuestion round (header `Human act`) asking the operator to re-login `agy1` on dev; do every unblocked part (code, declarations, fixture scaffolding) meanwhile. If the answer does not clear it, deliver what is not blocked and settle naming the unmeasured remainder — never declare unmeasured literals. Architecture child C3a — Antigravity terminal runtime. Builds on C1 (`harness_dispatch`, `dispatch`). Mechanisms (c) terminal literal, (e) terminal, (f) terminal. - Charter: a `SessionStart` `systemMessage` step from the per-dispatch hooks file. The first `-i` prompt then carries only the task. - Prompt-submit: the bridge derives it from the first `PreInvocation` after a `Stop`. - Session-end: today `apps/jaahd/agents/antigravity_runner.py:132-134` declares `_QUIT` but never compares it (no `pane_marker`, unmeasured TUI vocabulary). MEASURE agy 1.2.11's quit in a scratch `agy1` console session (what the pane shows when the operator quits at the prompt) and declare the pane marker on the adapter's `QuitSignature`. The node then runs `on_session_end` when that marker appears and completes the chat. - Read-once: first measure whether compaction shortens or rewrites `transcriptPath`. If it does, the existing shrink backstop (`tools/read_once_guard.py:636-640`) is the reset, plus the PreToolUse `Read|Bash` row mapped to agy tool names. If not, reset at each turn boundary (first `PreInvocation` after `Stop`). Partial reads always stay allowed, so a missed mid-turn compaction costs one ranged read, never a stuck runner. Record the measurement in `apps/jaahd/README.md` §Antigravity. PRD AC7 (verbatim): "in an Antigravity console session, re-read a file twice → re-read guard fires; type into an idle chat → prompt-submit event reopens it; quit at the prompt → the session completes." (Live terminal half runs in the Finish stage after `agy1` re-login.) Credentials & reach: - C3a/C3b terminal measurements + AC7/AC10 Antigravity terminal (live half) | dev account `agy1` (Google sign-in; Accounts page shows "Needs attention: Login") | **deferred**: the login is an operator action (I4: "I'll re-login both"). C3a/C3b are held until `agy1` shows available (their measurements need it); the Finish stage then runs the live checks - C1–C7 unit and replay tests, AC1–AC4 | nothing beyond the worktree (`./dc check full`) | verified (worktree) - Console (Accounts page check, scratch `agy1` console session): AC5, AC9, AC11 browser checks | `org/console/dev-login` (on roster, `credential_get` ok; its `base_url` field is stale, so use `https://app.dev.jaah.ai`) on dev | verified (probe: GET / → 200; Accounts page read in browser) Out of scope (PRD, verbatim — do NOT touch): - MUST NOT retire, rewrite or change the runtime selection of the legacy terminal runtime; Claude `oauth` stays `legacy_only` (ADR in `docs/adrs/README.md`, ACP Claude entry). - MUST NOT remove or reword any "stay published" degradation (list above), including Pi `no-subagents` and `acp-runtime-only`. - MUST NOT build Pi subagents or a Jaah-side subagent lane. - MUST NOT add Jaah-side workarounds for vendor-intrinsic DeepSeek/Codex gaps (PDF conversion, model remap changes, throttling avoidance). - MUST NOT do live-verification work for Antigravity `not-yet-observed`, nor touch `home-is-account-dir` or `microvm-signed-in-legacy-runtime`. - MUST NOT change `tools/provider_branches.toml` patterns/allowlist scope beyond what removing branches requires (gate tightening was not selected), and set no line-count target. - MUST NOT add a new provider or retire one; no change to login/sign-in flows, model-tier resolution, or the plan gate (`non_claude_engines`). Stay-published keys (must stay byte-identical): DeepSeek `document-blocks-unsupported`, `images-flash-only`, `prompt-cache-controls-ignored`, `beta-features-ignored`, `web-search-extra-calls`, `claude-model-names-remapped`, `model-quality-differs`; Codex `device-code-login-workspace-gated`, `subscription-concurrency-throttling`; Pi `no-subagents`, `acp-runtime-only`. I1-escaped (stay, unchanged): Antigravity `no-spend-reading`; Pi and DeepSeek `no-quota-reading`. Done means: - Bridge unit tests per derivation (prompt-submit from first `PreInvocation` after `Stop`; read-once reset per the measured branch) — `test_closes_no_prompt_submit_event`, `test_closes_no_read_once_guard` (terminal halves). - An `antigravity_runner` launch test shows no charter in `-i` — `test_closes_charter_in_first_prompt` (Antigravity). - The RECORDED quit pane fixture (measured on agy 1.2.11, not synthetic) completes the session — `test_closes_no_session_end_event` (terminal half). - `test_closes_project_memory_hooks` for Antigravity — terminal half (memory SessionStart/Stop rows run via this child's derivations and the per-dispatch hooks file). - README §Antigravity records both measurements; quick gate green; `python3 tools/check_provider_branches.py` exits 0. - (deferred — live Antigravity terminal AC7 needs `agy1` re-login; Finish stage)

Activity

  • Draft
  • Ready