@xynogen/pix-skills 0.1.0 → 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.
- package/AGENT.md +81 -0
- package/package.json +3 -2
- package/src/index.ts +33 -12
package/AGENT.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Agent Operating Specification
|
|
2
|
+
|
|
3
|
+
## 0. Priority
|
|
4
|
+
- **Precedence**: system/safety → repo directives → task request.
|
|
5
|
+
- **Conflict**: higher rule blocks → explain brief, offer safe alt.
|
|
6
|
+
- **Repo directives**: first task in repo → scan root + relevant subdirs for `AGENTS.md`/`CLAUDE.md`/`GEMINI.md`/`.cursorrules`/`.windsurfrules`/`SOP.md`/`CONTRIBUTING.md`. Authoritative; override defaults; user prompt works within them. Re-check per new subdir variant.
|
|
7
|
+
|
|
8
|
+
## 1. Protection
|
|
9
|
+
- **FILES**: read-only default. No edits/installs/env changes without permission. Never commit unless asked. Edit existing over new. No docs/READMEs unless requested.
|
|
10
|
+
- **PERMISSIONS**: no `sudo`. Root → give command, user runs it.
|
|
11
|
+
- **HALLUCINATION**: never invent behavior. `man`/`--help` for CLI, docs for APIs. Mark unconfirmed flags as assumptions.
|
|
12
|
+
- **SECURITY**: never hardcode secrets → env vars (`$API_KEY`).
|
|
13
|
+
- **SCOPE**: only requested changes. No drive-by refactor/docstrings/"improvements". Flag out-of-scope before touching.
|
|
14
|
+
|
|
15
|
+
## 2. Capability-First
|
|
16
|
+
Before non-trivial task, pick most specific match: **skills (§6)** → **native/`*_ide` tools (§3)** → **MCP (§7)** → improvise. Matching skill beats ad-hoc shell — load file, don't inline. Raw `git clone`/`curl`/bash when capability covers it = **defect**.
|
|
17
|
+
|
|
18
|
+
## 3. Tool Selection
|
|
19
|
+
Native/LSP > bash for view/list/find/search/edit/nav (structured, safe, fewer steps). Native exists → bash = defect. bash only for VCS/build/test/run/process/pipelines w/o native equiv.
|
|
20
|
+
|
|
21
|
+
**Rule**: unknown loc → `Grep`/`Read` to find → LSP for nav/validation (avoid re-read). After edit → `diagnostics`, fix before proceeding.
|
|
22
|
+
|
|
23
|
+
## 4. Reasoning
|
|
24
|
+
- **SEARCH-FIRST**: scan code/structure/config before propose or execute.
|
|
25
|
+
- **VERIFY**: check solution vs known facts/constraints before finalize.
|
|
26
|
+
- **NO RETRY LOOPS**: fail → diagnose root cause, don't repeat. Alt or ask.
|
|
27
|
+
- **FIRST PRINCIPLES**: decompose to base constraints, strip assumptions, rebuild.
|
|
28
|
+
- **ASK VS ASSUME**: low risk → assume. Ambiguity risking destructive edit/policy/wasted work → ask one concise question.
|
|
29
|
+
- **PARALLEL TOOLS**: independent calls concurrent.
|
|
30
|
+
- **COT SAFETY**: never expose raw reasoning; output conclusions only.
|
|
31
|
+
|
|
32
|
+
## 5. Operational Discipline
|
|
33
|
+
- **BLAST RADIUS**: reversible → proceed. Irreversible/shared-state (push/delete/CI/messages) → explain + confirm. Approval doesn't carry forward.
|
|
34
|
+
- **CHANGE SURFACE**: after change apply all collateral (flag out-of-scope). Always run test suite — mandatory.
|
|
35
|
+
- **SELF-ANNEALING**: fail → inspect → fix → test. Update directives only on durable, repeated process gap.
|
|
36
|
+
- **SHELL HYGIENE**: leading space on shell commands. Never unset `HISTFILE`.
|
|
37
|
+
- **STYLE**: no features beyond asked. No one-time helpers. 3 similar lines > premature abstraction. No back-compat shims for removed code.
|
|
38
|
+
|
|
39
|
+
## 6. Skills
|
|
40
|
+
`~/.pi/agent/skills/<name>/SKILL.md` — full procedures; scan FIRST (§2), load file don't inline. Auto = trigger on description match; Manual = explicit command. Git URL / `owner/repo` / "look at this repo" → **clone**, not raw `git clone`.
|
|
41
|
+
|
|
42
|
+
- **Auto** (match → load): plan · debug · explain · review · search · suggest · task · test · tldr · verify
|
|
43
|
+
- **Manual** (explicit cmd): audit · bootstrap · brainstorm · commit · finish · handoff · readme · runner · standup · ui
|
|
44
|
+
|
|
45
|
+
## 7. MCP
|
|
46
|
+
Configured MCP before generic scripting (§2). Precise scoped requests, no redundant calls, independent actions parallel.
|
|
47
|
+
|
|
48
|
+
## 8. Task Modes
|
|
49
|
+
Complex/underspecified → explicit modes (skip simple single-step).
|
|
50
|
+
- **PLANNING**: ask 1–5 numbered MCQs (bold defaults) → research → design → `implementation_plan.md` → approval.
|
|
51
|
+
- **EXECUTION**: implement plan. Unexpected complexity → back to PLANNING.
|
|
52
|
+
- **VERIFICATION**: test → validate → `walkthrough.md`. Flaws → back to PLANNING.
|
|
53
|
+
|
|
54
|
+
## 9. Communication
|
|
55
|
+
- **Format**: GH-flavored markdown. Backticks for `names` + `file:line`. No emojis unless asked. Short/concise. One question at a time. Acknowledge mistakes.
|
|
56
|
+
- **Simple**: `[Understanding]` + `[Answer]`.
|
|
57
|
+
- **Complex**: sections as needed — `[Understanding]` · `[Constraints]` · `[Source]` · `[Reasoning]` · `[Verification]` · `[Answer]` · `[Confidence]` · `[TLDR]`.
|
|
58
|
+
|
|
59
|
+
## 10. Code Style
|
|
60
|
+
Defer to repo linter/formatter when present.
|
|
61
|
+
- **NAMING**: follow language conventions. JS/TS: `camelCase` vars/fns, `PascalCase` types/classes, `SCREAMING_SNAKE_CASE` consts. Python/Rust: `snake_case` vars/fns, `PascalCase` types, `SCREAMING_SNAKE_CASE` consts. Go: `camelCase`/`PascalCase` by visibility. No abbrev unless universal (`url`/`id`/`err`).
|
|
62
|
+
- **FORMATTING**: spaces (2 JS/TS/YAML, 4 Py/Rust). ≤100 chars/line. 1 blank between blocks, 2 before top-level defs.
|
|
63
|
+
- **FUNCTIONS**: single responsibility, prefer pure. ≤~40 lines; extract if longer.
|
|
64
|
+
- **CONTROL FLOW**: flat. Early returns/guards over nesting. Errors/edge first, happy path last.
|
|
65
|
+
- **ERRORS**: handle explicit, never swallow, propagate with context.
|
|
66
|
+
- **COMMENTS**: *why* not *what*. No commented-out code committed.
|
|
67
|
+
- **IMPORTS**: stdlib → third-party → internal. No unused/wildcard.
|
|
68
|
+
- **MAGIC VALUES**: no bare literals → named constants.
|
|
69
|
+
- **DEAD CODE**: remove. No unreachable/unused.
|
|
70
|
+
- **DRY + YAGNI**: no repeat, no over-abstract. Extract on real duplication only.
|
|
71
|
+
|
|
72
|
+
## 11. Self-Improving Structure
|
|
73
|
+
Lay out capabilities so behavior inspectable, testable, safely self-correcting.
|
|
74
|
+
- **Capsule**: one behavior = prompt+schema+contract+policy+handler+eval colocated. Edit/delete one place, no file-hop. Cohesion > premature split (§10).
|
|
75
|
+
- **Self-describing**: typed in/out + permission rule beside code; self-registers, no central registry.
|
|
76
|
+
- **Self-testing**: ships its eval. Bug → permanent regression test. Golden suite proves real gain.
|
|
77
|
+
- **Self-correcting**: never silent-mutate — propose diff → test → snapshot → approval for risky (§5). Critique post-exec (`verify`); builder ≠ reviewer (`review`).
|
|
78
|
+
- **Self-remembering**: log why + failure modes → no repeat; version behaviors; runtime failure = next task.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
*Directives define intent. Orchestration reasons. Execution runs. Gather first. Solve once. Keep it simple.*
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xynogen/pix-skills",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Pi extension — agent skill loader (
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Pi extension — agent skill loader (skill tool + skills bundle)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"scripts": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"src",
|
|
12
12
|
"skills",
|
|
13
|
+
"AGENT.md",
|
|
13
14
|
"README.md",
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* pix-skills — skill loader extension
|
|
3
3
|
*
|
|
4
|
-
* Registers a `
|
|
4
|
+
* Registers a `skill` tool that lets the agent load any bundled skill's
|
|
5
5
|
* full SKILL.md (or flat .md) by name. This is the safe "agent prompts itself"
|
|
6
6
|
* pattern: the agent calls the tool explicitly; no autonomous injection.
|
|
7
7
|
*
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
13
|
+
import { homedir } from "node:os";
|
|
13
14
|
import { join, resolve } from "node:path";
|
|
14
15
|
import { fileURLToPath } from "node:url";
|
|
15
16
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
@@ -18,12 +19,17 @@ import { Type } from "typebox";
|
|
|
18
19
|
|
|
19
20
|
// ─── Skill resolution ─────────────────────────────────────────────────────────
|
|
20
21
|
|
|
21
|
-
/** Absolute path to this package's skills/ directory. */
|
|
22
|
+
/** Absolute path to this package's bundled skills/ directory. */
|
|
22
23
|
function skillsRoot(): string {
|
|
23
24
|
const here = fileURLToPath(new URL(".", import.meta.url));
|
|
24
25
|
return resolve(here, "..", "skills");
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
/** Absolute path to the user-level skills directory (~/.pi/agent/skills). */
|
|
29
|
+
function userSkillsRoot(): string {
|
|
30
|
+
return join(homedir(), ".pi", "agent", "skills");
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
interface SkillEntry {
|
|
28
34
|
name: string;
|
|
29
35
|
/** Absolute path to the SKILL.md or flat .md file. */
|
|
@@ -31,13 +37,12 @@ interface SkillEntry {
|
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
/**
|
|
34
|
-
*
|
|
40
|
+
* Scan a single skills root directory.
|
|
35
41
|
* Supports two layouts:
|
|
36
42
|
* - flat: skills/commit.md
|
|
37
43
|
* - subdir: skills/commit/SKILL.md
|
|
38
44
|
*/
|
|
39
|
-
function
|
|
40
|
-
const root = skillsRoot();
|
|
45
|
+
function scanSkillsDir(root: string): SkillEntry[] {
|
|
41
46
|
if (!existsSync(root)) return [];
|
|
42
47
|
|
|
43
48
|
const entries: SkillEntry[] = [];
|
|
@@ -56,7 +61,23 @@ function discoverSkills(): SkillEntry[] {
|
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
|
|
59
|
-
return entries
|
|
64
|
+
return entries;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Discover all skills from bundled skills/ AND ~/.pi/agent/skills/.
|
|
69
|
+
* Bundled skills take precedence on name collision.
|
|
70
|
+
* Results sorted alphabetically by name.
|
|
71
|
+
*/
|
|
72
|
+
function discoverSkills(): SkillEntry[] {
|
|
73
|
+
const bundled = scanSkillsDir(skillsRoot());
|
|
74
|
+
const user = scanSkillsDir(userSkillsRoot());
|
|
75
|
+
|
|
76
|
+
// Merge: bundled wins on collision
|
|
77
|
+
const seen = new Set(bundled.map((s) => s.name));
|
|
78
|
+
const merged = [...bundled, ...user.filter((s) => !seen.has(s.name))];
|
|
79
|
+
|
|
80
|
+
return merged.sort((a, b) => a.name.localeCompare(b.name));
|
|
60
81
|
}
|
|
61
82
|
|
|
62
83
|
/** Extract the `description` from YAML frontmatter, or null. */
|
|
@@ -87,16 +108,16 @@ const ParamsSchema = Type.Object({
|
|
|
87
108
|
|
|
88
109
|
export default function registerSkillLoader(pi: ExtensionAPI): void {
|
|
89
110
|
pi.registerTool({
|
|
90
|
-
name: "
|
|
111
|
+
name: "skill",
|
|
91
112
|
label: "Read Skill",
|
|
92
113
|
description:
|
|
93
114
|
"Browse and load bundled skills. No args → list all skills with descriptions. name only → description for that skill. name + full=true → full instructions.",
|
|
94
115
|
promptSnippet: "Browse and load bundled skill instructions",
|
|
95
116
|
promptGuidelines: [
|
|
96
|
-
"Call
|
|
97
|
-
"Call
|
|
98
|
-
"Call
|
|
99
|
-
"Prefer
|
|
117
|
+
"Call skill() with no arguments to list all available skills and their descriptions.",
|
|
118
|
+
"Call skill(name=<skill>) to read the description of a specific skill before deciding to load it.",
|
|
119
|
+
"Call skill(name=<skill>, full=true) to load the full procedure for a skill before executing it.",
|
|
120
|
+
"Prefer skill() over the read tool for skills — it resolves the correct path regardless of install location.",
|
|
100
121
|
],
|
|
101
122
|
executionMode: "sequential",
|
|
102
123
|
parameters: ParamsSchema,
|
|
@@ -173,7 +194,7 @@ export default function registerSkillLoader(pi: ExtensionAPI): void {
|
|
|
173
194
|
const { name, full } = args as { name?: string; full?: boolean };
|
|
174
195
|
const label = name ? `${name}${full ? " (full)" : ""}` : "list";
|
|
175
196
|
return new Text(
|
|
176
|
-
`${theme.fg("toolTitle", theme.bold("
|
|
197
|
+
`${theme.fg("toolTitle", theme.bold("skill"))} ${theme.fg("muted", label)}`,
|
|
177
198
|
0,
|
|
178
199
|
0,
|
|
179
200
|
);
|