pi-para 0.5.2
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/CHANGELOG.md +214 -0
- package/README.md +305 -0
- package/SETUP.md +171 -0
- package/dist/capture.d.ts +34 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +461 -0
- package/dist/capture.js.map +1 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +405 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands.d.ts +15 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +786 -0
- package/dist/commands.js.map +1 -0
- package/dist/context.d.ts +61 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +289 -0
- package/dist/context.js.map +1 -0
- package/dist/daemon.d.ts +49 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +226 -0
- package/dist/daemon.js.map +1 -0
- package/dist/frontmatter.d.ts +59 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +170 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/gepa/dataset.d.ts +36 -0
- package/dist/gepa/dataset.d.ts.map +1 -0
- package/dist/gepa/dataset.js +148 -0
- package/dist/gepa/dataset.js.map +1 -0
- package/dist/gepa/evaluator.d.ts +51 -0
- package/dist/gepa/evaluator.d.ts.map +1 -0
- package/dist/gepa/evaluator.js +317 -0
- package/dist/gepa/evaluator.js.map +1 -0
- package/dist/gepa/index.d.ts +66 -0
- package/dist/gepa/index.d.ts.map +1 -0
- package/dist/gepa/index.js +240 -0
- package/dist/gepa/index.js.map +1 -0
- package/dist/gepa/llm.d.ts +35 -0
- package/dist/gepa/llm.d.ts.map +1 -0
- package/dist/gepa/llm.js +268 -0
- package/dist/gepa/llm.js.map +1 -0
- package/dist/gepa/optimized/capture-prompt.txt +65 -0
- package/dist/gepa/optimizer.d.ts +29 -0
- package/dist/gepa/optimizer.d.ts.map +1 -0
- package/dist/gepa/optimizer.js +249 -0
- package/dist/gepa/optimizer.js.map +1 -0
- package/dist/gepa/targets.d.ts +39 -0
- package/dist/gepa/targets.d.ts.map +1 -0
- package/dist/gepa/targets.js +326 -0
- package/dist/gepa/targets.js.map +1 -0
- package/dist/gepa/types.d.ts +168 -0
- package/dist/gepa/types.d.ts.map +1 -0
- package/dist/gepa/types.js +124 -0
- package/dist/gepa/types.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +294 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest.d.ts +88 -0
- package/dist/ingest.d.ts.map +1 -0
- package/dist/ingest.js +105 -0
- package/dist/ingest.js.map +1 -0
- package/dist/link-discovery.d.ts +40 -0
- package/dist/link-discovery.d.ts.map +1 -0
- package/dist/link-discovery.js +122 -0
- package/dist/link-discovery.js.map +1 -0
- package/dist/link-utils.d.ts +30 -0
- package/dist/link-utils.d.ts.map +1 -0
- package/dist/link-utils.js +145 -0
- package/dist/link-utils.js.map +1 -0
- package/dist/lint.d.ts +39 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +827 -0
- package/dist/lint.js.map +1 -0
- package/dist/maintainer.d.ts +24 -0
- package/dist/maintainer.d.ts.map +1 -0
- package/dist/maintainer.js +358 -0
- package/dist/maintainer.js.map +1 -0
- package/dist/processor.d.ts +14 -0
- package/dist/processor.d.ts.map +1 -0
- package/dist/processor.js +361 -0
- package/dist/processor.js.map +1 -0
- package/dist/query.d.ts +69 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +107 -0
- package/dist/query.js.map +1 -0
- package/dist/raw.d.ts +57 -0
- package/dist/raw.d.ts.map +1 -0
- package/dist/raw.js +219 -0
- package/dist/raw.js.map +1 -0
- package/dist/redact.d.ts +21 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +143 -0
- package/dist/redact.js.map +1 -0
- package/dist/scope.d.ts +54 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +161 -0
- package/dist/scope.js.map +1 -0
- package/dist/scripts/bulk-link-fix.d.ts +9 -0
- package/dist/scripts/bulk-link-fix.d.ts.map +1 -0
- package/dist/scripts/bulk-link-fix.js +106 -0
- package/dist/scripts/bulk-link-fix.js.map +1 -0
- package/dist/session-tools.d.ts +33 -0
- package/dist/session-tools.d.ts.map +1 -0
- package/dist/session-tools.js +211 -0
- package/dist/session-tools.js.map +1 -0
- package/dist/state.d.ts +54 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +176 -0
- package/dist/state.js.map +1 -0
- package/dist/store.d.ts +56 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +227 -0
- package/dist/store.js.map +1 -0
- package/dist/summarize.d.ts +56 -0
- package/dist/summarize.d.ts.map +1 -0
- package/dist/summarize.js +231 -0
- package/dist/summarize.js.map +1 -0
- package/dist/tag-registry.d.ts +56 -0
- package/dist/tag-registry.d.ts.map +1 -0
- package/dist/tag-registry.js +146 -0
- package/dist/tag-registry.js.map +1 -0
- package/dist/templates/prompts.d.ts +63 -0
- package/dist/templates/prompts.d.ts.map +1 -0
- package/dist/templates/prompts.js +260 -0
- package/dist/templates/prompts.js.map +1 -0
- package/dist/tools.d.ts +26 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +1033 -0
- package/dist/tools.js.map +1 -0
- package/dist/watcher.d.ts +25 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +84 -0
- package/dist/watcher.js.map +1 -0
- package/dist/webui/client/dist/index.html +1885 -0
- package/dist/webui/server.d.ts +31 -0
- package/dist/webui/server.d.ts.map +1 -0
- package/dist/webui/server.js +566 -0
- package/dist/webui/server.js.map +1 -0
- package/dist/wiki.d.ts +103 -0
- package/dist/wiki.d.ts.map +1 -0
- package/dist/wiki.js +428 -0
- package/dist/wiki.js.map +1 -0
- package/package.json +142 -0
- package/scripts/gepa/__pycache__/dataset.cpython-313.pyc +0 -0
- package/scripts/gepa/__pycache__/lm_providers.cpython-313.pyc +0 -0
- package/scripts/gepa/__pycache__/metric.cpython-313.pyc +0 -0
- package/scripts/gepa/__pycache__/program.cpython-313.pyc +0 -0
- package/scripts/gepa/__pycache__/wiki_reader.cpython-313.pyc +0 -0
- package/scripts/gepa/dataset.py +192 -0
- package/scripts/gepa/lm_providers.py +472 -0
- package/scripts/gepa/metric.py +279 -0
- package/scripts/gepa/optimize.py +367 -0
- package/scripts/gepa/program.py +99 -0
- package/scripts/gepa/pyproject.toml +19 -0
- package/scripts/gepa/run-all.sh +53 -0
- package/scripts/gepa/uv.lock +2241 -0
- package/scripts/gepa/wiki_reader.py +113 -0
- package/skills/para/SKILL.md +77 -0
- package/skills/setup/SKILL.md +20 -0
- package/src/capture.ts +563 -0
- package/src/cli.ts +416 -0
- package/src/commands.ts +878 -0
- package/src/context.ts +390 -0
- package/src/daemon.ts +288 -0
- package/src/frontmatter.ts +219 -0
- package/src/gepa/index.ts +287 -0
- package/src/gepa/optimized/capture-prompt.txt +65 -0
- package/src/index.ts +384 -0
- package/src/ingest.ts +177 -0
- package/src/link-discovery.ts +170 -0
- package/src/link-utils.ts +169 -0
- package/src/lint.ts +1018 -0
- package/src/maintainer.ts +404 -0
- package/src/processor.ts +415 -0
- package/src/python/__pycache__/minimax_lm.cpython-312.pyc +0 -0
- package/src/python/minimax_lm.py +198 -0
- package/src/python/rlm_capture.py +215 -0
- package/src/query.ts +148 -0
- package/src/raw.ts +276 -0
- package/src/redact.ts +159 -0
- package/src/scope.ts +214 -0
- package/src/scripts/bulk-link-fix.ts +126 -0
- package/src/session-tools.ts +260 -0
- package/src/state.ts +271 -0
- package/src/store.ts +288 -0
- package/src/summarize.ts +273 -0
- package/src/tag-registry.ts +157 -0
- package/src/templates/index.md +17 -0
- package/src/templates/prompts.ts +274 -0
- package/src/templates/schema.md +116 -0
- package/src/tools.ts +1293 -0
- package/src/watcher.ts +101 -0
- package/src/webui/client/dist/index.html +1885 -0
- package/src/webui/server.ts +765 -0
- package/src/wiki.ts +550 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical tag registry — normalizes and deduplicates wiki page tags.
|
|
3
|
+
*
|
|
4
|
+
* Rules:
|
|
5
|
+
* 1. Spaces → hyphens ("session files" → "session-files")
|
|
6
|
+
* 2. Lowercase everything
|
|
7
|
+
* 3. Map aliases → canonical tags
|
|
8
|
+
* 4. Remove tags that duplicate scope values on the same page
|
|
9
|
+
* 5. Deduplicate
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// -- Scope normalization -----------------------------------------------------
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Normalize a scope value.
|
|
16
|
+
*
|
|
17
|
+
* Scope should be a project name (kebab-case, single token), not a topic
|
|
18
|
+
* description. The daemon LLM sometimes writes freeform multi-word
|
|
19
|
+
* descriptions like "session exploration" or "mono project" as scope.
|
|
20
|
+
*
|
|
21
|
+
* Rules:
|
|
22
|
+
* 1. Trim + lowercase
|
|
23
|
+
* 2. If the value contains a known project name as a prefix, extract it
|
|
24
|
+
* (e.g. "pi-para daemon" → "pi-para", "pi-mono project" → "pi-mono")
|
|
25
|
+
* 3. If still multi-word after extraction, drop it — it's a topic
|
|
26
|
+
* description, not a project name
|
|
27
|
+
* 4. Return the clean kebab-case scope
|
|
28
|
+
*
|
|
29
|
+
* This is project-agnostic — works for any project, not just pi-para.
|
|
30
|
+
*/
|
|
31
|
+
export function normalizeScope(scope: string): string | null {
|
|
32
|
+
const s = scope.trim().toLowerCase();
|
|
33
|
+
if (!s) return null;
|
|
34
|
+
|
|
35
|
+
// Already clean (no spaces) — pass through
|
|
36
|
+
if (!s.includes(" ")) return s;
|
|
37
|
+
|
|
38
|
+
// Try to extract a kebab-case project name prefix.
|
|
39
|
+
// Multi-word scopes from the LLM follow the pattern:
|
|
40
|
+
// "<project-name> <topic words>" e.g. "pi-mono project", "pi-para daemon"
|
|
41
|
+
// Extract the first kebab-case token if it looks like a project name.
|
|
42
|
+
const firstToken = s.split(" ")[0];
|
|
43
|
+
if (firstToken && firstToken.includes("-")) {
|
|
44
|
+
// Looks like a kebab-case project name (e.g. "pi-mono", "pi-para")
|
|
45
|
+
return firstToken;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Multi-word without a kebab prefix → topic description, drop it
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Normalize a full scope list:
|
|
54
|
+
* 1. Normalize each value
|
|
55
|
+
* 2. Deduplicate
|
|
56
|
+
* 3. Ensure at least one scope remains (fallback to "global")
|
|
57
|
+
*/
|
|
58
|
+
export function normalizeScopes(scopes: string[]): string[] {
|
|
59
|
+
const result = new Set<string>();
|
|
60
|
+
for (const s of scopes) {
|
|
61
|
+
const normalized = normalizeScope(s);
|
|
62
|
+
if (normalized) result.add(normalized);
|
|
63
|
+
}
|
|
64
|
+
if (result.size === 0) result.add("global");
|
|
65
|
+
return [...result].sort();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// -- Tag normalization -------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
/** Canonical tag → list of aliases that map to it. */
|
|
71
|
+
const TAG_ALIASES: Record<string, string[]> = {
|
|
72
|
+
// session/capture family
|
|
73
|
+
"session-capture": ["capture", "background-capture", "session"],
|
|
74
|
+
"session-files": ["session files"],
|
|
75
|
+
|
|
76
|
+
// project identity
|
|
77
|
+
"pi-para": ["para"],
|
|
78
|
+
"pi-mono": ["mono"],
|
|
79
|
+
"coding-agent": ["agent"],
|
|
80
|
+
|
|
81
|
+
// tech
|
|
82
|
+
"node-llama-cpp": [],
|
|
83
|
+
"qmd-search": ["bm25"],
|
|
84
|
+
"lazy-loading": [],
|
|
85
|
+
|
|
86
|
+
// kebab-case normalization
|
|
87
|
+
"scope-detection": ["scope detection"],
|
|
88
|
+
"project-structure": ["project structure", "structure"],
|
|
89
|
+
"model-registry": ["model registry"],
|
|
90
|
+
"thinking-level": ["thinking level"],
|
|
91
|
+
"interactive-mode": ["interactive mode"],
|
|
92
|
+
"exploration-incomplete": ["exploration incomplete"],
|
|
93
|
+
"ui-component": ["UI component"],
|
|
94
|
+
"scoped-models": ["scopedModels"],
|
|
95
|
+
"github-packages": [],
|
|
96
|
+
"architecture-pattern": [],
|
|
97
|
+
"knowledge-management": ["knowledge-base"],
|
|
98
|
+
|
|
99
|
+
// UI
|
|
100
|
+
"webui": ["ui", "frontend", "react"],
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/** Build reverse lookup: alias → canonical. */
|
|
104
|
+
function buildAliasMap(): Map<string, string> {
|
|
105
|
+
const map = new Map<string, string>();
|
|
106
|
+
for (const [canonical, aliases] of Object.entries(TAG_ALIASES)) {
|
|
107
|
+
for (const alias of aliases) {
|
|
108
|
+
map.set(alias.toLowerCase(), canonical);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return map;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const ALIAS_MAP = buildAliasMap();
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Normalize a single tag:
|
|
118
|
+
* 1. Trim + lowercase
|
|
119
|
+
* 2. Spaces → hyphens
|
|
120
|
+
* 3. Resolve alias → canonical
|
|
121
|
+
*/
|
|
122
|
+
export function normalizeTag(tag: string): string {
|
|
123
|
+
let t = tag.trim().toLowerCase().replace(/\s+/g, "-");
|
|
124
|
+
const canonical = ALIAS_MAP.get(t);
|
|
125
|
+
if (canonical) t = canonical;
|
|
126
|
+
return t;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Normalize a full tag list for a page, given its scope.
|
|
131
|
+
*
|
|
132
|
+
* 1. Normalize each tag
|
|
133
|
+
* 2. Remove tags that exactly match a scope value
|
|
134
|
+
* 3. Deduplicate
|
|
135
|
+
* 4. Sort alphabetically
|
|
136
|
+
*/
|
|
137
|
+
export function normalizeTags(tags: string[], scope: string[]): string[] {
|
|
138
|
+
const scopeSet = new Set(scope.map(s => s.toLowerCase()));
|
|
139
|
+
const normalized = new Set<string>();
|
|
140
|
+
|
|
141
|
+
for (const tag of tags) {
|
|
142
|
+
const t = normalizeTag(tag);
|
|
143
|
+
if (!t) continue;
|
|
144
|
+
// Don't add tags that duplicate scope
|
|
145
|
+
if (scopeSet.has(t)) continue;
|
|
146
|
+
normalized.add(t);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return [...normalized].sort();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get the full alias map for external inspection (e.g., lint reporting).
|
|
154
|
+
*/
|
|
155
|
+
export function getAliasMap(): ReadonlyMap<string, string> {
|
|
156
|
+
return ALIAS_MAP;
|
|
157
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM prompt templates for ingest, query, lint, capture, and summarize operations.
|
|
3
|
+
*
|
|
4
|
+
* Use getPrompt(name) to load the GEPA-optimized version (if deployed) or the original.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
8
|
+
import { join, dirname } from "node:path";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Load a prompt by name — returns the GEPA-optimized version if
|
|
13
|
+
* config.gepa.useOptimized is true, otherwise returns the original.
|
|
14
|
+
*
|
|
15
|
+
* Resolution order:
|
|
16
|
+
* 1. User-generated optimized prompt at ~/.pi/wiki/gepa/optimized/{name}.txt
|
|
17
|
+
* 2. Bundled optimized prompt shipped with the package (src/gepa/optimized/{name}.txt)
|
|
18
|
+
* 3. Original constant from this file
|
|
19
|
+
*/
|
|
20
|
+
export function getPrompt(name: string): string {
|
|
21
|
+
const original = _originals()[name];
|
|
22
|
+
if (!original) return "";
|
|
23
|
+
try {
|
|
24
|
+
const cfgPath = join(homedir(), ".pi", "wiki", "config.json");
|
|
25
|
+
if (!existsSync(cfgPath)) return original;
|
|
26
|
+
const cfg = JSON.parse(readFileSync(cfgPath, "utf-8"));
|
|
27
|
+
if (!cfg.gepa?.useOptimized) return original;
|
|
28
|
+
|
|
29
|
+
// 1. Check user-generated optimized prompt
|
|
30
|
+
const userPath = join(homedir(), ".pi", "wiki", "gepa", "optimized", `${name}.txt`);
|
|
31
|
+
if (existsSync(userPath)) {
|
|
32
|
+
const content = readFileSync(userPath, "utf-8").trim();
|
|
33
|
+
if (content.length > 50) return content;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 2. Check bundled optimized prompt (shipped with package)
|
|
37
|
+
const bundledPath = join(dirname(new URL(import.meta.url).pathname), "..", "gepa", "optimized", `${name}.txt`);
|
|
38
|
+
if (existsSync(bundledPath)) {
|
|
39
|
+
const content = readFileSync(bundledPath, "utf-8").trim();
|
|
40
|
+
if (content.length > 50) return content;
|
|
41
|
+
}
|
|
42
|
+
} catch { /* fall through to original */ }
|
|
43
|
+
return original;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function _originals(): Record<string, string> {
|
|
47
|
+
return {
|
|
48
|
+
"wiki-system-prompt": WIKI_SYSTEM_PROMPT,
|
|
49
|
+
"ingest-prompt": INGEST_PROMPT,
|
|
50
|
+
"query-prompt": QUERY_PROMPT,
|
|
51
|
+
"capture-system-prompt": CAPTURE_SYSTEM_PROMPT,
|
|
52
|
+
"capture-prompt": CAPTURE_PROMPT,
|
|
53
|
+
"explicit-capture-prompt": EXPLICIT_CAPTURE_PROMPT,
|
|
54
|
+
"summarize-system-prompt": SUMMARIZE_SYSTEM_PROMPT,
|
|
55
|
+
"iterative-update-prompt": ITERATIVE_UPDATE_PROMPT,
|
|
56
|
+
"overview-prompt": OVERVIEW_PROMPT,
|
|
57
|
+
"lint-prompt": LINT_PROMPT,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// -- Wiki System Prompt (standalone agent) ------------------------------------
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* System prompt for the standalone wiki agent used in capture, lint, and
|
|
65
|
+
* summarize operations. This agent runs outside the session's agent loop.
|
|
66
|
+
*/
|
|
67
|
+
export const WIKI_SYSTEM_PROMPT = `You are a wiki knowledge management agent. You maintain a PARA-structured knowledge base.
|
|
68
|
+
|
|
69
|
+
Your job is to read content, extract knowledge, and write structured wiki pages. You operate autonomously — no user confirmation needed.
|
|
70
|
+
|
|
71
|
+
PARA category rules:
|
|
72
|
+
- **resources/**: Use for almost everything — architecture docs, how-tos, debugging solutions, configs, patterns, implementation notes. This is the default.
|
|
73
|
+
- **areas/**: Only for ongoing responsibilities with no end date (e.g. server config, deployment procedures).
|
|
74
|
+
- **projects/**: ONLY for actual goals with a defined end date and completion criteria. Do NOT use for documentation about a project's internals.
|
|
75
|
+
- **archives/**: Never create pages here — pages get moved here when completed.
|
|
76
|
+
|
|
77
|
+
When the user defines a specific goal with a completion condition, create a projects/ page. When identifying a repeating responsibility (monitoring, maintenance, quality), create an areas/ page.
|
|
78
|
+
|
|
79
|
+
Scope and tag rules:
|
|
80
|
+
- scope must be a kebab-case project name (e.g. "pi-para", "qmd"). NOT topic descriptions like "session exploration".
|
|
81
|
+
- tags must be kebab-case (no spaces). Don't duplicate scope values as tags.
|
|
82
|
+
|
|
83
|
+
Content rules:
|
|
84
|
+
- Use [[wikilinks]] to connect related pages. Always add a ## Connections section.
|
|
85
|
+
- Use the wiki summary format: Topic, Key Facts, Insights, Connections, Open Questions, Sources
|
|
86
|
+
- Keep pages focused on one concept each
|
|
87
|
+
- Be concise and factual — no fluff
|
|
88
|
+
- Check for existing similar pages before creating new ones to avoid duplicates
|
|
89
|
+
- NEVER include API keys, tokens, passwords, or secrets. Document WHERE they are stored, not the values.
|
|
90
|
+
- Index is auto-rebuilt after every write — do not manage index.md manually. Do NOT pass indexContent to wiki_write.`;
|
|
91
|
+
|
|
92
|
+
// -- Ingest Prompts ----------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Prompt included in the tool result when the LLM processes an ingested source.
|
|
96
|
+
* The LLM reads this along with the source content, schema, and current index.
|
|
97
|
+
*/
|
|
98
|
+
export const INGEST_PROMPT = `Analyze the source content below and integrate it into the wiki.
|
|
99
|
+
|
|
100
|
+
Instructions:
|
|
101
|
+
1. Identify key entities, concepts, facts, and relationships in the source
|
|
102
|
+
2. Review the current index to find existing pages that should be updated
|
|
103
|
+
3. Decide which existing wiki pages need updates and what new pages to create
|
|
104
|
+
4. For each page, use the wiki summary format:
|
|
105
|
+
- Topic: what this page covers
|
|
106
|
+
- Key Facts: established knowledge points
|
|
107
|
+
- Insights: non-obvious findings, patterns, implications
|
|
108
|
+
- Connections: [[wikilinks]] to related pages with descriptions
|
|
109
|
+
- Open Questions: gaps in knowledge, unresolved contradictions
|
|
110
|
+
- Sources: source URLs, file paths, session references
|
|
111
|
+
5. Assign PARA category correctly:
|
|
112
|
+
- resources/ for reference material (DEFAULT — use this for most pages)
|
|
113
|
+
- areas/ for ongoing responsibilities
|
|
114
|
+
- projects/ ONLY for actual goals with end dates
|
|
115
|
+
6. scope must be a kebab-case project name (NOT topic descriptions). tags must be kebab-case (no spaces).
|
|
116
|
+
7. Always add [[wikilinks]] and a ## Connections section linking related pages
|
|
117
|
+
8. Flag any contradictions with existing wiki content in Open Questions
|
|
118
|
+
9. When updating existing pages with new information, check whether existing Key Facts are still accurate in light of the new source. If the new source contradicts existing facts, update them and note the change in Open Questions.
|
|
119
|
+
10. Do NOT pass indexContent to wiki_write — the index is auto-rebuilt from all pages on disk.`;
|
|
120
|
+
|
|
121
|
+
// -- Query Prompts -----------------------------------------------------------
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Prompt sent when the LLM synthesizes an answer from wiki search results.
|
|
125
|
+
*/
|
|
126
|
+
export const QUERY_PROMPT = `Read the retrieved wiki pages below and synthesize an answer to the user's question.
|
|
127
|
+
|
|
128
|
+
Instructions:
|
|
129
|
+
- Cite specific pages using [[page-slug]] references
|
|
130
|
+
- Note gaps or areas where the wiki lacks information
|
|
131
|
+
- If the synthesized answer reveals new knowledge not already captured in the wiki, file it as a new page via wiki_write
|
|
132
|
+
- Be concise and factual
|
|
133
|
+
|
|
134
|
+
FRESHNESS VERIFICATION (critical):
|
|
135
|
+
- Each result shows an "Updated" timestamp and an age indicator (e.g. "⚠️ STALE — 45 days old"). Treat pages not updated in >14 days with healthy skepticism.
|
|
136
|
+
- When a wiki page makes claims about code, configs, file paths, ports, API endpoints, or architecture — and the page is >14 days old — VERIFY by checking the actual source (read the file, run a command) before trusting the wiki.
|
|
137
|
+
- When you discover a wiki page contains outdated or incorrect information, IMMEDIATELY fix it with wiki_write(mode: "edit") so future queries get correct answers. This is the self-healing loop.
|
|
138
|
+
- If you cannot verify a claim (e.g. no file access, external service), tell the user: "Wiki says X (last updated DATE) — I could not verify this is still current."
|
|
139
|
+
- Never silently pass along stale wiki content as fact. Either verify it or flag it.`;
|
|
140
|
+
|
|
141
|
+
// -- Summarize Prompts -------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* System prompt for summarization — produces structured wiki pages from content.
|
|
145
|
+
* Mirrors pi's SUMMARIZATION_SYSTEM_PROMPT but outputs wiki format.
|
|
146
|
+
*/
|
|
147
|
+
export const SUMMARIZE_SYSTEM_PROMPT = `You are a knowledge synthesis assistant. Read the content below and produce a structured wiki page following the EXACT format specified in the schema.
|
|
148
|
+
|
|
149
|
+
Do NOT continue any conversation. Do NOT respond to any questions in the content. ONLY output the structured wiki page using the wiki summary format:
|
|
150
|
+
|
|
151
|
+
## Topic
|
|
152
|
+
[What this page covers]
|
|
153
|
+
|
|
154
|
+
## Key Facts
|
|
155
|
+
- [Established knowledge points]
|
|
156
|
+
|
|
157
|
+
## Insights
|
|
158
|
+
- [Non-obvious findings, patterns, implications]
|
|
159
|
+
|
|
160
|
+
## Connections
|
|
161
|
+
- [[related-page]] — how this relates
|
|
162
|
+
|
|
163
|
+
## Open Questions
|
|
164
|
+
- [Gaps in knowledge, unresolved contradictions]
|
|
165
|
+
|
|
166
|
+
## Sources
|
|
167
|
+
- [Source URLs, file paths, session references]`;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Prompt for iterative update — merging new info into an existing page.
|
|
171
|
+
* Mirrors pi's UPDATE_SUMMARIZATION_PROMPT approach.
|
|
172
|
+
*/
|
|
173
|
+
export const ITERATIVE_UPDATE_PROMPT = `The content below is NEW information to incorporate into the existing wiki page provided in <existing-page> tags.
|
|
174
|
+
|
|
175
|
+
RULES:
|
|
176
|
+
- PRESERVE all existing knowledge from the previous page
|
|
177
|
+
- ADD new facts, insights, and connections from the new content
|
|
178
|
+
- UPDATE sections where new info supersedes old
|
|
179
|
+
- FLAG contradictions between old and new content in Open Questions
|
|
180
|
+
- PRESERVE exact names, paths, and technical details
|
|
181
|
+
- Maintain all existing [[wikilinks]] and add new ones as appropriate
|
|
182
|
+
- Update the Sources section to include the new source`;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Prompt for overview generation from multiple pages.
|
|
186
|
+
*/
|
|
187
|
+
export const OVERVIEW_PROMPT = `Summarize the following wiki pages into a high-level overview page. Identify themes, patterns, and connections across pages. Use the wiki summary format.
|
|
188
|
+
|
|
189
|
+
For each major theme:
|
|
190
|
+
- Note which pages contribute to the theme
|
|
191
|
+
- Identify cross-cutting patterns
|
|
192
|
+
- Flag contradictions between pages
|
|
193
|
+
- Highlight gaps (topics that should have pages but don't)`;
|
|
194
|
+
|
|
195
|
+
// -- Lint Prompts ------------------------------------------------------------
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Prompt for the LLM when reviewing lint results and auto-fixing issues.
|
|
199
|
+
*/
|
|
200
|
+
export const LINT_PROMPT = `Review the lint results below and fix all auto-fixable issues.
|
|
201
|
+
|
|
202
|
+
For each issue:
|
|
203
|
+
- Prioritize by impact (errors first, then warnings, then info)
|
|
204
|
+
- Fix broken wikilinks by finding the correct target page or removing dead links
|
|
205
|
+
- Add missing pages for concepts referenced across multiple pages
|
|
206
|
+
- Move stale projects to archives if inactive for 90+ days
|
|
207
|
+
- Fix frontmatter issues (missing fields, invalid dates, empty scope)
|
|
208
|
+
- Update index.md to include any pages missing from the index
|
|
209
|
+
- Propose archiving for inactive projects
|
|
210
|
+
|
|
211
|
+
Report unfixable issues that require human judgment.`;
|
|
212
|
+
|
|
213
|
+
// -- Capture Prompts ---------------------------------------------------------
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* System prompt for the standalone capture agent.
|
|
217
|
+
* Used as WIKI_SYSTEM_PROMPT for the capture agent instance.
|
|
218
|
+
*/
|
|
219
|
+
export const CAPTURE_SYSTEM_PROMPT = `You are a knowledge capture assistant. Your job is to extract persistent knowledge from coding sessions and write it to a PARA-structured wiki.
|
|
220
|
+
|
|
221
|
+
Capture ANY of the following — even from short sessions:
|
|
222
|
+
- Architecture decisions and rationale ("we chose X because Y")
|
|
223
|
+
- Debugging solutions (root cause + fix)
|
|
224
|
+
- Server/infrastructure details (IPs, paths, credentials locations, configs)
|
|
225
|
+
- Build and deployment procedures (commands, steps, gotchas)
|
|
226
|
+
- API keys, service endpoints, and where they are stored
|
|
227
|
+
- Project conventions and coding patterns
|
|
228
|
+
- Tool configurations and setup steps
|
|
229
|
+
- Dependencies and version constraints
|
|
230
|
+
- Environment-specific knowledge (dev vs prod differences)
|
|
231
|
+
- Operational runbooks (how to restart, deploy, rollback)
|
|
232
|
+
|
|
233
|
+
Index is auto-rebuilt after every write — do not manage index.md manually. Do NOT pass indexContent to wiki_write.
|
|
234
|
+
|
|
235
|
+
Rules:
|
|
236
|
+
- If the session was ONLY greetings or completely off-topic chitchat with zero project knowledge, respond with "nothing to capture"
|
|
237
|
+
- Otherwise, always capture — even small facts are valuable ("the deploy key is at /path/to/key")
|
|
238
|
+
- Classify each piece of knowledge by PARA category autonomously
|
|
239
|
+
- When the user defines a specific goal with a completion condition, create a projects/ page. When identifying a repeating responsibility (monitoring, maintenance, quality), create an areas/ page.
|
|
240
|
+
- Produce wiki pages in the standard wiki summary format (Topic, Key Facts, Insights, Connections, Open Questions, Sources)
|
|
241
|
+
- Include the full session file path in the Sources section for traceability
|
|
242
|
+
- ALWAYS search wiki_query BEFORE creating any page — update existing pages instead of creating duplicates
|
|
243
|
+
- If wiki_query finds a page on the same topic (even with a different title/slug), update THAT page using its existing slug
|
|
244
|
+
- The conversation may include compaction summaries from earlier in the session — treat these as authoritative records of prior work
|
|
245
|
+
- Write directly via wiki_write — no user confirmation needed
|
|
246
|
+
- NEVER include API keys, tokens, passwords, or secrets in wiki pages. Document WHERE they are stored, not the actual values.`;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Prompt template for auto-capture at session_shutdown.
|
|
250
|
+
* The serialized conversation is appended after this prompt.
|
|
251
|
+
*/
|
|
252
|
+
export const CAPTURE_PROMPT = `Analyze the session conversation below and capture ALL project-relevant knowledge into the wiki.
|
|
253
|
+
|
|
254
|
+
Capture bias: when in doubt, capture it. Small operational facts (paths, configs, server details, commands) are often the most valuable because they are hard to rediscover.
|
|
255
|
+
|
|
256
|
+
Only respond with "nothing to capture" if the session was purely greetings or off-topic chitchat with zero project knowledge.
|
|
257
|
+
|
|
258
|
+
For everything else:
|
|
259
|
+
1. Use wiki_query to search for EXISTING pages on each topic FIRST
|
|
260
|
+
2. If a matching page exists, use wiki_read to get its content, then wiki_write with its EXACT slug to update it
|
|
261
|
+
3. Only create a NEW page if wiki_query returned no relevant results
|
|
262
|
+
4. Each page must include the session file path in its Sources section
|
|
263
|
+
5. Do NOT pass indexContent to wiki_write - the index is auto-rebuilt from all pages on disk
|
|
264
|
+
|
|
265
|
+
CRITICAL: prefer updating over creating. The wiki likely already has pages on most topics.
|
|
266
|
+
|
|
267
|
+
<session-conversation>
|
|
268
|
+
`;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Prompt template for explicit capture via /wiki-capture.
|
|
272
|
+
* A topic hint (if provided) and the serialized conversation are appended.
|
|
273
|
+
*/
|
|
274
|
+
export const EXPLICIT_CAPTURE_PROMPT = `Capture knowledge from the current session into the wiki.`;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Wiki Schema
|
|
2
|
+
|
|
3
|
+
## Page Format
|
|
4
|
+
|
|
5
|
+
Every wiki page is a markdown file with YAML frontmatter:
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
---
|
|
9
|
+
title: Page Title
|
|
10
|
+
para: projects | areas | resources | archives
|
|
11
|
+
scope:
|
|
12
|
+
- project-name
|
|
13
|
+
tags:
|
|
14
|
+
- topic-tag
|
|
15
|
+
sources:
|
|
16
|
+
- https://example.com
|
|
17
|
+
created: "2026-01-01"
|
|
18
|
+
updated: "2026-01-01"
|
|
19
|
+
links:
|
|
20
|
+
- other-page-slug
|
|
21
|
+
---
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## PARA Categories
|
|
25
|
+
|
|
26
|
+
- **resources/**: Reference material, architecture docs, how-tos, patterns, debugging solutions, implementation notes. **Use this for almost everything.** If you're documenting how something works, put it here.
|
|
27
|
+
- **areas/**: Ongoing responsibilities with no end date — server configs, deployment procedures, infrastructure. Default scope: `["global"]`.
|
|
28
|
+
- **projects/**: ONLY for actual project goals with a defined end date and completion criteria (e.g. "migrate auth to OAuth2"). Do NOT use for documentation about a project's internals. A page about "pi-para daemon architecture" is a resource, not a project.
|
|
29
|
+
- **archives/**: Completed or deprecated items. Never create pages here — pages get moved here when done.
|
|
30
|
+
|
|
31
|
+
### Category decision rule
|
|
32
|
+
|
|
33
|
+
Ask: "Is this a goal I'm trying to accomplish, or knowledge I'm recording?"
|
|
34
|
+
- **Goal with end date** → projects/
|
|
35
|
+
- **Knowledge/reference** → resources/
|
|
36
|
+
- **Ongoing responsibility** → areas/
|
|
37
|
+
|
|
38
|
+
## Scope
|
|
39
|
+
|
|
40
|
+
Scope is the **project name** this page relates to. Must be kebab-case, single token.
|
|
41
|
+
|
|
42
|
+
✅ Correct: `pi-para`, `qmd`, `pi-mono`, `my-app`
|
|
43
|
+
❌ Wrong: `session exploration`, `daemon implementation`, `project structure`
|
|
44
|
+
|
|
45
|
+
Pages relevant to all projects use `global`.
|
|
46
|
+
|
|
47
|
+
## Tags
|
|
48
|
+
|
|
49
|
+
Tags are topic classifiers. Must be kebab-case (no spaces).
|
|
50
|
+
|
|
51
|
+
✅ Correct: `session-capture`, `lazy-loading`, `architecture`
|
|
52
|
+
❌ Wrong: `session files`, `UI component`, `model registry`
|
|
53
|
+
|
|
54
|
+
Don't duplicate scope values as tags — if scope is `pi-para`, don't also tag `pi-para`.
|
|
55
|
+
|
|
56
|
+
## Naming Conventions
|
|
57
|
+
|
|
58
|
+
- Slugs: lowercase, hyphens, no special characters (e.g., `ssl-cert-gotchas`)
|
|
59
|
+
- One concept per page
|
|
60
|
+
|
|
61
|
+
## Wikilinks
|
|
62
|
+
|
|
63
|
+
Use `[[slug]]` to connect related pages. Every page should link to related pages in a `## Connections` section:
|
|
64
|
+
|
|
65
|
+
```markdown
|
|
66
|
+
## Connections
|
|
67
|
+
- [[related-page]] — how this relates
|
|
68
|
+
- [[another-page]] — why it's relevant
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The `links` frontmatter field is auto-synced from body `[[wikilinks]]` — don't set it manually.
|
|
72
|
+
|
|
73
|
+
## Wiki Summary Format
|
|
74
|
+
|
|
75
|
+
```markdown
|
|
76
|
+
## Topic
|
|
77
|
+
[What this page covers]
|
|
78
|
+
|
|
79
|
+
## Key Facts
|
|
80
|
+
- [Established knowledge points]
|
|
81
|
+
|
|
82
|
+
## Insights
|
|
83
|
+
- [Non-obvious findings, patterns, implications]
|
|
84
|
+
|
|
85
|
+
## Connections
|
|
86
|
+
- [[related-page]] — how this relates
|
|
87
|
+
|
|
88
|
+
## Open Questions
|
|
89
|
+
- [Gaps in knowledge, unresolved contradictions]
|
|
90
|
+
|
|
91
|
+
## Sources
|
|
92
|
+
- [Source URLs, file paths, session references]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Updates vs. New Pages
|
|
96
|
+
|
|
97
|
+
- Update an existing page when new information relates to the same concept
|
|
98
|
+
- Create a new page when the concept is distinct enough to stand alone
|
|
99
|
+
- When in doubt, create a new page and add [[wikilinks]]
|
|
100
|
+
|
|
101
|
+
## Secrets
|
|
102
|
+
|
|
103
|
+
NEVER include secrets in wiki pages:
|
|
104
|
+
- API keys, tokens, passwords, private keys
|
|
105
|
+
- Connection strings with credentials
|
|
106
|
+
- Any value that would be dangerous if exposed
|
|
107
|
+
|
|
108
|
+
Instead, document WHERE the secret is stored:
|
|
109
|
+
- ✅ `API key stored in ~/.config/qmd/index.yml on server 10.88.1.8`
|
|
110
|
+
- ❌ `key: sk-or-v1-abc123...`
|
|
111
|
+
|
|
112
|
+
Secrets are automatically redacted on write. If you see `<REDACTED>` in a page, it was stripped for security.
|
|
113
|
+
|
|
114
|
+
## Tone
|
|
115
|
+
|
|
116
|
+
Technical, concise, factual. No fluff.
|