@artale/pi-pai 4.4.0 → 4.5.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/.gitlab-ci.yml ADDED
@@ -0,0 +1,41 @@
1
+ # Pi Package CI — shared GitLab CI template
2
+ # Use with: include https://warehouse:8888/artale/pi-ci-template/raw/main/.gitlab-ci.yml
3
+ # Or copy directly into each repo.
4
+
5
+ image: node:22-alpine
6
+
7
+ stages:
8
+ - validate
9
+ - test
10
+
11
+ cache:
12
+ paths:
13
+ - node_modules/
14
+
15
+ before_script:
16
+ - node --version
17
+ - npm --version
18
+
19
+ validate:
20
+ stage: validate
21
+ script:
22
+ - echo "Package: $(node -p "require('./package.json').name") v$(node -p "require('./package.json').version")"
23
+ - |
24
+ if [ -f tsconfig.json ]; then
25
+ npm ci --ignore-scripts 2>/dev/null || npm install --ignore-scripts
26
+ npx tsc --noEmit && echo "TypeScript: PASS" || { echo "TypeScript: FAIL"; exit 1; }
27
+ else
28
+ echo "No tsconfig — skipping compile"
29
+ fi
30
+
31
+ test:
32
+ stage: test
33
+ script:
34
+ - |
35
+ if [ -f scripts/test.sh ]; then
36
+ bash scripts/test.sh && echo "Tests: PASS" || { echo "Tests: FAIL"; exit 1; }
37
+ elif [ -f test.sh ]; then
38
+ bash test.sh && echo "Tests: PASS" || { echo "Tests: FAIL"; exit 1; }
39
+ else
40
+ echo "No tests — skipping"
41
+ fi
package/SYSTEM.md.pai CHANGED
@@ -1,14 +1,14 @@
1
1
  # PAI on Pi — Personal AI Infrastructure
2
2
 
3
- You are **{{YOUR_AI_NAME}}**, {{YOUR_NAME}}'s personal AI assistant. You run on the Pi coding agent framework with the full PAI methodology.
3
+ You are **Pi**, Artale's personal AI assistant. You run on the Pi coding agent framework with the full PAI methodology.
4
4
 
5
5
  ## Identity
6
6
 
7
- - **Name:** {{YOUR_AI_NAME}}
8
- - **Principal:** {{YOUR_NAME}}
7
+ - **Name:** Pi
8
+ - **Principal:** Artale
9
9
  - **Personality:** Customize your AI's personality traits below
10
10
  - **Traits:** Enthusiasm 60, Energy 70, Expressiveness 65, Precision 90, Curiosity 85
11
- - First person ("I"), user by name ("{{YOUR_NAME}}", never "the user")
11
+ - First person ("I"), user by name ("Artale", never "the user")
12
12
 
13
13
  ## Modes
14
14
 
@@ -17,7 +17,7 @@ Every response uses exactly one mode. BEFORE ANY WORK, classify the request and
17
17
  **Routing priority (check in this order):**
18
18
 
19
19
  1. **MINIMAL** — Greetings, ratings, simple acknowledgments ("ok", "thanks", "8")
20
- 2. **ALGORITHM** (DEFAULT) — All real and complex work. Use when the task involves ANY of: designing, building, creating, planning, investigating, debugging, troubleshooting, refactoring, researching, analyzing, writing, multi-step work, multiple components, creative output, or anything requiring sustained thought. **When in doubt, ALWAYS use ALGORITHM.**
20
+ 2. **ALGORITHM** (DEFAULT) — All real and complex work. Use when the task involves ANY of: designing, building, creating, planning, investigating, debugging, troubleshooting, refactoring, researching,...
21
21
  3. **NATIVE** (rare exception) — ONLY for simple single-action tasks that require no planning or creativity.
22
22
 
23
23
  ## NATIVE MODE
@@ -32,7 +32,7 @@ Then do the work, then:
32
32
  ```
33
33
  CHANGE: [8-word bullets on what changed]
34
34
  VERIFY: [8-word bullets on how we know what happened]
35
- {{YOUR_AI_NAME}}: [8-16 word summary]
35
+ Pi: [8-16 word summary]
36
36
  ```
37
37
 
38
38
  ## ALGORITHM MODE
@@ -87,14 +87,14 @@ TASK: [8 word description]
87
87
  === PAI ==============================
88
88
  CHANGE: [8-word bullets]
89
89
  VERIFY: [8-word bullets]
90
- {{YOUR_AI_NAME}}: [summary in 8-16 words]
90
+ Pi: [summary in 8-16 words]
91
91
  ```
92
92
 
93
93
  ## Critical Behavioral Rules
94
94
 
95
95
  **Surgical fixes only.** When debugging, make precise targeted corrections. Never delete or rearchitect existing components as a fix.
96
96
 
97
- **Never assert without verification.** NEVER tell {{YOUR_NAME}} something "is" a certain way unless you have verified it. After changes, verify before claiming success.
97
+ **Never assert without verification.** NEVER tell Artale something "is" a certain way unless you have verified it. After changes, verify before claiming success.
98
98
 
99
99
  **First principles over bolt-ons.** Most problems are symptoms. Understand > Simplify > Reduce > Add (last resort).
100
100
 
@@ -104,17 +104,101 @@ VERIFY: [8-word bullets]
104
104
 
105
105
  **Minimal scope.** Only change what was asked. No bonus refactoring.
106
106
 
107
- ## Projects
107
+ ## Factory Infrastructure
108
108
 
109
- Add your projects here:
109
+ The ecosystem runs on engine VPS 77.42.112.29. Key endpoints:
110
110
 
111
- | Project | Path | Stack |
112
- |---------|------|-------|
113
- | Example | ~/Projects/MyProject | Your stack here |
111
+ | Service | Port | Purpose |
112
+ |---------|------|---------|
113
+ | git-proxy (AI Proxy) | 8099 | Routes LLM calls /v1/chat/completions, also serves /factory-status and /health |
114
+ | agent-site (Docs) | 8084 | Factory documentation and agent portal |
115
+ | ollama (LLM) | 11434 | Local model inference |
116
+ | qdrant (Vector DB) | 6333 | Vector storage and retrieval |
117
+ | forgejo (Git) | 3030 | Git hosting |
118
+ | grafana | 3001 | Dashboards and monitoring |
119
+ | prometheus | 9090 | Metrics collection |
120
+ | deploy-webhook | 8098 | Autonomous deploy endpoint (requires auth token) |
121
+
122
+ **Containers:** 25 total — 6 agents, 14 infrastructure, 5 monitoring/deploy. All UP.
123
+
124
+ ## RSI Phases
125
+
126
+ The factory has completed 4 phases of recursive self-improvement:
127
+
128
+ ### Phase 3 — AI builds and deploys
129
+ git-proxy serves /factory-status (JSON factory state) and /health. Agents can autonomously discover factory state via HTTP API. Pattern: agents read docs → design extension → deploy via git-proxy → update docs.
130
+
131
+ ### Phase 4 — Close the loop
132
+ git-proxy serves /deploy endpoint connected to deploy-webhook (port 8098). Agents POST deployment commands with auth token. Autonomous cycle: agents read docs → design → deploy → update docs. Full cycle runs without human intervention in design/deploy phase.
133
+
134
+ ### Phase A — Self-diagnosis cron
135
+ skill_health.py runs every 6 hours on the engine VPS. Checks all 63 DeepMind skills by running test.sh in each skill directory. Reports degraded skills (below 80% pass rate) to deploy-webhook via POST /deploy for auto-patching.
136
+
137
+ ## Available Extensions
138
+
139
+ Extensions at ~/.pi/agent/extensions/:
140
+
141
+ | Extension | Purpose | Key Commands |
142
+ |-----------|---------|--------------|
143
+ | pi-verifier | Two-agent verification system, quiet by default | /verifier on, /verifier quiet, /verifier off |
144
+ | pi-logger | Agent activity logging to JSONL | /logs, log_action tool |
145
+ | pi-scout | Extension ecosystem audit | /scout scan, /scout auto |
146
+ | pi-rsiloop | RSI loop orchestrator with retry logic | /rsiloop run, rsi_status |
147
+ | pi-rsi | RSI ecosystem dashboard | /rsi, /rsi check, /rsi gaps |
148
+ | pi-oracle | Expert advisor subagent | oracle tool |
149
+ | pi-librarian | Codebase context and file discovery | librarian tool |
150
+ | pi-pipeline | Workflow orchestration | pipeline tool |
151
+ | pi-test-gen | Auto-generate tests from contract schemas | /gentest <file>, generate_tests tool |
152
+ | pi-taste | Developer preference learning | /taste, /taste pull, taste_learn tool |
153
+ | pi-design | Design slop repair (7 patterns, 10 smells, OKLCH) | /design fix <file>, /design audit, design_repair tool |
154
+ | pi-seeds | State graph persistence | seeds tool |
155
+ | pi-fork | Parallel agent execution | fork tool |
156
+ | pi-comm | Webhook messenger + desktop notifications | comm tool |
157
+ | pi-agentic-factory | Factory bridge | /factory status, /factory agents |
158
+ | pi-compliance | EU AI Act compliance | comply tool |
159
+
160
+ ## Proxy Routing
161
+
162
+ The git-proxy at port 8099 routes LLM calls:
163
+
164
+ - `go-` prefix models → OpenCode Go ($10/mo flat, 12 models including deepseek-v4-flash, deepseek-v4-pro, kimi-k26, minimax-m27, qwen36-plus)
165
+ - `zen-` prefix → OpenCode Zen ($14.59/mo PRO, includes claude-opus-4-7, gemini-3.1-pro, gpt-5.4-pro)
166
+ - Bare model names (no prefix) → CrofAI ($20/mo + per-token, 2,500 req/day cap)
167
+ - 429 fallback: CrofAI → Go (auto-maps model names for fallback)
168
+
169
+ ## Tool Confusion Repair
170
+
171
+ The proxy includes deterministic tool call repair for open models. Patterns repaired:
172
+ 1. Empty/null objects in optional fields → strip them
173
+ 2. JSON string where array expected → wrap in array
174
+ 3. Markdown links in file paths → extract URL
175
+ 4. null/NULL/None in values → delete
176
+
177
+ ## Design Slop Repair
178
+
179
+ When generating UI/design code, use pi-design tool. Key rules:
180
+ - 7 surface patterns: MONITOR, SHOWCASE, NARRATIVE, FORM, SOCIAL, MEDIA, SHELL
181
+ - 10 design smells to avoid (purple gradients, three-card rows, left-side borders, etc.)
182
+ - Use OKLCH colors instead of HSL for perceptual uniformity
183
+ - Surface pattern determines layout approach before implementation
184
+
185
+ ## DeepMind Skills
186
+
187
+ 63 DeepMind science skills loaded on 3 agents:
188
+ - **hermes** (@alfrednartbot) — primary research agent
189
+ - **fullyhermes** (@fullyhermybot) — secondary research agent
190
+ - **hermes-voice** (port 18790) — voice interface agent
191
+
192
+ Tested every 6h via skill_health.py cron. 80% pass rate threshold triggers auto-patch.
114
193
 
115
194
  ## Environment
116
195
 
117
- - **Machine:** Your machine
118
- - **Terminal:** Your terminal
119
- - **Runtime:** Your preferred runtime
120
- - **Language:** Your preferred language
196
+ - **Machine:** Windows 11 (Git Bash)
197
+ - **Terminal:** Git Bash MINGW64
198
+ - **Runtime:** Node.js via pi CLI
199
+ - **Proxy:** localhost:18901 (grok-proxy.cjs)
200
+ - **Codebase:** ~/Projects/pi-threads/ (extends @earendil-works/pi-coding-agent)
201
+ - **Extensions:** 80 pi-*.ts files at ~/.pi/agent/extensions/
202
+ - **Memory:** 4 canonical entries at ~/.pi/memory/entries.jsonl
203
+ - **Factory VPS:** root@77.42.112.29:2222
204
+ - **Pi config:** ~/.pi/agent/settings.json
@@ -0,0 +1 @@
1
+ {"operation": "prompt", "prompt": "<user_query>\nhi\n</user_query>", "timestamp": "2026-05-18T14:12:26.348907"}
package/package.json CHANGED
@@ -1,65 +1,64 @@
1
- {
2
- "name": "@artale/pi-pai",
3
- "version": "4.4.0",
4
- "description": "Personal AI Infrastructure for Pi \u2014 synced with PAI v1.0.0 + Daniel Miesslers framework + 9 skill categories",
5
- "type": "module",
6
- "main": "src/extension.ts",
7
- "pi": {
8
- "extensions": [
9
- "src/extension.ts"
10
- ],
11
- "commands": [
12
- "status"
13
- ],
14
- "tools": [
15
- "pai_status",
16
- "pai_learn",
17
- "pai_rate"
18
- ],
19
- "skills": [
20
- "agents",
21
- "content-analysis",
22
- "investigation",
23
- "media",
24
- "research",
25
- "scraping",
26
- "security",
27
- "telos",
28
- "thinking"
29
- ]
30
- },
31
- "scripts": {
32
- "build": "tsc",
33
- "test": "pi -e src/extension.ts -p \"say hello and list your /commands and tools\"",
34
- "test:old": "echo \"Legacy tests\""
35
- },
36
- "keywords": [
37
- "pi-package",
38
- "pi-extension",
39
- "pai",
40
- "personal-ai-infrastructure",
41
- "telos",
42
- "ralph-wiggum",
43
- "damage-control",
44
- "goal-tracking",
45
- "learning-loop",
46
- "scientific-method"
47
- ],
48
- "author": "arosstale",
49
- "license": "MIT",
50
- "repository": {
51
- "type": "git",
52
- "url": "https://github.com/arosstale/pi-pai.git"
53
- },
54
- "devDependencies": {
55
- "@types/js-yaml": "^4.0.9",
56
- "@types/node": "^25.0.3",
57
- "typescript": "^5.9.3"
58
- },
59
- "peerDependencies": {
60
- "@mariozechner/pi-coding-agent": ">=0.50.0"
61
- },
62
- "dependencies": {
63
- "js-yaml": "^4.1.1"
64
- }
65
- }
1
+ {
2
+ "name": "@artale/pi-pai",
3
+ "version": "4.5.0",
4
+ "description": "Personal AI Infrastructure for Pi MVI core: minimal, progressive complexity, memory on demand",
5
+ "type": "module",
6
+ "main": "src/pi-pai-core.ts",
7
+ "pi": {
8
+ "extensions": [
9
+ "src/pi-pai-core.ts"
10
+ ],
11
+ "commands": [
12
+ "pai"
13
+ ],
14
+ "tools": [
15
+ "capture_learning"
16
+ ],
17
+ "skills": [
18
+ "agents",
19
+ "content-analysis",
20
+ "investigation",
21
+ "media",
22
+ "research",
23
+ "scraping",
24
+ "security",
25
+ "telos",
26
+ "thinking"
27
+ ],
28
+ "image": "https://unpkg.com/@artale/pi-pai@4.4.1/preview.png"
29
+ },
30
+ "scripts": {
31
+ "build": "tsc",
32
+ "test": "pi -e src/extension.ts -p \"say hello and list your /commands and tools\"",
33
+ "test:old": "echo \"Legacy tests\""
34
+ },
35
+ "keywords": [
36
+ "pi-package",
37
+ "pi-extension",
38
+ "pai",
39
+ "personal-ai-infrastructure",
40
+ "telos",
41
+ "ralph-wiggum",
42
+ "damage-control",
43
+ "goal-tracking",
44
+ "learning-loop",
45
+ "scientific-method"
46
+ ],
47
+ "author": "arosstale",
48
+ "license": "MIT",
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/arosstale/pi-pai.git"
52
+ },
53
+ "devDependencies": {
54
+ "@types/js-yaml": "^4.0.9",
55
+ "@types/node": "^25.0.3",
56
+ "typescript": "^5.9.3"
57
+ },
58
+ "peerDependencies": {
59
+ "@mariozechner/pi-coding-agent": ">=0.50.0"
60
+ },
61
+ "dependencies": {
62
+ "js-yaml": "^4.1.1"
63
+ }
64
+ }
package/preview.png ADDED
Binary file
@@ -0,0 +1,215 @@
1
+ /**
2
+ * pi-pai — Personal AI Infrastructure (Core)
3
+ * Kelsey Hightower MVI: lean core, optional modules loaded on demand.
4
+ * Progressive complexity: simple tasks get zero algorithm overhead.
5
+ *
6
+ * Based on PAI v4.0.3 methodology (ISC, phases, criteria, learning signals).
7
+ * Optional features moved to separate extensions.
8
+ *
9
+ * Install: pi install npm:pi-pai
10
+ *
11
+ * /pai mission|goal|done|loop|next|isc|isca|status|reset
12
+ * capture_learning tool — store signals for cross-session improvement
13
+ */
14
+
15
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
16
+ import { Type } from "@sinclair/typebox";
17
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync, readdirSync } from "fs";
18
+ import { homedir } from "os";
19
+ import { join } from "path";
20
+
21
+ const PAI_DIR = join(homedir(), ".config", "PAI-pi");
22
+ const MEMORY_DIR = join(PAI_DIR, "memory");
23
+ const WORK_DIR = join(MEMORY_DIR, "work");
24
+ const LEARNING_DIR = join(MEMORY_DIR, "learning");
25
+
26
+ for (const dir of [MEMORY_DIR, WORK_DIR, LEARNING_DIR]) {
27
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
28
+ }
29
+
30
+ // ISC minimums per effort level
31
+ const ISC_MINIMUMS: Record<string, number> = {
32
+ standard: 8, extended: 16, advanced: 24, deep: 40, comprehensive: 64,
33
+ };
34
+
35
+ type EffortLevel = keyof typeof ISC_MINIMUMS;
36
+ type AlgorithmPhase = "OBSERVE" | "THINK" | "PLAN" | "BUILD" | "EXECUTE" | "VERIFY" | "LEARN";
37
+ const PHASES: AlgorithmPhase[] = ["OBSERVE", "THINK", "PLAN", "BUILD", "EXECUTE", "VERIFY", "LEARN"];
38
+
39
+ function iscSplittingTest(criterion: string): { pass: boolean; reason?: string } {
40
+ if (/\b(and|as well as|along with)\b/i.test(criterion))
41
+ return { pass: false, reason: "Compound criterion — split into separate ISCs" };
42
+ if (/\b(all|every|each|any|both)\b/i.test(criterion))
43
+ return { pass: false, reason: "Scope word detected — be more specific" };
44
+ const words = criterion.trim().split(/\s+/).length;
45
+ if (words > 20) return { pass: false, reason: "Too long (" + words + " words) — shorten" };
46
+ return { pass: true };
47
+ }
48
+
49
+ interface AntiCriterion {
50
+ id: string;
51
+ description: string;
52
+ severity: "critical" | "high" | "medium";
53
+ }
54
+
55
+ interface Learning {
56
+ insight: string;
57
+ confidence: number;
58
+ category: string;
59
+ timestamp: Date;
60
+ }
61
+
62
+ function readMemory<T>(slug: string): T[] {
63
+ const file = join(MEMORY_DIR, slug + ".jsonl");
64
+ if (!existsSync(file)) return [];
65
+ return readFileSync(file, "utf-8").trim().split("\n").filter(Boolean).map(function(l) { return JSON.parse(l); });
66
+ }
67
+
68
+ function writeMemory<T>(slug: string, data: T): void {
69
+ const file = join(MEMORY_DIR, slug + ".jsonl");
70
+ try { appendFileSync(file, JSON.stringify(data) + "\n"); } catch { /* best effort */ }
71
+ }
72
+
73
+ interface AlgorithmLoop {
74
+ phase: AlgorithmPhase;
75
+ goal: string;
76
+ effort: EffortLevel;
77
+ isc: string[];
78
+ iscA: AntiCriterion[];
79
+ startTime: number;
80
+ data: Record<string, string>;
81
+ }
82
+
83
+ let loop: AlgorithmLoop | null = null;
84
+ let goals: { id: string; title: string; status: string }[] = [];
85
+ let learnings: Learning[] = [];
86
+
87
+ export default function (pi: ExtensionAPI) {
88
+ pi.registerCommand("pai", {
89
+ description: "PAI: mission|goal|done|loop|next|isc|isca|status|reset",
90
+ handler: async function(args, ctx) {
91
+ var parts = (args || "").trim().split(/\s+/);
92
+ var sub = parts[0] ? parts[0].toLowerCase() : "";
93
+ var restStr = parts.slice(1).join(" ");
94
+
95
+ switch (sub) {
96
+ case "mission":
97
+ if (!restStr) { ctx.ui.notify("Usage: /pai mission <statement>", "error"); return; }
98
+ writeMemory("mission", { mission: restStr, ts: new Date().toISOString() });
99
+ ctx.ui.notify("MISSION: " + restStr, "info");
100
+ break;
101
+
102
+ case "goal":
103
+ if (!restStr) { ctx.ui.notify("Usage: /pai goal <title>", "error"); return; }
104
+ var id = "g" + goals.length;
105
+ goals.push({ id: id, title: restStr, status: "active" });
106
+ writeMemory("goals", { id: id, title: restStr, status: "active" });
107
+ ctx.ui.notify("GOAL " + id + ": " + restStr, "info");
108
+ break;
109
+
110
+ case "done":
111
+ var g = goals.find(function(g) { return g.id === restStr; });
112
+ if (!g) { ctx.ui.notify("Goal " + restStr + " not found", "error"); return; }
113
+ g.status = "completed";
114
+ ctx.ui.notify("DONE: " + g.title, "info");
115
+ break;
116
+
117
+ case "loop":
118
+ loop = {
119
+ phase: "OBSERVE",
120
+ goal: restStr || "unnamed",
121
+ effort: "standard",
122
+ isc: [],
123
+ iscA: [],
124
+ startTime: Date.now(),
125
+ data: {},
126
+ };
127
+ ctx.ui.notify("ALGORITHM: " + loop.goal + " [OBSERVE]", "info");
128
+ break;
129
+
130
+ case "isc":
131
+ if (!loop) { ctx.ui.notify("No active loop — /pai loop first", "error"); return; }
132
+ var test = iscSplittingTest(restStr);
133
+ if (!test.pass) { ctx.ui.notify("ISC FAIL: " + test.reason, "warning"); return; }
134
+ loop.isc.push(restStr);
135
+ ctx.ui.notify("ISC-" + loop.isc.length, "info");
136
+ break;
137
+
138
+ case "isca":
139
+ if (!loop) { ctx.ui.notify("No active loop", "error"); return; }
140
+ var sev = /critical|security|data.?loss/i.test(restStr) ? "critical" : "medium" as const;
141
+ loop.iscA.push({ id: "a" + loop.iscA.length, description: restStr, severity: sev });
142
+ ctx.ui.notify("ANTI [" + sev + "]", "info");
143
+ break;
144
+
145
+ case "next":
146
+ if (!loop) { ctx.ui.notify("No active loop", "error"); return; }
147
+ var idx = PHASES.indexOf(loop.phase);
148
+ if (restStr) loop.data[loop.phase] = restStr;
149
+
150
+ // ISC count gate before EXECUTE
151
+ if (loop.phase === "PLAN") {
152
+ var min = ISC_MINIMUMS[loop.effort];
153
+ if (loop.isc.length < min) {
154
+ ctx.ui.notify("ISC GATE: " + loop.isc.length + "/" + min, "warning");
155
+ return;
156
+ }
157
+ }
158
+
159
+ if (idx < PHASES.length - 1) {
160
+ loop.phase = PHASES[idx + 1];
161
+ ctx.ui.notify("-> " + loop.phase, "info");
162
+ } else {
163
+ var elapsed = Math.round((Date.now() - loop.startTime) / 1000);
164
+ writeMemory("cycles", { goal: loop.goal, isc: loop.isc.length, elapsed: elapsed, ts: new Date().toISOString() });
165
+ ctx.ui.notify("LOOP DONE (" + elapsed + "s) " + loop.isc.length + " ISC", "info");
166
+ loop = null;
167
+ }
168
+ break;
169
+
170
+ case "status":
171
+ var memory = readMemory<Record<string, any>>("mission");
172
+ var cycles = readMemory<Record<string, any>>("cycles");
173
+ var mission = memory.length ? memory[memory.length - 1].mission : "Not set";
174
+ var fields: string[] = ["MISSION: " + mission];
175
+ fields.push("Goals: " + goals.filter(function(g) { return g.status === "active"; }).length + " active");
176
+ fields.push("Cycles: " + cycles.length + " completed");
177
+ if (loop) fields.push("LOOP: [" + loop.phase + "] " + loop.isc.length + " ISC");
178
+ ctx.ui.notify(fields.join(" | "), "info");
179
+ break;
180
+
181
+ case "reset":
182
+ loop = null;
183
+ goals = [];
184
+ learnings = [];
185
+ ctx.ui.notify("PAI reset", "warning");
186
+ break;
187
+
188
+ default:
189
+ ctx.ui.notify("/pai mission|goal|done|loop|next|isc|isca|status|reset", "info");
190
+ }
191
+ },
192
+ });
193
+
194
+ // Learning signal tool (on demand, not at startup)
195
+ pi.registerTool({
196
+ name: "capture_learning",
197
+ label: "Learn",
198
+ description: "Capture a learning signal for cross-session improvement",
199
+ parameters: Type.Object({
200
+ insight: Type.String({ description: "What you learned" }),
201
+ category: Type.Optional(Type.String({ description: "algorithm|domain|system|process" })),
202
+ }),
203
+ async execute(_callId: string, params: { insight: string; category?: string }) {
204
+ var entry = { insight: params.insight, category: params.category || "domain", confidence: 0.8, timestamp: new Date().toISOString() };
205
+ writeMemory("signals", entry);
206
+ learnings.push(entry);
207
+ return { content: [{ type: "text" as const, text: "LEARNED: " + params.insight.slice(0, 60) }] };
208
+ },
209
+ });
210
+
211
+ // Simple status line — no heavy initialization
212
+ pi.on("agent_start", async function(_event, ctx) {
213
+ ctx.ui.setStatus("pai", "PAI Core | Algorithm ready");
214
+ });
215
+ }