agy-context-saver 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,72 @@
1
+ # Changelog
2
+
3
+ All notable changes to `Agy-Context-Saver` will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.3.0] - 2026-10-07
9
+
10
+ ### Governance & Loophole Elimination
11
+ - **Proportional Backoff Engine**: Eliminated the "Pendulum Freeze Trap" (where total bans on task polling caused hung/deadlocked background commands to run unmonitored forever) by implementing an exponential backoff curve ($0\text{s} \to 30\text{s} \to 75\text{s} \to 188\text{s} \to 469\text{s} \to 600\text{s}$). Tasks can be safely diagnosed when silent without enabling busy-waiting loops.
12
+ - **Watchdog Timer Coordination**: Coordinated `schedule` watchdog timers with the active proportional backoff window. Timers shorter than the backoff cooldown are rejected with detailed feedback, while legitimate watchdog timers ($\ge 30\text{s}$) are permitted and auto-cancel via native Reactive Wakeup.
13
+ - **Shell Wrapper Unwrapping (LH-01-B)**: Added recursive shell wrapper unwrapping (`cmd /c`, `powershell -Command`, `pwsh -c`, `bash -c`) inside `run_command` so wrapped commands are transparently rewritten to RTK equivalents instead of bypassing token optimization.
14
+ - **Internal State Shell Guard (LH-02-B)**: Added strict shell command guards blocking direct shell access (`cat`, `Get-Content`, `type`) to internal Antigravity execution state (`.system_generated/`), routing transcript queries to MCP tools.
15
+ - **Benchmark Shell Mutation Protection (LH-09-B)**: Extended benchmark and evaluator protections to shell redirect and removal operations (`>`, `rm`, `del`, `Remove-Item`), preventing benchmark tampering via the terminal.
16
+ - **Single Source of Truth Ledger**: Authored comprehensive `LEDGER.md` tracking all 10 historical loopholes (LH-01 to LH-10), remnant escape routes, backoff mathematical formulas, and architectural invariants.
17
+
18
+ ---
19
+
20
+ ## [1.2.1] - 2026-10-07
21
+
22
+ ### Documentation & Developer Experience
23
+ - **MCP Prompts Documentation**: Formally documented the `/mcp:agy-context-saver:context_shield` prompt across `README.md` and the documentation site, clarifying the operational difference between user slash commands (Prompts) and autonomous agent capabilities (Tools).
24
+ - **Quickstart Optimization**: Repositioned the Quickstart installation block to the very top of `README.md` and `docs/index.md` for immediate onboarding.
25
+ - **Zensical Docs Site Overhaul**: Added `context_shield` reference and tip callouts across `docs/index.md`, `docs/tools.md`, and `docs/governance.md`; updated navigation title to `Tools & Prompts`.
26
+ - **Dynamic Test Assertions**: Updated installed MCP server verification test to dynamically synchronize with `package.json` version.
27
+
28
+ ---
29
+
30
+ ## [1.2.0] - 2026-10-07
31
+
32
+ ### Performance & Forensics
33
+ - **Batch Full-Transcript Dereferencing**: Replaced sequential full-transcript scans with `batchFindFullSteps()`, reducing $N$-item dereferencing from $O(N)$ full-file passes down to a single streaming pass ($O(1)$) in 18.4ms.
34
+ - **Sliding-Window Turn Retention**: Bounded transcript memory retention in `read_transcript` (`WINDOW_SIZE = Math.max(100, lastTurns * 15)`) with an early-stopping block formatter, parsing 2,000 steps in 21.8ms under 24 KB memory.
35
+ - **Regex LRU Caching**: Added in-memory LRU cache (`regexCache`, capacity: 100) for query pattern compilation in `query_transcript`.
36
+ - **Short-Circuit Field Search**: Converted transcript search to test fields sequentially (`content` $\to$ `thinking` $\to$ `tool_calls`), avoiding heavy string concatenations.
37
+ - **Fast-Path Message Cleaning**: Added fast-path bypass in `cleanMessageContent` for strings $\le 120$ characters, eliminating redundant base64 regexes and newline splits.
38
+ - **Static Rules In-Memory Cache**: Cached `rules/AGENTS.md` in memory with `mtimeMs` file stat invalidation, eliminating disk I/O on `resources/read` and `prompts/get`.
39
+
40
+ ### Execution Governor & Hook
41
+ - **Fast-Path Builtin Bypass**: Added `NON_REWRITABLE_BINARIES` set (`node`, `powershell`, `pwsh`, `cmd`, `dir`, `echo`, `cd`, `del`, etc.) and PowerShell cmdlet prefixes to bypass `spawnSync("rtk")`, dropping execution latency from ~30ms to $< 0.05$ms.
42
+ - **Persistent Command Rewrite LRU Cache**: Implemented persistent disk LRU cache (`agy-rtk-rewrite-cache.json` in `os.tmpdir()`) for rewritable commands, reducing repeat rewrite lookups to $< 0.1$ms.
43
+ - **Session Ledger State Partitioning**: Partitioned session state by conversation ID (`agy-session-${safeId}.json`) to eliminate cross-session file contention.
44
+
45
+ ### Registration & Lifecycle
46
+ - **Idempotent Config & Schema Synchronization**: Added `safeWriteFileIfChanged` and `safeCopyFileIfChanged` across all configuration (`hooks.json`, `mcp_config.json`) and MCP tool schemas (`~/.gemini/antigravity/mcp/agy-context-saver/`), eliminating disk churn during repeat syncs.
47
+ - **RTK Provisioning Check Reuse**: Passed pre-detected RTK metadata to `ensureRtkInstalled()` to eliminate redundant `execSync` version checks during installation.
48
+
49
+ ### Security & Reliability
50
+ - **Stdio Payload Safety Ceiling**: Added 10 MB payload guard (`MAX_STDIO_PAYLOAD_BYTES`) on the MCP stdio line reader, emitting standard JSON-RPC `-32600 Invalid Request` on oversized payloads.
51
+ - **New Performance Verification Suite**: Added `tests/test-performance-probes.mjs` verifying batch dereferencing, sliding window bounds, stdio safety ceiling, and idempotent writes.
52
+
53
+ ---
54
+
55
+ ## [1.1.0] - 2026-10-07
56
+
57
+ ### Added
58
+ - **Closed Execution Topology & Governance Invariants**: Comprehensive PreToolUse hook intercepting native inspection tools (`view_file`, `grep_search`, `list_dir`, `find_by_name`) and hard-routing them to RTK.
59
+ - **Root-Based Antigravity State Protection**: Denied direct access to `.system_generated/` internal files to prevent transcript bloat and loop degradation.
60
+ - **Session-Wide Lifecycle Ledger**: Non-resettable session task polling counter with Tier 3 `force_ask` circuit breaker at 5 denials.
61
+ - **Evaluator & Benchmark Mutation Safeguard**: Gated mutation of evaluator or benchmark artifacts behind user confirmation.
62
+ - **Platform-Aware Windows Routing**: Windows-native routing for `rtk rg "<pattern>" .` and `rtk find <path>` to eliminate stdin hangs.
63
+ - **Universal MCP Server**: 6 core tools (`check_context_health`, `subagent_brief`, `get_installation_status`, `sync_installation`, `read_transcript`, `query_transcript`).
64
+
65
+ ---
66
+
67
+ ## [1.0.0] - 2026-10-07
68
+
69
+ ### Initial Release
70
+ - Initial release of Agy-Context-Saver.
71
+ - Antigravity Model Context Protocol (MCP) server.
72
+ - Background task lifecycle governance and reactive wakeup enforcement.
package/README.md CHANGED
@@ -13,6 +13,23 @@ It permanently eliminates session degradation, memory bloat, and context window
13
13
 
14
14
  ---
15
15
 
16
+ ## Quickstart (Instant Install)
17
+
18
+ Install and synchronize the governor and RTK across your Antigravity environment:
19
+
20
+ ```bash
21
+ # Fastest: one-line registration via npx
22
+ npx agy-context-saver install
23
+
24
+ # Or locally from this repository
25
+ npm run setup
26
+
27
+ # Audit health across all layers at any time
28
+ npm run status
29
+ ```
30
+
31
+ ---
32
+
16
33
  ## Architectural Division of Responsibilities
17
34
 
18
35
  ```text
@@ -65,23 +82,6 @@ It permanently eliminates session degradation, memory bloat, and context window
65
82
 
66
83
  ---
67
84
 
68
- ## Quickstart (Instant Install)
69
-
70
- Install and synchronize the governor and RTK across your Antigravity environment:
71
-
72
- ```bash
73
- # Fastest: one-line registration via npx
74
- npx agy-context-saver install
75
-
76
- # Or locally from this repository
77
- npm run setup
78
-
79
- # Audit health across all layers at any time
80
- npm run status
81
- ```
82
-
83
- ---
84
-
85
85
  ## Key Capabilities
86
86
 
87
87
  - **Transparent RTK Rewriting**: Native `run_command` calls are automatically rewritten (e.g. `pytest` $\to$ `rtk pytest`) via Antigravity PreToolUse hooks.
@@ -154,14 +154,17 @@ node tests/test-lifecycle-rollback.mjs
154
154
 
155
155
  ---
156
156
 
157
- ## Available MCP Tools
158
-
159
- 1. `check_context_health`: Diagnoses conversation transcript turn budgets, payload size, RTK status, and polling loops.
160
- 2. `subagent_brief`: Formulates scope-isolated prompts for delegated subagents.
161
- 3. `read_transcript`: Reads recent conversation history in clean Markdown format (compact/full).
162
- 4. `query_transcript`: Forensic filtering and regex search engine for conversation logs.
163
- 5. `get_installation_status`: Inspects live Antigravity plugin link, hook, MCP server, tool schemas, and RTK binary.
164
- 6. `sync_installation`: Re-verifies and repairs all integration layers in ~25ms.
157
+ ## MCP Tools & Slash Commands
158
+
159
+ * **User Slash Command (`/mcp:...`)**:
160
+ - `/mcp:agy-context-saver:context_shield`: Injects 3-layer governance rules and RTK standards into any session with one click. *(MCP Prompts appear in your chat autocomplete menu; MCP Tools are called autonomously by the agent).*
161
+ * **Agent MCP Tools**:
162
+ 1. `check_context_health`: Diagnoses conversation transcript turn budgets, payload size, RTK status, and polling loops.
163
+ 2. `subagent_brief`: Formulates scope-isolated prompts for delegated subagents.
164
+ 3. `read_transcript`: Reads recent conversation history in clean Markdown format (compact/full).
165
+ 4. `query_transcript`: Forensic filtering and regex search engine for conversation logs.
166
+ 5. `get_installation_status`: Inspects live Antigravity plugin link, hook, MCP server, tool schemas, and RTK binary.
167
+ 6. `sync_installation`: Re-verifies and repairs all integration layers in ~25ms.
165
168
 
166
169
  ---
167
170
 
package/mcp/index.js CHANGED
@@ -51,7 +51,7 @@ if (cliArg === "install" || cliArg === "--install") {
51
51
 
52
52
  function printHelp() {
53
53
  console.log(`
54
- Agy-Context-Saver 🛡️ (v1.2.0)
54
+ Agy-Context-Saver 🛡️ (v1.2.1)
55
55
  Universal MCP Server & Lifecycle Governor for Google Antigravity (Powered by RTK)
56
56
 
57
57
  Usage:
@@ -98,7 +98,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
98
98
  const rulesPath = path.resolve(__dirname, "../rules/AGENTS.md");
99
99
 
100
100
  const SERVER_NAME = "agy-context-saver";
101
- const SERVER_VERSION = "1.2.0";
101
+ const SERVER_VERSION = "1.3.0";
102
102
 
103
103
  // --- Tools Specification ---
104
104
  const TOOLS = [
package/package.json CHANGED
@@ -1,41 +1,42 @@
1
- {
2
- "name": "agy-context-saver",
3
- "version": "1.2.0",
4
- "description": "Universal Model Context Protocol (MCP) server & lifecycle governor purpose-built for Google Antigravity",
5
- "main": "mcp/index.js",
6
- "bin": {
7
- "agy-context-saver": "mcp/index.js"
8
- },
9
- "type": "module",
10
- "scripts": {
11
- "start": "node mcp/index.js",
12
- "setup": "node scripts/install-register.mjs",
13
- "uninstall": "node scripts/install-register.mjs --uninstall",
14
- "status": "node scripts/install-register.mjs --status",
15
- "test": "node tests/test-hook.mjs && node tests/test-mcp.mjs && node tests/test-e2e-probes.mjs && node tests/test-performance-probes.mjs && node tests/test-installed-verification.mjs && node tests/test-lifecycle-rollback.mjs"
16
- },
17
- "keywords": [
18
- "antigravity",
19
- "mcp",
20
- "model-context-protocol",
21
- "gemini",
22
- "context-window",
23
- "lifecycle-hooks",
24
- "agentic-coding"
25
- ],
26
- "files": [
27
- "mcp",
28
- "scripts",
29
- "rules",
30
- "skills",
31
- "hooks.json",
32
- "plugin.json",
33
- "mcp_config.json",
34
- "install.ps1",
35
- "install.sh",
36
- "README.md",
37
- "LICENSE"
38
- ],
39
- "author": "paragon-ux",
40
- "license": "MIT"
41
- }
1
+ {
2
+ "name": "agy-context-saver",
3
+ "version": "1.3.0",
4
+ "description": "Universal Model Context Protocol (MCP) server & lifecycle governor purpose-built for Google Antigravity",
5
+ "main": "mcp/index.js",
6
+ "bin": {
7
+ "agy-context-saver": "mcp/index.js"
8
+ },
9
+ "type": "module",
10
+ "scripts": {
11
+ "start": "node mcp/index.js",
12
+ "setup": "node scripts/install-register.mjs",
13
+ "uninstall": "node scripts/install-register.mjs --uninstall",
14
+ "status": "node scripts/install-register.mjs --status",
15
+ "test": "node tests/test-hook.mjs && node tests/test-mcp.mjs && node tests/test-e2e-probes.mjs && node tests/test-performance-probes.mjs && node tests/test-installed-verification.mjs && node tests/test-lifecycle-rollback.mjs"
16
+ },
17
+ "keywords": [
18
+ "antigravity",
19
+ "mcp",
20
+ "model-context-protocol",
21
+ "gemini",
22
+ "context-window",
23
+ "lifecycle-hooks",
24
+ "agentic-coding"
25
+ ],
26
+ "files": [
27
+ "mcp",
28
+ "scripts",
29
+ "rules",
30
+ "skills",
31
+ "hooks.json",
32
+ "plugin.json",
33
+ "mcp_config.json",
34
+ "install.ps1",
35
+ "install.sh",
36
+ "README.md",
37
+ "CHANGELOG.md",
38
+ "LICENSE"
39
+ ],
40
+ "author": "paragon-ux",
41
+ "license": "MIT"
42
+ }
package/plugin.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "agy-context-saver",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Deterministic background polling governor and subagent context preservation shield for Antigravity"
5
5
  }
@@ -276,6 +276,20 @@ function rewriteCommandWithRtk(rawCmd) {
276
276
  return trimmed;
277
277
  }
278
278
 
279
+ // Unwrap shell wrappers (e.g. cmd /c "...", powershell -Command "...", bash -c "...") (LH-01-B)
280
+ const shellWrapperMatch = trimmed.match(
281
+ /^(cmd(?:\.exe)?\s+\/[cC]|(?:powershell|pwsh)(?:\.exe)?\s+(?:-Command|-c)|(?:bash|sh)\s+-c)\s+["']?(.+?)["']?$/i
282
+ );
283
+ if (shellWrapperMatch) {
284
+ const wrapperPrefix = shellWrapperMatch[1];
285
+ const innerCmd = shellWrapperMatch[2].trim();
286
+ const rewrittenInner = rewriteCommandWithRtk(innerCmd);
287
+ if (rewrittenInner !== innerCmd) {
288
+ return `${wrapperPrefix} "${rewrittenInner}"`;
289
+ }
290
+ return trimmed;
291
+ }
292
+
279
293
  // Fast-path bypass for shell builtins, non-rewritable binaries, and powershell cmdlets
280
294
  const firstWord = (trimmed.match(/^[^\s"']+/)?.[0] || "").toLowerCase();
281
295
  if (
@@ -317,6 +331,17 @@ function rewriteCommandWithRtk(rawCmd) {
317
331
  return rewritten;
318
332
  }
319
333
 
334
+ /**
335
+ * Calculates the required minimum cooldown interval (in seconds)
336
+ * proportional to the number of diagnostic status inspections already performed.
337
+ * Formula: Math.min(600, Math.round(30 * Math.pow(2.5, Math.max(0, pollCount - 1))))
338
+ * Levels: Level 0 -> 0s (baseline), Level 1 -> 30s, Level 2 -> 75s, Level 3 -> 188s, Level 4 -> 469s, Level 5+ -> 600s
339
+ */
340
+ function getRequiredBackoffSeconds(pollCount) {
341
+ if (pollCount <= 0) return 0;
342
+ return Math.min(600, Math.round(30 * Math.pow(2.5, Math.max(0, pollCount - 1))));
343
+ }
344
+
320
345
  // --- Main Hook Entrypoint ---
321
346
  let isGovernedTool = false;
322
347
 
@@ -364,6 +389,29 @@ try {
364
389
  });
365
390
  }
366
391
 
392
+ // LH-02-B: Direct shell access to internal Antigravity execution state (.system_generated)
393
+ if (isProtectedInternalState(rawCmd)) {
394
+ respond({
395
+ decision: "deny",
396
+ reason:
397
+ "Antigravity Execution Governance: Direct shell access to internal Antigravity execution state (.system_generated) is strictly prohibited to prevent transcript bloat and polling loops.\n" +
398
+ "- To inspect conversation transcripts: Call MCP tool read_transcript(conversationId=\"...\", mode=\"compact\") or query_transcript(...).\n" +
399
+ "- To inspect background tasks: Yield execution turn and rely on native Reactive Wakeup (<SYSTEM_MESSAGE>). Do not read internal task logs."
400
+ });
401
+ }
402
+
403
+ // LH-09-B: Shell command mutation of protected benchmark artifacts
404
+ if (
405
+ (rawCmd.includes(">") || /\b(?:rm|del|Remove-Item)\b/i.test(rawCmd)) &&
406
+ isProtectedBenchmarkPath(rawCmd)
407
+ ) {
408
+ respond({
409
+ decision: "force_ask",
410
+ reason:
411
+ "[BENCHMARK MUTATION DETECTED] Shell command mutation of protected evaluator/benchmark artifact requires explicit user confirmation to prevent benchmark contamination."
412
+ });
413
+ }
414
+
367
415
  const rewritten = rewriteCommandWithRtk(rawCmd);
368
416
  const isDaemon = args.IsDaemon === true || args.isDaemon === true;
369
417
  const waitMs = args.WaitMsBeforeAsync !== undefined ? args.WaitMsBeforeAsync : args.waitMsBeforeAsync;
@@ -486,33 +534,43 @@ try {
486
534
  session.taskIds.push(taskId);
487
535
  }
488
536
 
489
- // First inspection check in the session is permitted
490
- if (session.pollCount === 0) {
491
- session.pollCount = 1;
537
+ const now = Date.now();
538
+ const requiredBackoffSec = Math.max(30, getRequiredBackoffSeconds(session.pollCount));
539
+ const requiredBackoffMs = requiredBackoffSec * 1000;
540
+ const elapsedMs = session.lastPollTime ? (now - session.lastPollTime) : Infinity;
541
+ const elapsedSec = Math.floor(elapsedMs / 1000);
542
+
543
+ // Premature check before backoff interval has elapsed
544
+ if (elapsedMs < requiredBackoffMs) {
545
+ session.denials++;
492
546
  saveSessionState(convId, session);
493
- respond({ decision: "allow" });
494
- }
495
547
 
496
- // Any subsequent polling checks in the session are strictly denied
497
- session.denials++;
498
- saveSessionState(convId, session);
548
+ if (session.denials >= 5) {
549
+ respond({
550
+ decision: "force_ask",
551
+ reason: `[CIRCUIT BREAKER ACTIVATED] Autonomous loop suspended: manage_task('${action}') called prematurely ${session.denials} times during active backoff window across tasks [${session.taskIds.join(", ")}]. Stop calling tools and yield the turn for native Reactive Wakeup (<SYSTEM_MESSAGE>). User confirmation required to proceed.`
552
+ });
553
+ }
499
554
 
500
- if (session.denials >= 5) {
555
+ const remainingSec = Math.ceil((requiredBackoffMs - elapsedMs) / 1000);
501
556
  respond({
502
- decision: "force_ask",
503
- reason: `[CIRCUIT BREAKER ACTIVATED] Autonomous loop suspended: manage_task('${action}') has been denied ${session.denials} times across tasks [${session.taskIds.join(", ")}]. Stop calling tools and yield the turn for native Reactive Wakeup (<SYSTEM_MESSAGE>). User confirmation required to proceed.`
557
+ decision: "deny",
558
+ reason: `Antigravity Execution Governance: Proportional Backoff Active (Level ${session.pollCount}, ${session.denials} denial${session.denials > 1 ? "s" : ""}). Diagnostic check #${session.pollCount + 1} requires at least ${requiredBackoffSec}s elapsed since previous check (${elapsedSec}s elapsed, ${remainingSec}s remaining). Tasks execute asynchronously and notify you automatically via native Reactive Wakeup (<SYSTEM_MESSAGE>) upon completion. Stop calling tools and yield your turn now.`
504
559
  });
505
560
  }
506
561
 
507
- respond({
508
- decision: "deny",
509
- reason: `Antigravity Execution Governance: Background task polling is prohibited (${session.denials} denial). Tasks execute asynchronously and notify you automatically via native Reactive Wakeup (<SYSTEM_MESSAGE>) upon completion. Stop calling tools and yield your turn now.`
510
- });
562
+ // Backoff window satisfied! Allow diagnostic check and advance level:
563
+ session.pollCount++;
564
+ session.lastPollTime = now;
565
+ session.denials = 0;
566
+ saveSessionState(convId, session);
567
+ respond({ decision: "allow" });
511
568
  }
512
569
 
513
570
  if (toolName === "schedule") {
514
571
  const prompt = String(args.Prompt || args.prompt || "").replace(/^["']|["']$/g, "").trim().toLowerCase();
515
572
  const cond = String(args.TimerCondition || args.timerCondition || "").replace(/^["']|["']$/g, "").trim().toLowerCase();
573
+ const duration = Number(args.DurationSeconds || args.durationSeconds || args.duration || 0);
516
574
 
517
575
  const isTaskPoll =
518
576
  cond.startsWith("task-") ||
@@ -525,23 +583,30 @@ try {
525
583
  ((prompt.includes("check") || prompt.includes("status") || prompt.includes("poll") || prompt.includes("monitor") || prompt.includes("wait")) &&
526
584
  (prompt.includes("task") || prompt.includes("process") || prompt.includes("job") || prompt.includes("test") || prompt.includes("command") || prompt.includes("suite")));
527
585
 
528
- // All polling timers are strictly denied regardless of duration (LH-03)
529
586
  if (isTaskPoll) {
530
587
  const session = getSessionState(convId);
531
- session.denials++;
532
- saveSessionState(convId, session);
588
+ const requiredBackoffSec = Math.max(30, getRequiredBackoffSeconds(session.pollCount));
589
+
590
+ // Task watchdog timers must be AT LEAST the required backoff window!
591
+ if (duration < requiredBackoffSec) {
592
+ session.denials++;
593
+ saveSessionState(convId, session);
594
+
595
+ if (session.denials >= 5) {
596
+ respond({
597
+ decision: "force_ask",
598
+ reason: `[CIRCUIT BREAKER ACTIVATED] Autonomous loop suspended: schedule polling timer has been denied ${session.denials} times. Background tasks notify you automatically upon completion. User confirmation required to proceed.`
599
+ });
600
+ }
533
601
 
534
- if (session.denials >= 5) {
535
602
  respond({
536
- decision: "force_ask",
537
- reason: `[CIRCUIT BREAKER ACTIVATED] Autonomous loop suspended: schedule polling timer has been denied ${session.denials} times. Background tasks notify you automatically upon completion. User confirmation required to proceed.`
603
+ decision: "deny",
604
+ reason: `Antigravity Execution Governance: Task watchdog timer duration too short (${duration}s, ${session.denials} denial${session.denials > 1 ? "s" : ""}). Under Proportional Backoff (Level ${session.pollCount}), watchdog timer must be at least ${requiredBackoffSec}s. Tasks notify you automatically via native Reactive Wakeup (<SYSTEM_MESSAGE>). Stop calling tools and yield the turn instead.`
538
605
  });
539
606
  }
540
607
 
541
- respond({
542
- decision: "deny",
543
- reason: "Antigravity Execution Governance: Scheduling timers to poll or monitor background tasks is prohibited regardless of duration. Background tasks notify you automatically via native Reactive Wakeup (<SYSTEM_MESSAGE>). Stop calling tools and yield the turn instead."
544
- });
608
+ // If duration >= requiredBackoffSec, watchdog timer is permitted!
609
+ respond({ decision: "allow" });
545
610
  }
546
611
 
547
612
  // Non-polling timers (e.g. user-requested reminders) are allowed