agentguard-local 0.1.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.
@@ -0,0 +1,37 @@
1
+ # AgentGuard Decisions
2
+
3
+ ## D1: Preserve Terminal I/O With A Client-Side Runner
4
+
5
+ Original LLD choice: use a client-side shim plus daemon instead of routing interactive sessions through a daemon-owned PTY.
6
+
7
+ Observed constraint: preserving stdin/stdout/stderr/cwd/env and exit code is essential for CLI tools and test fixtures.
8
+
9
+ Chosen adjustment: `agentguard run` asks the daemon for admission, then the client process spawns the real tool in a new process group with inherited stdio. The daemon records root pid/pgid and manages only that guarded process group.
10
+
11
+ Tradeoff: the daemon does not own the child process directly, so exit registration is cooperative. Daemon restart reconciliation handles still-running pids and marks uncertain records `lost`.
12
+
13
+ Tests: `run_fake_tool_records_job_and_preserves_stdio_and_exit_code`, `daemon_restart_reconciles_still_running_job`, and `shim_wraps_fake_codex_without_real_codex_and_injects_thread_cap`.
14
+
15
+ ## D2: Use A Command-Output Memory Sampler Fallback In MVP
16
+
17
+ Original LLD choice: prefer DispatchSource memory pressure events, `host_statistics64` / `vm_statistics64`, `ProcessInfo.physicalMemory`, and pid/process APIs behind traits.
18
+
19
+ Observed constraint: implementing and binding the low-level macOS APIs would slow the MVP without changing the pure scheduler and policy behavior.
20
+
21
+ Chosen adjustment: keep pressure sampling at the daemon edge and use stable macOS command output from `sysctl hw.memsize` and `vm_stat` as the fallback sampler. Deterministic pressure tests use `AGENTGUARD_FAKE_PRESSURE_FILE`.
22
+
23
+ Tradeoff: this fallback is polling-oriented and less precise than DispatchSource pressure callbacks. The core pressure classifier and scheduler remain pure so native API sampling can replace the fallback later.
24
+
25
+ Tests: `pressure_classifier_uses_thresholds_and_events`, `pressure_recovery_hysteresis_requires_stable_recovery`, `simulated_soft_pressure_queues_then_recovery_admits_job`, and `simulated_critical_pressure_pauses_and_recovery_resumes_guarded_group`.
26
+
27
+ ## D3: Codex Integration Is Preventive In V1
28
+
29
+ Original LLD choice: inject a safe subagent/thread cap with `-c agents.max_threads=N` unless the user supplied an explicit override.
30
+
31
+ Observed constraint: an external local daemon cannot reliably queue individual Codex subagents inside an already-running Codex session.
32
+
33
+ Chosen adjustment: the Codex adapter only rewrites launch arguments. It prepends `-c agents.max_threads=N` when no explicit `agents.max_threads` setting is present.
34
+
35
+ Tradeoff: AgentGuard controls initial Codex fan-out but does not inspect or schedule individual subagents after launch.
36
+
37
+ Tests: `codex_adapter_injects_thread_cap_when_absent`, `codex_adapter_does_not_override_explicit_config`, and `shim_wraps_fake_codex_without_real_codex_and_injects_thread_cap`.
@@ -0,0 +1,75 @@
1
+ # AgentGuard Testing
2
+
3
+ Run the required checks from the repository root:
4
+
5
+ ```sh
6
+ cargo fmt --check
7
+ cargo clippy --workspace --all-targets --all-features -- -D warnings
8
+ cargo test --workspace --all-features
9
+ ```
10
+
11
+ If `cargo nextest` is installed, also run:
12
+
13
+ ```sh
14
+ cargo nextest run --workspace --all-features
15
+ ```
16
+
17
+ Do not install nextest just for this project.
18
+
19
+ ## Fake Pressure Testing
20
+
21
+ The daemon supports deterministic pressure tests through `AGENTGUARD_FAKE_PRESSURE_FILE` when `AGENTGUARD_TEST_MODE=1` is set:
22
+
23
+ ```sh
24
+ printf normal > /tmp/agentguard-pressure.txt
25
+ AGENTGUARD_TEST_MODE=1 \
26
+ AGENTGUARD_FAKE_PRESSURE_FILE=/tmp/agentguard-pressure.txt \
27
+ target/debug/agentguardd --socket /tmp/agentguard.sock --db /tmp/agentguard.db --foreground
28
+ ```
29
+
30
+ Change the file to `soft` to force queued admission and `critical` to force guarded process-group pause behavior:
31
+
32
+ ```sh
33
+ printf soft > /tmp/agentguard-pressure.txt
34
+ printf critical > /tmp/agentguard-pressure.txt
35
+ printf normal > /tmp/agentguard-pressure.txt
36
+ ```
37
+
38
+ The integration tests use this path rather than allocating large memory, which keeps smoke tests safe on 8GB Macs.
39
+
40
+ ## Coverage Map
41
+
42
+ - Unit: pressure classifier threshold behavior.
43
+ - Unit: pressure recovery hysteresis.
44
+ - Unit: scheduler admission under normal pressure.
45
+ - Unit: scheduler queueing under soft pressure.
46
+ - Unit: scheduler pause selection under critical pressure.
47
+ - Unit: priority ordering plus aging.
48
+ - Unit: policy load/save/defaults.
49
+ - Unit: job lifecycle transition validity.
50
+ - Unit: Codex adapter injects `agents.max_threads` when absent.
51
+ - Unit: Codex adapter does not override explicit user config.
52
+ - Unit: socket protocol serialization compatibility.
53
+ - Integration: start daemon on a temporary socket and SQLite database.
54
+ - Integration: `agentguard status --json` returns pressure, policy, and job state.
55
+ - Integration: `agentguard run -- <fake-tool>` starts and records a job.
56
+ - Integration: active job limit queues the second job.
57
+ - Integration: simulated soft pressure queues a job with a human-readable reason.
58
+ - Integration: simulated recovery admits queued jobs.
59
+ - Integration: simulated critical pressure pauses a low-priority guarded process group.
60
+ - Integration: resume after recovery sends `SIGCONT` to the guarded process group.
61
+ - Integration: daemon restart reconciles a still-running job.
62
+ - Integration: shim preserves cwd/env/args/stdout/stderr/stdin behavior and exit code through inherited process execution.
63
+ - Integration: shim dispatch wraps a fake `codex` binary without requiring real Codex.
64
+
65
+ ## macOS Smoke Checks
66
+
67
+ These are safe manual checks after `cargo build`:
68
+
69
+ ```sh
70
+ target/debug/agentguard doctor
71
+ target/debug/agentguard run -- /bin/sleep 1
72
+ target/debug/agentguard run --priority low -- /bin/sleep 30
73
+ ```
74
+
75
+ Use fake pressure for pressure scenarios. Do not allocate large memory on small Macs just to exercise queueing or pause behavior.
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
4
+ BIN="$DIR/darwin-arm64/agentguard"
5
+ if [ ! -x "$BIN" ]; then
6
+ echo "agentguard: bundled darwin-arm64 binary is missing. Build from source with cargo build --release." >&2
7
+ exit 127
8
+ fi
9
+ exec "$BIN" "$@"
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
4
+ BIN="$DIR/darwin-arm64/agentguardd"
5
+ if [ ! -x "$BIN" ]; then
6
+ echo "agentguardd: bundled darwin-arm64 binary is missing. Build from source with cargo build --release." >&2
7
+ exit 127
8
+ fi
9
+ exec "$BIN" "$@"
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "agentguard-local",
3
+ "version": "0.1.0",
4
+ "description": "macOS-first RAM-aware admission controller for local AI coding CLI processes",
5
+ "license": "MIT OR Apache-2.0",
6
+ "homepage": "https://github.com/aiswarya797/agentguard#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/aiswarya797/agentguard.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/aiswarya797/agentguard/issues"
13
+ },
14
+ "keywords": [
15
+ "agentguard",
16
+ "codex",
17
+ "macos",
18
+ "cli",
19
+ "memory",
20
+ "scheduler"
21
+ ],
22
+ "os": [
23
+ "darwin"
24
+ ],
25
+ "cpu": [
26
+ "arm64"
27
+ ],
28
+ "bin": {
29
+ "agentguard": "npm/bin/agentguard",
30
+ "agentguardd": "npm/bin/agentguardd"
31
+ },
32
+ "files": [
33
+ "Cargo.lock",
34
+ "Cargo.toml",
35
+ "README.md",
36
+ "crates/",
37
+ "docs/DECISIONS.md",
38
+ "docs/TESTING.md",
39
+ "npm/bin/"
40
+ ],
41
+ "publishConfig": {
42
+ "access": "public"
43
+ }
44
+ }