pi-sage 0.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.
@@ -0,0 +1,116 @@
1
+ # Coding Standards for Sage
2
+
3
+ ## 1) Purpose
4
+
5
+ This document defines the engineering standards for building and evolving Sage.
6
+
7
+ Sage is a **high-reasoning advisory subagent**, not an execution agent. Code should optimize for safety, determinism, observability, and maintainability.
8
+
9
+ ---
10
+
11
+ ## 2) Scope
12
+
13
+ These standards apply to all Sage-related code, including:
14
+ - extension runtime code (`.pi/extensions/sage/*`)
15
+ - settings and policy layers
16
+ - subprocess runner logic
17
+ - prompt/system-guidance injection
18
+ - tests and supporting tooling
19
+
20
+ ---
21
+
22
+ ## 3) Non-Negotiable Product Constraints
23
+
24
+ Every implementation must preserve these behaviors:
25
+
26
+ 1. **Interactive-primary-only invocation**
27
+ - Sage can only be invoked from top-level interactive primary sessions.
28
+ 2. **No recursion**
29
+ - Sage subagents cannot invoke `sage_consult`.
30
+ 3. **Single-shot interaction**
31
+ - One request -> one Sage response; no multi-turn Sage loops.
32
+ 4. **Advisory-only execution model**
33
+ - Sage provides analysis/recommendations, not direct implementation actions.
34
+ 5. **Deny-by-default policy**
35
+ - Unknown/missing caller context must block invocation.
36
+
37
+ ---
38
+
39
+ ## 4) Architecture and Design Principles
40
+
41
+ 1. **Policy-first execution**
42
+ - Evaluate hard gates (caller context, safety) before soft budget checks.
43
+ 2. **Fail safe, not permissive**
44
+ - On ambiguity, block with structured reason codes.
45
+ 3. **Small composable modules**
46
+ - Separate `policy`, `tool-policy`, `runner`, `settings`, and `types`.
47
+ 4. **Pure functions for critical policy logic**
48
+ - Keep eligibility and guardrail checks side-effect-free for easy testing.
49
+ 5. **No hidden behavior**
50
+ - Important policy decisions must be visible in structured metadata.
51
+
52
+ ---
53
+
54
+ ## 5) TypeScript Standards
55
+
56
+ 1. Use strict typing and explicit interfaces for all policy and result contracts.
57
+ 2. Avoid `any`; if unavoidable, isolate and document with rationale.
58
+ 3. Prefer discriminated unions for block codes and policy outcomes.
59
+ 4. Use exhaustive `switch` handling for enums/unions.
60
+ 5. Keep function signatures narrow and intention-revealing.
61
+ 6. Export reusable types from a single `types.ts` module.
62
+
63
+ ---
64
+
65
+ ## 6) Error and Result Handling
66
+
67
+ 1. Return structured block/failure outcomes with stable `blockCode` values.
68
+ 2. Never crash the primary flow due to Sage failure.
69
+ 3. Use consistent result shapes for successful and blocked paths.
70
+ 4. Include user-facing, concise explanations for blocked invocations.
71
+ 5. Preserve diagnostic detail in `details` for debugging and telemetry.
72
+
73
+ ---
74
+
75
+ ## 7) Security and Access Controls
76
+
77
+ 1. Enforce advisory tool policy by default (`read-only-lite`: `ls,glob,grep,read`).
78
+ 2. Disallow mutating/execution/network/orchestration tools in Sage.
79
+ 3. Restrict filesystem reads to workspace/project roots.
80
+ 4. Apply sensitive-path denylist by default (`.env*`, `*.pem`, `*.key`, etc.).
81
+ 5. Enforce per-call volume limits (tool calls/files/bytes/result caps).
82
+
83
+ ---
84
+
85
+ ## 8) Observability Standards
86
+
87
+ Each Sage call should emit enough metadata to explain behavior:
88
+ - invocation mode (`autonomous` vs `user-requested`)
89
+ - caller-context allow/block decision
90
+ - block reason and stable block code when denied
91
+ - model, reasoning level, latency
92
+ - token usage/cost (when available)
93
+ - tool profile and tool usage counters
94
+
95
+ Observability must support both operator trust and debugging efficiency.
96
+
97
+ ---
98
+
99
+ ## 9) Documentation and Change Discipline
100
+
101
+ 1. Keep implementation aligned with `docs/SAGE_SPEC.md` (locked baseline).
102
+ 2. Update spec/docs in the same PR when behavior changes.
103
+ 3. Document policy changes as explicit decisions (not implicit code drift).
104
+ 4. Add short rationale comments for non-obvious guardrails.
105
+
106
+ ---
107
+
108
+ ## 10) Code Review Checklist (Required)
109
+
110
+ - [ ] Interactive-only caller gate remains non-bypassable.
111
+ - [ ] No recursion paths exist (`sage_consult` unavailable to Sage subprocess).
112
+ - [ ] Single-shot behavior preserved.
113
+ - [ ] Tool policy remains advisory/read-only by default.
114
+ - [ ] Blocked and success paths return consistent structured metadata.
115
+ - [ ] New behavior has unit/integration coverage.
116
+ - [ ] Docs/spec updated if behavior changed.
@@ -0,0 +1,70 @@
1
+ # Installation Requirements (End Users)
2
+
3
+ This extension is designed for Pi and is installed as a Pi package.
4
+
5
+ ## Required
6
+
7
+ 1. **Pi CLI installed and on PATH**
8
+ - `pi --version` should work from the shell.
9
+ 2. **Pi 0.64.0+**
10
+ 3. **Model/provider auth configured in Pi**
11
+ - e.g., Anthropic/OpenAI/Gemini keys or OAuth login.
12
+ 4. **Interactive session usage**
13
+ - Sage is intentionally restricted to interactive top-level primary sessions.
14
+
15
+ ## Optional (profile-dependent)
16
+
17
+ - **git CLI**
18
+ - Needed only when using the `git-review-readonly` tool profile.
19
+
20
+ ## Install commands
21
+
22
+ ### Global
23
+
24
+ ```bash
25
+ pi install npm:pi-sage
26
+ ```
27
+
28
+ ### Project-local
29
+
30
+ ```bash
31
+ pi install -l npm:pi-sage
32
+ ```
33
+
34
+ After install, run `/reload` in Pi.
35
+
36
+ ## File locations by install scope
37
+
38
+ ### Global install
39
+
40
+ - Package reference is stored in: `~/.pi/agent/settings.json`
41
+ - Package files are installed with `npm install -g` in npm global node_modules
42
+ - Windows typical: `%APPDATA%/npm/node_modules/pi-sage/`
43
+ - macOS/Linux typical: `<npm-global-prefix>/lib/node_modules/pi-sage/`
44
+
45
+ Find exact global path with:
46
+
47
+ ```bash
48
+ npm root -g
49
+ ```
50
+
51
+ ### Project-local install
52
+
53
+ - Package reference is stored in: `.pi/settings.json`
54
+ - Package files are installed under project-local Pi storage: `.pi/npm/`
55
+
56
+ ## Settings precedence
57
+
58
+ Sage settings resolve in this order:
59
+
60
+ 1. `.pi/sage-settings.json` (project)
61
+ 2. `~/.pi/agent/sage-settings.json` (global)
62
+ 3. defaults
63
+
64
+ This enables a global default configuration with per-project overrides.
65
+
66
+ ## Troubleshooting
67
+
68
+ - If Sage cannot start, verify `pi` is executable in the runtime environment.
69
+ - If no Sage model is found, verify provider auth and model availability.
70
+ - If consultations block on limits, adjust cap settings in `/sage-settings`.
@@ -0,0 +1,46 @@
1
+ # Interactive E2E Harness Plan (Sage)
2
+
3
+ ## Purpose
4
+
5
+ Sage is intentionally restricted to interactive top-level primary sessions.
6
+ Because of this, E2E validation must run through an interactive Pi session path, not RPC-only execution.
7
+
8
+ ## Harness Strategy
9
+
10
+ Use `tmux` to drive a real interactive Pi session:
11
+
12
+ 1. Start a dedicated tmux session for E2E.
13
+ 2. Launch `pi` in interactive mode in the project root.
14
+ 3. Send commands/prompts via `tmux send-keys`.
15
+ 4. Capture output via `tmux capture-pane` and/or parse session JSONL artifacts.
16
+ 5. Assert expected behavior in Node `node:test` suites.
17
+
18
+ ## Core Flows to Validate
19
+
20
+ 1. `/reload` picks up extension changes in-session.
21
+ 2. Eligible caller path can invoke Sage.
22
+ 3. Explicit "second opinion" request invokes Sage in eligible interactive context.
23
+ 4. Ineligible contexts are blocked with structured metadata and no subprocess launch.
24
+
25
+ ## Suggested Script Structure
26
+
27
+ - `scripts/e2e/start-interactive-session.sh`
28
+ - `scripts/e2e/send-input.sh`
29
+ - `scripts/e2e/capture-output.sh`
30
+ - `scripts/e2e/stop-interactive-session.sh`
31
+
32
+ ## Assertion Sources
33
+
34
+ Prefer deterministic artifacts over rendered text where possible:
35
+ - session entries / tool result details
36
+ - structured `policy` block metadata
37
+ - explicit block codes
38
+
39
+ Use pane text capture as supplemental debugging evidence.
40
+
41
+ ## Reliability Notes
42
+
43
+ - Add bounded waits and retry windows for async turn completion.
44
+ - Ensure each test uses an isolated session directory.
45
+ - Clean up tmux sessions even on failure.
46
+ - Keep E2E cases focused and few; rely on unit/integration for matrix depth.
@@ -0,0 +1,175 @@
1
+ # Testing Standards for Sage
2
+
3
+ ## 1) Purpose
4
+
5
+ This document defines the required testing methodology for Sage development.
6
+
7
+ Primary goals:
8
+ - prevent policy regressions
9
+ - detect safety/security drift early
10
+ - keep iteration fast while maintaining high confidence
11
+
12
+ ---
13
+
14
+ ## 2) Testing Philosophy
15
+
16
+ Sage testing follows a layered strategy:
17
+ 1. **Static quality gates** (lint, type checks)
18
+ 2. **Fast deterministic unit tests**
19
+ 3. **Integration tests for policy + runtime boundaries**
20
+ 4. **Interactive E2E tests for real behavior validation**
21
+
22
+ No single layer is sufficient on its own.
23
+
24
+ ### Test runner standard (mandatory)
25
+
26
+ - Use **Node’s built-in test runner** (`node:test`, executed via `node --test`).
27
+ - TypeScript test files are supported via Node-compatible TS execution (`node --import tsx --test ...` or equivalent Node-native setup).
28
+ - **Vitest is not allowed** for this project.
29
+
30
+ ---
31
+
32
+ ## 3) Mandatory Continuous Test Pipeline
33
+
34
+ Every active development loop and PR must include:
35
+
36
+ 1. **Lint** (required)
37
+ 2. **Typecheck** (required)
38
+ 3. **Unit tests** (required)
39
+ 4. **Integration tests** (required)
40
+ 5. **E2E tests** (required for behavior-impacting changes)
41
+
42
+ ### Required command contract
43
+
44
+ The project should provide these scripts (or equivalent), backed by Node's built-in test runner:
45
+
46
+ - `npm run lint`
47
+ - `npm run typecheck`
48
+ - `npm run test:unit` (Node test runner)
49
+ - `npm run test:integration` (Node test runner)
50
+ - `npm run test:e2e` (Node test runner)
51
+ - `npm test` (full suite)
52
+
53
+ If script names differ, document the mapping in this file.
54
+
55
+ ---
56
+
57
+ ## 4) Test Layers and Expectations
58
+
59
+ ## 4.1 Lint (required)
60
+
61
+ Lint must run on every change and fail the pipeline on violations.
62
+
63
+ Minimum expectations:
64
+ - no unused vars/imports
65
+ - no implicit `any` in critical modules
66
+ - no unsafe ignored promise errors
67
+ - no dead/unreachable policy branches
68
+
69
+ ## 4.2 Typecheck (required)
70
+
71
+ Typecheck should run in strict mode for Sage modules and fail on:
72
+ - type unsoundness in policy/result contracts
73
+ - incomplete union handling for block codes
74
+ - incompatible details/result schema changes
75
+
76
+ ## 4.3 Unit Tests (required)
77
+
78
+ Unit tests must cover deterministic logic:
79
+ - caller eligibility gate
80
+ - soft/hard gate ordering
81
+ - tool policy resolution
82
+ - path denylist logic
83
+ - volume cap logic
84
+ - block result construction
85
+
86
+ Target: high branch coverage in policy modules.
87
+
88
+ ## 4.4 Integration Tests (required)
89
+
90
+ Integration tests must validate end-to-end behavior of `sage_consult` handler logic (without relying solely on mocks):
91
+ - explicit request bypasses soft limits only
92
+ - hard caller gate remains non-bypassable
93
+ - RPC roles are blocked
94
+ - non-interactive/CI contexts are blocked
95
+ - advisory tool profile enforcement
96
+ - structured metadata returned for success and blocked cases
97
+
98
+ ## 4.5 E2E Tests (required for behavior changes)
99
+
100
+ Because Sage is interactive-only, E2E tests must exercise a real interactive session path.
101
+
102
+ Required E2E checks:
103
+ - interactive primary can invoke Sage
104
+ - `/reload` workflow preserves extension behavior
105
+ - explicit “second opinion” path triggers Sage in eligible context
106
+ - blocked contexts never spawn Sage subprocess
107
+
108
+ ---
109
+
110
+ ## 5) Sage-Specific Regression Matrix (Must Stay Green)
111
+
112
+ ### Caller-context gating
113
+ - [ ] interactive + primary + non-subagent + non-RPC + non-CI -> allowed
114
+ - [ ] non-interactive -> blocked
115
+ - [ ] CI mode -> blocked
116
+ - [ ] RPC orchestrated role -> blocked
117
+ - [ ] subagent -> blocked
118
+ - [ ] unknown/missing context -> blocked
119
+
120
+ ### Invocation behavior
121
+ - [ ] explicit request bypasses soft limits
122
+ - [ ] explicit request does NOT bypass hard safety limits
123
+ - [ ] explicit request does NOT bypass caller-scope gate
124
+ - [ ] single-shot only
125
+ - [ ] no recursion
126
+
127
+ ### Tool/data policy
128
+ - [ ] default profile is `read-only-lite`
129
+ - [ ] disallowed tools blocked (`edit`, `write`, `bash`, `sage_consult`, etc.)
130
+ - [ ] denylisted paths blocked
131
+ - [ ] volume caps enforced
132
+
133
+ ---
134
+
135
+ ## 6) CI Policy
136
+
137
+ 1. CI must fail fast on lint/typecheck failures.
138
+ 2. Unit+integration must run on every PR.
139
+ 3. E2E must run for policy/runtime changes (or at minimum before merge to main).
140
+ 4. Failing tests block merge unless explicitly waived with documented justification.
141
+ 5. CI test jobs must use Node’s built-in test runner (no Vitest jobs).
142
+
143
+ ---
144
+
145
+ ## 7) Flaky Test Policy
146
+
147
+ 1. Flaky tests are treated as defects, not noise.
148
+ 2. Quarantine only with an owner + issue + deadline.
149
+ 3. No permanent quarantines.
150
+ 4. Add deterministic fixtures/timeouts to reduce nondeterminism.
151
+
152
+ ---
153
+
154
+ ## 8) Artifacts and Diagnostics
155
+
156
+ For failed CI runs, capture:
157
+ - lint output
158
+ - typecheck output
159
+ - failed test logs
160
+ - relevant session/tool metadata for Sage calls
161
+
162
+ Interactive E2E failures should include terminal/session transcripts sufficient for reproduction.
163
+
164
+ ---
165
+
166
+ ## 9) Definition of Done (Testing)
167
+
168
+ A Sage change is test-complete only when:
169
+ - [ ] lint passes
170
+ - [ ] typecheck passes
171
+ - [ ] unit tests pass
172
+ - [ ] integration tests pass
173
+ - [ ] required E2E tests pass
174
+ - [ ] new behavior has coverage and assertions
175
+ - [ ] regressions are not introduced in caller/tool policy gates
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "pi-sage",
3
+ "version": "0.2.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "description": "Interactive-only advisory Sage extension for Pi",
7
+ "keywords": [
8
+ "pi",
9
+ "pi-extension",
10
+ "sage",
11
+ "code-review"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/HenryLach/sage.git"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/HenryLach/sage/issues"
19
+ },
20
+ "homepage": "https://github.com/HenryLach/sage#readme",
21
+ "license": "MIT",
22
+ "files": [
23
+ ".pi/extensions/sage/**",
24
+ "README.md",
25
+ "AGENTS.md",
26
+ "LICENSE",
27
+ "docs/*.md"
28
+ ],
29
+ "pi": {
30
+ "extensions": [
31
+ "./.pi/extensions/sage/index.ts"
32
+ ]
33
+ },
34
+ "engines": {
35
+ "node": ">=22.0.0"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "scripts": {
41
+ "prepare": "husky",
42
+ "lint": "eslint . --ext .ts,.mts,.cts --max-warnings=0",
43
+ "typecheck": "tsc --noEmit",
44
+ "test:unit": "node --import tsx --test test/unit/**/*.test.ts",
45
+ "test:integration": "node --import tsx --test test/integration/**/*.test.ts",
46
+ "test:e2e": "node --import tsx --test test/e2e/**/*.test.ts",
47
+ "test": "npm run lint && npm run typecheck && npm run test:unit && npm run test:integration && npm run test:e2e"
48
+ },
49
+ "dependencies": {
50
+ "@sinclair/typebox": "^0.34.49"
51
+ },
52
+ "devDependencies": {
53
+ "@mariozechner/pi-coding-agent": "^0.64.0",
54
+ "@types/node": "^22.15.3",
55
+ "@typescript-eslint/eslint-plugin": "^8.30.1",
56
+ "@typescript-eslint/parser": "^8.30.1",
57
+ "eslint": "^9.24.0",
58
+ "husky": "^9.1.7",
59
+ "tsx": "^4.19.3",
60
+ "typescript": "^5.8.3"
61
+ }
62
+ }