agy-context-saver 0.0.0-stage → 1.2.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/LICENSE +21 -0
- package/README.md +169 -2
- package/hooks.json +16 -0
- package/install.ps1 +42 -0
- package/install.sh +6 -0
- package/mcp/index.js +1085 -0
- package/mcp/instructions.md +30 -0
- package/mcp_config.json +8 -0
- package/package.json +41 -6
- package/plugin.json +5 -0
- package/rules/AGENTS.md +78 -0
- package/scripts/execution-guard-hook.mjs +575 -0
- package/scripts/install-register.mjs +620 -0
- package/scripts/provision-rtk.mjs +120 -0
- package/skills/context-governance/SKILL.md +130 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { execSync } from "node:child_process";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const repoRoot = path.resolve(__dirname, "..");
|
|
9
|
+
const binDir = path.join(repoRoot, "bin");
|
|
10
|
+
|
|
11
|
+
export const RTK_VERSION = "v0.51.0";
|
|
12
|
+
|
|
13
|
+
export function getRtkPlatformAsset() {
|
|
14
|
+
const platform = os.platform();
|
|
15
|
+
const arch = os.arch();
|
|
16
|
+
|
|
17
|
+
if (platform === "win32" && arch === "x64") {
|
|
18
|
+
return { asset: "rtk-x86_64-pc-windows-msvc.zip", exeName: "rtk.exe", isZip: true };
|
|
19
|
+
}
|
|
20
|
+
if (platform === "darwin" && arch === "arm64") {
|
|
21
|
+
return { asset: "rtk-aarch64-apple-darwin.tar.gz", exeName: "rtk", isZip: false };
|
|
22
|
+
}
|
|
23
|
+
if (platform === "darwin" && arch === "x64") {
|
|
24
|
+
return { asset: "rtk-x86_64-apple-darwin.tar.gz", exeName: "rtk", isZip: false };
|
|
25
|
+
}
|
|
26
|
+
if (platform === "linux" && arch === "x64") {
|
|
27
|
+
return { asset: "rtk-x86_64-unknown-linux-musl.tar.gz", exeName: "rtk", isZip: false };
|
|
28
|
+
}
|
|
29
|
+
if (platform === "linux" && arch === "arm64") {
|
|
30
|
+
return { asset: "rtk-aarch64-unknown-linux-gnu.tar.gz", exeName: "rtk", isZip: false };
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function findExistingRtk() {
|
|
36
|
+
// Check local binDir first
|
|
37
|
+
const info = getRtkPlatformAsset();
|
|
38
|
+
const localExe = info ? path.join(binDir, info.exeName) : null;
|
|
39
|
+
if (localExe && fs.existsSync(localExe)) {
|
|
40
|
+
try {
|
|
41
|
+
const out = execSync(`"${localExe}" --version`, { encoding: "utf-8", timeout: 5000 }).trim();
|
|
42
|
+
return { path: localExe, version: out, isLocal: true };
|
|
43
|
+
} catch {}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Check PATH
|
|
47
|
+
try {
|
|
48
|
+
const out = execSync("rtk --version", { encoding: "utf-8", timeout: 5000 }).trim();
|
|
49
|
+
return { path: "rtk", version: out, isLocal: false };
|
|
50
|
+
} catch {}
|
|
51
|
+
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function ensureRtkInstalled(options = {}) {
|
|
56
|
+
const log = options.silent ? () => {} : console.log;
|
|
57
|
+
const existing = options.existingRtk || findExistingRtk();
|
|
58
|
+
if (existing) {
|
|
59
|
+
log(`✓ RTK is already installed: ${existing.version} (${existing.path})`);
|
|
60
|
+
return existing;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const assetInfo = getRtkPlatformAsset();
|
|
64
|
+
if (!assetInfo) {
|
|
65
|
+
throw new Error(`Unsupported platform/architecture for prebuilt RTK: ${os.platform()} ${os.arch()}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!fs.existsSync(binDir)) {
|
|
69
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const targetExe = path.join(binDir, assetInfo.exeName);
|
|
73
|
+
const downloadUrl = `https://github.com/rtk-ai/rtk/releases/download/${RTK_VERSION}/${assetInfo.asset}`;
|
|
74
|
+
log(`⚡ Downloading RTK ${RTK_VERSION} from ${downloadUrl}...`);
|
|
75
|
+
|
|
76
|
+
const response = await fetch(downloadUrl);
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
throw new Error(`Failed to download RTK release (${response.status} ${response.statusText}): ${downloadUrl}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
82
|
+
const archivePath = path.join(binDir, assetInfo.asset);
|
|
83
|
+
fs.writeFileSync(archivePath, buffer);
|
|
84
|
+
|
|
85
|
+
log(`✓ Downloaded ${Math.round(buffer.length / 1024)} KB. Extracting archive...`);
|
|
86
|
+
try {
|
|
87
|
+
// Windows 10/11, macOS, and Linux all provide native tar
|
|
88
|
+
execSync(`tar -xf "${archivePath}" -C "${binDir}"`, { stdio: "pipe" });
|
|
89
|
+
} catch (err) {
|
|
90
|
+
// Fallback on Windows if tar fails
|
|
91
|
+
if (os.platform() === "win32") {
|
|
92
|
+
execSync(`powershell -NoProfile -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${binDir}' -Force"`, { stdio: "pipe" });
|
|
93
|
+
} else {
|
|
94
|
+
throw err;
|
|
95
|
+
}
|
|
96
|
+
} finally {
|
|
97
|
+
try { fs.unlinkSync(archivePath); } catch {}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Make executable on POSIX
|
|
101
|
+
if (os.platform() !== "win32") {
|
|
102
|
+
try { fs.chmodSync(targetExe, 0o755); } catch {}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const verified = findExistingRtk();
|
|
106
|
+
if (!verified) {
|
|
107
|
+
throw new Error(`RTK installation verification failed: could not run ${targetExe}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
log(`✓ Successfully installed and verified RTK: ${verified.version} at ${verified.path}`);
|
|
111
|
+
return verified;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Auto-run if executed directly
|
|
115
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
116
|
+
ensureRtkInstalled().catch((err) => {
|
|
117
|
+
console.error("Error provisioning RTK:", err);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: context-governance
|
|
3
|
+
description: >-
|
|
4
|
+
Use when running shell commands with large outputs, inspecting session transcript health,
|
|
5
|
+
preventing repetitive background polling loops, inspecting codebases with RTK, or delegating heavy research to subagents.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Context Governance & Execution Guard (Agy-Context-Saver + RTK)
|
|
9
|
+
|
|
10
|
+
Agy-Context-Saver and RTK protect session transcript health and LLM attention by transparently compressing command outputs, preventing repetitive background polling loops, routing native inspection to compact CLI interfaces, and offloading deep research to sandboxed subagents.
|
|
11
|
+
|
|
12
|
+
## Architectural Boundaries
|
|
13
|
+
|
|
14
|
+
- **RTK (Rust Token Killer)**: Owns shell command rewriting, terminal output compression, and canonical codebase inspection (`rtk read`, `rtk grep`, `rtk find`, `rtk ls`, `rtk err`, `rtk summary`).
|
|
15
|
+
- **Agy-Context-Saver**: Owns Antigravity lifecycle governance, Reactive Wakeup enforcement, transcript forensics, and session integrity.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Codebase Inspection via RTK
|
|
20
|
+
|
|
21
|
+
Native Antigravity file and search tools (`view_file`, `grep_search`, `find_by_name`, `list_dir`) bypass token compression and are hard-routed to RTK shell commands:
|
|
22
|
+
|
|
23
|
+
- `rtk read <file>`: Reads file with intelligent token filtering and line ranges.
|
|
24
|
+
- `rtk find <path>`: Compact file search tree and directory listings (cross-platform, works on Windows & POSIX).
|
|
25
|
+
- Search commands by platform:
|
|
26
|
+
- **Windows**: Use `rtk rg "<pattern>" .` (explicit target `.` is required to avoid child process stdin pipe stalls) or `rg "<pattern>" .`.
|
|
27
|
+
- **POSIX / Linux / macOS**: Use `rtk grep "<pattern>"` or `rtk rg "<pattern>"`.
|
|
28
|
+
- Directory listing by platform:
|
|
29
|
+
- **Windows**: Use `rtk find <path>` or PowerShell `dir` / `Get-ChildItem`. (Avoid `rtk ls` or `rtk tree` on Windows as they rely on POSIX binaries/flags).
|
|
30
|
+
- **POSIX / Linux / macOS**: Use `rtk ls <path>` or `rtk tree`.
|
|
31
|
+
- `rtk err <cmd>`: Runs command and displays only errors/warnings.
|
|
32
|
+
- `rtk summary <cmd>`: Runs command and produces a 2-line technical summary.
|
|
33
|
+
|
|
34
|
+
*Safe Harbor*: Documented Antigravity special files (`SKILL.md`, brain artifacts, `.gemini/config/`) may be viewed directly via `view_file`.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Available Agy MCP Tools
|
|
39
|
+
|
|
40
|
+
### 1. `check_context_health`
|
|
41
|
+
Performs streaming inspection of `transcript.jsonl` to calculate turn budgets, step counts, raw payload size, RTK status, and detect busy-polling loops.
|
|
42
|
+
- **Parameters**:
|
|
43
|
+
- `transcriptPath` (string, required): Absolute path to `transcript.jsonl`.
|
|
44
|
+
|
|
45
|
+
### 2. `subagent_brief`
|
|
46
|
+
Generates a strictly formatted, scope-isolated prompt for delegating research or debugging to a subagent (`invoke_subagent`).
|
|
47
|
+
- **Parameters**:
|
|
48
|
+
- `objective` (string, required): Core investigative or implementation goal.
|
|
49
|
+
- `scopeFiles` (array of strings, optional): Specific file targets.
|
|
50
|
+
- `expectedDeliverable` (string, optional): Expected concise synthesis format.
|
|
51
|
+
|
|
52
|
+
### 3. `read_transcript`
|
|
53
|
+
Quickly reads recent conversation turns from an Antigravity transcript in clean Markdown format with zero JSON noise.
|
|
54
|
+
- **Parameters**:
|
|
55
|
+
- `conversationId` (string, required): Conversation UUID or path.
|
|
56
|
+
- `mode` (string, default: "compact"): "compact" or "full".
|
|
57
|
+
- `lastTurns` (number, default: 3): Number of turns to display.
|
|
58
|
+
|
|
59
|
+
### 4. `query_transcript`
|
|
60
|
+
Granular query and forensic filtering engine for transcripts with keyword/regex search and role filtering.
|
|
61
|
+
- **Parameters**:
|
|
62
|
+
- `conversationId` (string, required): Conversation UUID or path.
|
|
63
|
+
- `query` (string, optional): Search keyword or regex.
|
|
64
|
+
- `roles` (array, default: ["user", "assistant"]): Filter by role.
|
|
65
|
+
|
|
66
|
+
### 5. `get_installation_status`
|
|
67
|
+
Audits the Antigravity integration layers (Native Plugin Link, Lifecycle Hook in `hooks.json`, MCP Server in `mcp_config.json`, Tool Schemas, and RTK binary/hook).
|
|
68
|
+
|
|
69
|
+
### 6. `sync_installation`
|
|
70
|
+
Re-verifies, repairs, and synchronizes the installation and tool schemas in ~25ms.
|
|
71
|
+
- **Parameters**:
|
|
72
|
+
- `checkOnly` (boolean, default: false): Dry-run audit mode.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Core Governance Rules
|
|
77
|
+
|
|
78
|
+
1. **Reactive Wakeup First**:
|
|
79
|
+
- Never busy-wait on `manage_task(Action='status')` or `schedule` polling timers.
|
|
80
|
+
- Stop calling tools and yield the turn for native Reactive Wakeup (`<SYSTEM_MESSAGE>`).
|
|
81
|
+
- Polling calls across tasks are tracked in a session ledger. 5 cumulative denials trigger `force_ask` autonomous freeze.
|
|
82
|
+
|
|
83
|
+
2. **Fast Synchronous Execution**:
|
|
84
|
+
- Commands default to `WaitMsBeforeAsync: 10000` to complete synchronously without background detachment.
|
|
85
|
+
|
|
86
|
+
3. **Protected Antigravity State**:
|
|
87
|
+
- Direct access to `.system_generated/` (transcripts, task logs, scheduler state) is strictly denied. Use Agy MCP transcript tools.
|
|
88
|
+
|
|
89
|
+
4. **Benchmark Integrity**:
|
|
90
|
+
- Mutating benchmark definitions, prompt templates, or evaluators requires explicit user confirmation.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Zero-Guesswork Testing & Verification Playbook
|
|
95
|
+
|
|
96
|
+
When validating this framework or reproducing tests, execute these exact steps:
|
|
97
|
+
|
|
98
|
+
1. **Check Live Registration**:
|
|
99
|
+
```bash
|
|
100
|
+
npm run status
|
|
101
|
+
# or
|
|
102
|
+
node mcp/index.js status
|
|
103
|
+
```
|
|
104
|
+
*Expected*: Reports `HEALTHY & ACTIVE 🛡️` across plugin link, hook, MCP server, schemas, and RTK.
|
|
105
|
+
|
|
106
|
+
2. **Run Full Test Suite**:
|
|
107
|
+
```bash
|
|
108
|
+
npm test
|
|
109
|
+
```
|
|
110
|
+
*Expected*: All 5 suites pass (Unit hook tests, MCP protocol tests, E2E probes, live system validation, lifecycle rollback).
|
|
111
|
+
|
|
112
|
+
3. **Run Targeted Suite Tests**:
|
|
113
|
+
- Governance Hook: `node tests/test-hook.mjs`
|
|
114
|
+
- MCP Protocol & JSON-RPC: `node tests/test-mcp.mjs`
|
|
115
|
+
- E2E Probes: `node tests/test-e2e-probes.mjs`
|
|
116
|
+
- Live System Checks: `node tests/test-installed-verification.mjs`
|
|
117
|
+
- Lifecycle & Rollback: `node tests/test-lifecycle-rollback.mjs`
|
|
118
|
+
|
|
119
|
+
4. **Verify MCP Tools Inside Antigravity**:
|
|
120
|
+
- `get_installation_status`: Call with `{}` to audit all 4 layers + RTK.
|
|
121
|
+
- `check_context_health`: Call with `{ "transcriptPath": "<path-to-transcript.jsonl>" }`.
|
|
122
|
+
- `read_transcript`: Call with `{ "conversationId": "<uuid>", "lastTurns": 3, "mode": "compact" }`.
|
|
123
|
+
- `query_transcript`: Call with `{ "conversationId": "<uuid>", "query": "<term>", "summaryOnly": true }`.
|
|
124
|
+
- `subagent_brief`: Call with `{ "objective": "<goal>", "scopeFiles": ["..."] }`.
|
|
125
|
+
|
|
126
|
+
5. **Operational Guardrails**:
|
|
127
|
+
- ❌ Never launch `npm start` or `node mcp/index.js` interactively without stdin redirection (it is a stdio JSON-RPC daemon).
|
|
128
|
+
- ❌ Never loop on `manage_task(Action='status')` or use task watchdog timers (circuit breaker freezes at 5 denials).
|
|
129
|
+
- ❌ Never run `npm run uninstall` as an isolated test (always follow immediately with `npm run setup`).
|
|
130
|
+
- ❌ On Windows, never run `rtk rg` without an explicit directory (e.g. use `rtk rg "pattern" .`).
|