@artale/pi-pai 4.4.1 → 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 +41 -0
- package/SYSTEM.md.pai +101 -17
- package/agents/context_bundles/MON_14_unknown.jsonl +1 -0
- package/package.json +7 -9
- package/src/pi-pai-core.ts +215 -0
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 **
|
|
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:**
|
|
8
|
-
- **Principal:**
|
|
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 ("
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
##
|
|
107
|
+
## Factory Infrastructure
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
The ecosystem runs on engine VPS 77.42.112.29. Key endpoints:
|
|
110
110
|
|
|
111
|
-
|
|
|
112
|
-
|
|
113
|
-
|
|
|
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:**
|
|
118
|
-
- **Terminal:**
|
|
119
|
-
- **Runtime:**
|
|
120
|
-
- **
|
|
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,20 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@artale/pi-pai",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "Personal AI Infrastructure for Pi —
|
|
3
|
+
"version": "4.5.0",
|
|
4
|
+
"description": "Personal AI Infrastructure for Pi — MVI core: minimal, progressive complexity, memory on demand",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "src/
|
|
6
|
+
"main": "src/pi-pai-core.ts",
|
|
7
7
|
"pi": {
|
|
8
8
|
"extensions": [
|
|
9
|
-
"src/
|
|
9
|
+
"src/pi-pai-core.ts"
|
|
10
10
|
],
|
|
11
11
|
"commands": [
|
|
12
|
-
"
|
|
12
|
+
"pai"
|
|
13
13
|
],
|
|
14
14
|
"tools": [
|
|
15
|
-
"
|
|
16
|
-
"pai_learn",
|
|
17
|
-
"pai_rate"
|
|
15
|
+
"capture_learning"
|
|
18
16
|
],
|
|
19
17
|
"skills": [
|
|
20
18
|
"agents",
|
|
@@ -27,7 +25,7 @@
|
|
|
27
25
|
"telos",
|
|
28
26
|
"thinking"
|
|
29
27
|
],
|
|
30
|
-
"image": "https://
|
|
28
|
+
"image": "https://unpkg.com/@artale/pi-pai@4.4.1/preview.png"
|
|
31
29
|
},
|
|
32
30
|
"scripts": {
|
|
33
31
|
"build": "tsc",
|
|
@@ -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
|
+
}
|