@zosmaai/pi-llm-wiki 0.11.3 → 0.11.4
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 +10 -0
- package/README.md +80 -2
- package/commands/wiki-digest.md +28 -0
- package/commands/wiki-discover.md +30 -0
- package/commands/wiki-ingest.md +36 -0
- package/commands/wiki-init.md +30 -0
- package/commands/wiki-lint.md +25 -0
- package/commands/wiki-query.md +37 -0
- package/commands/wiki-record.md +36 -0
- package/commands/wiki-req.md +55 -0
- package/commands/wiki-retro.md +34 -0
- package/commands/wiki-run.md +31 -0
- package/commands/wiki-skills.md +26 -0
- package/commands/wiki-status.md +16 -0
- package/dist/extensions/llm-wiki/lib/host.js +97 -0
- package/dist/extensions/llm-wiki/lib/observation.js +9 -0
- package/dist/extensions/llm-wiki/lib/task-config.js +74 -49
- package/dist/extensions/llm-wiki/lib/utils.js +59 -16
- package/docs/configuration.md +49 -8
- package/extensions/llm-wiki/index.ts +44 -6
- package/extensions/llm-wiki/lib/host.ts +125 -0
- package/extensions/llm-wiki/lib/observation.ts +14 -1
- package/extensions/llm-wiki/lib/task-config.ts +115 -55
- package/extensions/llm-wiki/lib/utils.ts +55 -14
- package/package.json +12 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
### Added
|
|
6
|
+
- **oh-my-pi (`omp`) host support** alongside pi, from one codebase and with no hard fork. `@oh-my-pi/pi-coding-agent` rewrites `@mariozechner/pi-*` and bare `typebox` specifiers onto its own bundled packages, so the extension module graph is unchanged; what differed was the on-disk config layout and slash-command discovery.
|
|
7
|
+
- **`extensions/llm-wiki/lib/host.ts`**: detects the host (`LLM_WIKI_HOST` override → agent-directory marker → `OMP_PROFILE` → `pi`) and enumerates every settings file both layouts use.
|
|
8
|
+
- **Dual-layout settings**: `loadTaskConfig` now merges `<agentDir>/{settings.json,config.yml,config.yaml}` and `<cwd>/{.pi,.omp}/{settings.json,config.yml,config.yaml}`, host-native project directory last. YAML is parsed for the `config.yml` files oh-my-pi migrates to. `/wiki-model` and `/wiki-trajectories` write JSON into whichever project config directory already exists, so a `.pi`-only repository never sprouts a second settings file and a hand-authored `config.yml` is never rewritten.
|
|
9
|
+
- **`commands/`**: a generated, committed mirror of `prompts/` (`npm run build:commands`, also run by `prepack`). pi finds slash-command templates through `pi.prompts`; oh-my-pi only turns `<package>/commands/*.md` into real `/wiki-*` commands.
|
|
10
|
+
- **Manifest**: added `package.json#omp.extensions`, naming the entry module rather than the `./extensions` directory — oh-my-pi reads `omp` before falling back to `pi`, and `omp -e <package-root>` imports a manifest entry verbatim, so a directory entry fails there. No new dependency: the host resolves its own bundled packages for the extension, so an `@oh-my-pi/pi-coding-agent` peer would be inert while dragging the whole host tree into `pnpm-lock.yaml`.
|
|
11
|
+
- **17 tests** (`test/host-compat.test.ts`, plus manifest/mirror assertions in `test/package-structure.test.ts`): host detection and its precedence, settings-file enumeration and ordering, write-target selection, cross-host config round-trips, YAML reads, corrupt-file tolerance, and `commands/`↔`prompts/` parity.
|
|
12
|
+
- **Ambient surfaces are gated on "does a wiki apply here"**: the session notice, the periodic observe/retro reminder, and the `before_agent_start` recall injection (with its `<wiki_status>` system-prompt footer) fire unprompted, and vault resolution falls back to the personal vault — so once `~/.llm-wiki/` existed they spoke up in EVERY directory, injecting reminders and unrelated cross-project recall hits into repositories that never ran `/wiki-init`. Harmless under pi, where extensions are opted into per project; under oh-my-pi the plugin is installed once and loads everywhere. New `resolveProjectVaultRoot()` answers the question the old `resolveVaultRoot()` could not — "does THIS project have a vault", with no personal fallback and no false positive from the personal vault sitting on the ancestor path of every project under `$HOME`. The new `llm-wiki.ambientPersonalVault` setting overrides the host-dependent default (`true` under pi, preserving historical behaviour; `false` under omp). Tools and slash commands are registered either way, so `/wiki-init` and `wiki_bootstrap` still work in any directory.
|
|
13
|
+
- **17 more tests** (`test/ambient-gate.test.ts`): project-vault resolution (own vault, ancestor walk, `WIKI_HOME`, personal-vault exclusion), the host-dependent default and its explicit override, the composed gate across four project states, and the reminder gate — including that a closed gate does not bank turns, so opening it later is not an instant nag, and that `display: false` is not a substitute because it still injects into model context.
|
|
14
|
+
|
|
5
15
|
### Fixed
|
|
6
16
|
- **MCP server failed to start on `@modelcontextprotocol/server` 2.0.0** (Issue #128): `mcp/index.ts` imported `StdioServerTransport` from the package root, but SDK 2.0.0 (published 2026-07-27) moved that export to the `./stdio` subpath, so `node dist/mcp/index.js` died with `SyntaxError: The requested module '@modelcontextprotocol/server' does not provide an export named 'StdioServerTransport'` before the transport ever connected. The declared range `^2.0.0-alpha.2` is a caret range over a prerelease, so it permits `2.0.0`: every fresh consumer install resolved the stable SDK against the pre-stable import, while `pnpm-lock.yaml` pinned the `2.0.0-alpha.2` floor — so `test/mcp-package.test.ts`, which does spawn the published command and complete the stdio handshake, only ever exercised the alpha where the root export still existed. Fixed by importing `StdioServerTransport` from `@modelcontextprotocol/server/stdio` (the `./stdio` subpath does not exist in `2.0.0-alpha.2`, so the range, the lockfile and the import move together), raising the range to `^2.0.0`, and refreshing the lockfile so the existing smoke test now runs against the SDK consumers actually get.
|
|
7
17
|
- **Packaged MCP server was never exercised with consumer-resolved dependencies**: a new `packaged-mcp-consumer` CI job packs the tarball, installs it into a directory with **no lockfile**, prints the resolved SDK version, and runs `scripts/mcp-smoke.mjs` — the stdio handshake (`initialize` → `tools/list`) — against that install. This closes the whole class of failure behind Issue #128: a dependency range that resolves differently for consumers than for this repo's lockfile can no longer break the published server undetected.
|
package/README.md
CHANGED
|
@@ -47,10 +47,21 @@ Start with a new OKF vault, or point pi-llm-wiki at an existing vault and adopt
|
|
|
47
47
|
|
|
48
48
|
## Quick Start
|
|
49
49
|
|
|
50
|
+
**pi** ([`@mariozechner/pi-coding-agent`](https://github.com/badlogic/pi-mono)):
|
|
51
|
+
|
|
50
52
|
```bash
|
|
51
53
|
pi install npm:@zosmaai/pi-llm-wiki
|
|
52
54
|
```
|
|
53
55
|
|
|
56
|
+
**oh-my-pi** ([`omp`](https://github.com/can1357/oh-my-pi)):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
omp install @zosmaai/pi-llm-wiki
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Both hosts load the same extension, skill, and `/wiki-*` slash commands — see
|
|
63
|
+
[Dual-host support](#dual-host-support-pi--oh-my-pi) for what differs.
|
|
64
|
+
|
|
54
65
|
The extension will proactively suggest creating a wiki on your first session. Alternatively:
|
|
55
66
|
|
|
56
67
|
```
|
|
@@ -385,6 +396,66 @@ The same server as an entry in `.mcp.json` (Claude Code) or `claude_desktop_conf
|
|
|
385
396
|
|
|
386
397
|
---
|
|
387
398
|
|
|
399
|
+
## Dual-host support (pi + oh-my-pi)
|
|
400
|
+
|
|
401
|
+
The package targets two hosts from a single codebase:
|
|
402
|
+
|
|
403
|
+
| | **pi** (`@mariozechner/pi-coding-agent`) | **oh-my-pi** (`omp`) |
|
|
404
|
+
|---|---|---|
|
|
405
|
+
| Extension entry | `package.json#pi.extensions` | `package.json#omp.extensions` (falls back to `#pi`) |
|
|
406
|
+
| Skill | `skills/llm-wiki/SKILL.md` via `pi.skills` | same file, found by directory convention |
|
|
407
|
+
| Slash commands | `prompts/*.md` via `pi.prompts` | `commands/*.md` (generated mirror of `prompts/`) |
|
|
408
|
+
| Project config | `<cwd>/.pi/settings.json` | `<cwd>/.omp/settings.json`, then `.omp/config.yml` |
|
|
409
|
+
| User config | `~/.pi/agent/settings.json` | `~/.omp/agent/settings.json`, then `config.yml` |
|
|
410
|
+
| MCP server | auto-registered via `pi.mcpservers` | register manually (see below) |
|
|
411
|
+
| Ambient surfaces without a project wiki | on (personal vault) | off — see below |
|
|
412
|
+
|
|
413
|
+
No source changes are needed for the imports: oh-my-pi rewrites
|
|
414
|
+
`@mariozechner/pi-*` and bare `typebox` specifiers onto its own bundled
|
|
415
|
+
packages when it loads a legacy extension.
|
|
416
|
+
|
|
417
|
+
**Settings are read from both layouts.** `llm-wiki` config is merged from every
|
|
418
|
+
file above, host-native directory last. A vault configured under pi keeps
|
|
419
|
+
working after `omp` takes over the same repository, and writes land in whichever
|
|
420
|
+
config directory already exists (so a `.pi`-only repo does not sprout a second
|
|
421
|
+
settings file). Writes are always JSON — a hand-authored `config.yml` is read
|
|
422
|
+
but never rewritten.
|
|
423
|
+
|
|
424
|
+
Set `LLM_WIKI_HOST=pi|omp` to override host detection; by default it is derived
|
|
425
|
+
from the resolved agent directory.
|
|
426
|
+
|
|
427
|
+
**Ambient surfaces are gated under oh-my-pi.** The session notice, the periodic
|
|
428
|
+
observe/retro reminder, and `before_agent_start` recall all fire unprompted, and
|
|
429
|
+
vault resolution falls back to the personal vault — so once `~/.llm-wiki/`
|
|
430
|
+
exists they would speak up in *every* directory. Under pi that is the historical
|
|
431
|
+
behaviour and it is kept; under omp the plugin is installed once and loads in
|
|
432
|
+
every project, so a repository that never ran `/wiki-init` stays quiet. Override
|
|
433
|
+
either default with `llm-wiki.ambientPersonalVault`. The wiki tools and slash
|
|
434
|
+
commands are registered regardless, so `/wiki-init` always works — and a project
|
|
435
|
+
with its own `.llm-wiki/` gets every surface back.
|
|
436
|
+
|
|
437
|
+
**MCP under oh-my-pi.** `pi.mcpservers` is a pi-only manifest key, and the
|
|
438
|
+
server's vault auto-detection depends on the client's working directory, so it
|
|
439
|
+
cannot be declared with a relative path. Register it explicitly instead:
|
|
440
|
+
|
|
441
|
+
```jsonc
|
|
442
|
+
// <cwd>/.omp/.mcp.json
|
|
443
|
+
{
|
|
444
|
+
"mcpServers": {
|
|
445
|
+
"llm-wiki": {
|
|
446
|
+
"command": "node",
|
|
447
|
+
"args": ["/abs/path/to/node_modules/@zosmaai/pi-llm-wiki/dist/mcp/index.js"],
|
|
448
|
+
"env": { "WIKI_ROOT": "/abs/path/to/your/wiki" }
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
You rarely need it: under either host the extension already registers the same
|
|
455
|
+
capabilities as native tools.
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
388
459
|
## Skill Behavior
|
|
389
460
|
|
|
390
461
|
The bundled `llm-wiki` skill teaches the model to:
|
|
@@ -495,6 +566,13 @@ Thanks to everyone who has contributed! This list is regenerated automatically b
|
|
|
495
566
|
<sub><b>Akshay</b></sub>
|
|
496
567
|
</a>
|
|
497
568
|
</td>
|
|
569
|
+
<td align="center">
|
|
570
|
+
<a href="https://github.com/prestalab">
|
|
571
|
+
<img src="https://avatars.githubusercontent.com/u/2825421?v=4" width="64;" alt="prestalab"/>
|
|
572
|
+
<br />
|
|
573
|
+
<sub><b>PrestaLab</b></sub>
|
|
574
|
+
</a>
|
|
575
|
+
</td>
|
|
498
576
|
<td align="center">
|
|
499
577
|
<a href="https://github.com/xcsf">
|
|
500
578
|
<img src="https://avatars.githubusercontent.com/u/43439835?v=4" width="64;" alt="xcsf"/>
|
|
@@ -509,6 +587,8 @@ Thanks to everyone who has contributed! This list is regenerated automatically b
|
|
|
509
587
|
<sub><b>Daniel Naab</b></sub>
|
|
510
588
|
</a>
|
|
511
589
|
</td>
|
|
590
|
+
</tr>
|
|
591
|
+
<tr>
|
|
512
592
|
<td align="center">
|
|
513
593
|
<a href="https://github.com/deestax">
|
|
514
594
|
<img src="https://avatars.githubusercontent.com/u/152369481?v=4" width="64;" alt="deestax"/>
|
|
@@ -516,8 +596,6 @@ Thanks to everyone who has contributed! This list is regenerated automatically b
|
|
|
516
596
|
<sub><b>Superdao</b></sub>
|
|
517
597
|
</a>
|
|
518
598
|
</td>
|
|
519
|
-
</tr>
|
|
520
|
-
<tr>
|
|
521
599
|
<td align="center">
|
|
522
600
|
<a href="https://github.com/mystery4f">
|
|
523
601
|
<img src="https://avatars.githubusercontent.com/u/40482524?v=4" width="64;" alt="mystery4f"/>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Generate a daily or weekly digest of wiki changes — new sources, pages, insights, and gaps.
|
|
3
|
+
argument-hint: "[--period daily|weekly]"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-digest
|
|
9
|
+
|
|
10
|
+
Generate a digest of recent wiki activity.
|
|
11
|
+
|
|
12
|
+
## User Arguments
|
|
13
|
+
|
|
14
|
+
$ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. Call `wiki_status()` to get current stats (page count, orphans, gaps, health).
|
|
19
|
+
2. Read `.llm-wiki/meta/log.md` for recent events since the last digest period.
|
|
20
|
+
3. Summarize:
|
|
21
|
+
- New sources captured
|
|
22
|
+
- New pages created or updated
|
|
23
|
+
- Key insights or connections made
|
|
24
|
+
- Knowledge gaps identified
|
|
25
|
+
- Health trends (improving, stable, declining)
|
|
26
|
+
4. Save the digest to `.llm-wiki/outputs/digest-YYYY-MM-DD.md` using the `write` tool.
|
|
27
|
+
5. Call `wiki_log_event(kind=digest)` to record this digest was generated.
|
|
28
|
+
6. Report a concise digest to the user.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Auto-discover new sources from the web. Searches based on config topics and known knowledge gaps.
|
|
3
|
+
argument-hint: "[--topic <topic>]"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-discover
|
|
9
|
+
|
|
10
|
+
Find new source material for the wiki by searching the web and capturing them as source packets.
|
|
11
|
+
|
|
12
|
+
## User Arguments
|
|
13
|
+
|
|
14
|
+
$ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. Call `wiki_status()` to get the current topic and mode from the wiki config.
|
|
19
|
+
2. Use `wiki_search(query=<topic>)` to find existing pages and identify what's already covered.
|
|
20
|
+
3. Search the web for new sources:
|
|
21
|
+
- If `--topic` is specified in `$ARGUMENTS`, focus on that topic
|
|
22
|
+
- Otherwise, search for the wiki's main topic + "latest", "news", "update"
|
|
23
|
+
4. For each promising result (max 5-10):
|
|
24
|
+
a. Call `wiki_capture_source(url=<url>)` to capture it as an immutable source packet
|
|
25
|
+
b. Skip ads, listicles, and duplicates — prefer in-depth analysis
|
|
26
|
+
5. Report: "Discovered [N] new sources captured as packets. Run `/wiki-ingest` to synthesize them into knowledge pages."
|
|
27
|
+
|
|
28
|
+
**Rules:**
|
|
29
|
+
- Do NOT manually save files to `raw/` — always use `wiki_capture_source`.
|
|
30
|
+
- The extension handles manifest, extraction, and skeleton page creation automatically.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Process new source packets and synthesize them into wiki knowledge pages.
|
|
3
|
+
argument-hint: "[source_id]"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-ingest
|
|
9
|
+
|
|
10
|
+
Process uningested source packets and synthesize them into wiki knowledge pages.
|
|
11
|
+
|
|
12
|
+
## User Arguments
|
|
13
|
+
|
|
14
|
+
$ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. Call `wiki_ingest(source_id=<id if provided>, batch_size=3)`.
|
|
19
|
+
2. If the tool reports "All sources ingested", inform the user and stop.
|
|
20
|
+
3. **If the tool reports it is ingesting in the background**, the synthesis sub-agent is handling those sources on the configured task model. Do NOT synthesize them yourself — just report which sources were dispatched and stop. (You'll be notified as each completes.)
|
|
21
|
+
4. **Otherwise** (the tool returned extracted content — background unavailable or `background=false`), for each source in the returned batch:
|
|
22
|
+
a. Read the extracted text from `.llm-wiki/raw/sources/<SOURCE_ID>/extracted.md`
|
|
23
|
+
b. Update the skeleton source page in `wiki/sources/` with a proper summary, key entities, and concepts
|
|
24
|
+
c. Use `wiki_ensure_page(type=entity, title=<name>)` for each new entity (people, orgs, tools, products)
|
|
25
|
+
d. Use `wiki_ensure_page(type=concept, title=<name>)` for each new concept (ideas, patterns, frameworks)
|
|
26
|
+
e. Add `[[wikilinks]]` cross-references between related pages
|
|
27
|
+
f. Flag any contradictions with existing wiki content using `⚠️ **Contradiction**` markers
|
|
28
|
+
5. After processing a synchronous batch, call `wiki_rebuild_meta` to update metadata.
|
|
29
|
+
6. Report: "Ingested [N] sources → [M] pages created/updated. [X] contradictions flagged."
|
|
30
|
+
|
|
31
|
+
> **Background vs synchronous:** ingestion runs in the background by default (non-blocking) when a task model is available, so the main agent is never stalled. It falls back to the synchronous main-agent flow above when no model/API key is configured, or when called with `background=false`.
|
|
32
|
+
|
|
33
|
+
**Rules:**
|
|
34
|
+
- Never modify files in `raw/` — source packets are immutable after capture.
|
|
35
|
+
- Never fabricate information — always cite sources with `[[sources/SRC-...]]`.
|
|
36
|
+
- The extension auto-updates metadata — you do NOT need to manually edit `meta/` files.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Initialize a new LLM Wiki in the current directory. Creates the full directory structure, config, and template files.
|
|
3
|
+
argument-hint: "<topic> [--mode personal|company]"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-init
|
|
9
|
+
|
|
10
|
+
Initialize a new LLM Wiki vault using the `wiki_bootstrap` tool.
|
|
11
|
+
|
|
12
|
+
## User Arguments
|
|
13
|
+
|
|
14
|
+
$ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. If the user provided a topic in `$ARGUMENTS`, use it. Otherwise, ask the user for the wiki **topic**.
|
|
19
|
+
2. Determine mode: default to `personal`; use `company` if the user specifies `--mode company` or requests it.
|
|
20
|
+
3. Call `wiki_bootstrap(topic=<topic>, mode=<mode>)` to create the vault.
|
|
21
|
+
4. Report the result and suggest next steps:
|
|
22
|
+
- "Use `wiki_capture_source` to add your first source (URL, file, or text)."
|
|
23
|
+
- "Run `/wiki-ingest` after capturing sources to synthesize them into knowledge pages."
|
|
24
|
+
|
|
25
|
+
**Do NOT manually create directories or files.** The `wiki_bootstrap` tool handles all scaffolding including:
|
|
26
|
+
- `.llm-wiki/raw/sources/` — immutable source packets
|
|
27
|
+
- `.llm-wiki/wiki/` — editable knowledge pages
|
|
28
|
+
- `.llm-wiki/meta/` — auto-generated metadata
|
|
29
|
+
- `.llm-wiki/config.json` — vault configuration
|
|
30
|
+
- `.llm-wiki/WIKI_SCHEMA.md` — operating rules
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Health check the wiki. Detects contradictions, orphans, missing pages, stale claims, and knowledge gaps.
|
|
3
|
+
argument-hint: "[--fix]"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-lint
|
|
9
|
+
|
|
10
|
+
Run a comprehensive health check on the wiki.
|
|
11
|
+
|
|
12
|
+
## User Arguments
|
|
13
|
+
|
|
14
|
+
$ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. Determine if auto-fix is requested: set `auto_fix=true` if `$ARGUMENTS` contains `--fix`, otherwise `false`.
|
|
19
|
+
2. Call `wiki_lint(auto_fix=<true/false>)` to run the health check.
|
|
20
|
+
3. Present the lint report to the user, including:
|
|
21
|
+
- Page count, orphans, missing pages, contradictions
|
|
22
|
+
- Knowledge gaps found
|
|
23
|
+
- Any auto-fixes applied
|
|
24
|
+
4. If contradictions are found, flag them for human review — do NOT auto-resolve contradictions.
|
|
25
|
+
5. If knowledge gaps are identified, suggest creating pages for frequently-mentioned topics.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Ask questions against the wiki. Synthesizes answers from wiki pages with cross-reference citations.
|
|
3
|
+
argument-hint: "<question>"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-query
|
|
9
|
+
|
|
10
|
+
Ask a question and get an answer synthesized from wiki content.
|
|
11
|
+
|
|
12
|
+
## User Question
|
|
13
|
+
|
|
14
|
+
$ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. Call `wiki_recall(query=<question>)` to find relevant wiki pages.
|
|
19
|
+
2. Read the full content of each matching page using the `read` tool.
|
|
20
|
+
3. Synthesize an answer with `[[wikilink]]` citations to specific wiki pages.
|
|
21
|
+
4. If the answer reveals a new connection or analysis worth preserving:
|
|
22
|
+
- Call `wiki_ensure_page(type=synthesis, title=<title>, content=<content>)` to save it
|
|
23
|
+
5. Call `wiki_log_event(kind=query, details={question: <question>})` to log the query.
|
|
24
|
+
|
|
25
|
+
**Rules:**
|
|
26
|
+
- Answer ONLY from wiki content, not from general knowledge.
|
|
27
|
+
- If the wiki lacks information, say so clearly and suggest what sources would help fill the gap.
|
|
28
|
+
|
|
29
|
+
**Example:**
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
/wiki-query What are the key differences between RAG and LLM Wiki?
|
|
33
|
+
→ Calls wiki_recall(query="RAG LLM Wiki differences")
|
|
34
|
+
→ Reads matching pages
|
|
35
|
+
→ Synthesizes a comparison with [[wikilink]] citations
|
|
36
|
+
→ Saves as synthesis page via wiki_ensure_page(type=synthesis, ...)
|
|
37
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Capture the just-completed task's tool-call trajectory into the wiki as agent working-memory, then optionally distill it into a reusable skill.
|
|
3
|
+
argument-hint: "<title> [--outcome success|failure|partial]"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-record
|
|
9
|
+
|
|
10
|
+
Capture the trajectory of the task you just completed — the sequence of tool calls that solved it — into the wiki's working-memory layer.
|
|
11
|
+
|
|
12
|
+
This is the counterpart to source capture: instead of recording what you *read*, it records what you *did*, so the wiki compounds over your own work.
|
|
13
|
+
|
|
14
|
+
## User Arguments
|
|
15
|
+
|
|
16
|
+
$ARGUMENTS
|
|
17
|
+
|
|
18
|
+
Read the LLM Wiki skill at `.pi/skills/llm-wiki/SKILL.md` first to understand the wiki conventions.
|
|
19
|
+
|
|
20
|
+
## Steps
|
|
21
|
+
|
|
22
|
+
1. Call `wiki_capture_trajectory` with:
|
|
23
|
+
- `title`: short descriptive phrase for the task (≤60 chars, noun phrase)
|
|
24
|
+
- `outcome`: optional — `success` (default), `failure`, or `partial`
|
|
25
|
+
- The extension auto-extracts the tool-call trajectory from the live session, so you usually do **not** pass `steps` manually.
|
|
26
|
+
2. Open the generated skeleton case page in `wiki/cases/` and flesh out:
|
|
27
|
+
- **Task** — what was requested
|
|
28
|
+
- **Approach** — the key steps and decisions (not every tool call, just the meaningful ones)
|
|
29
|
+
- **Outcome** — the result, and anything worth reusing or avoiding next time
|
|
30
|
+
3. If the task taught a reusable pattern, run `wiki_distill_skills` and create a `skill` page via `wiki_ensure_page(type="skill")` that cites `[[trajectories/TRJ-...]]`.
|
|
31
|
+
4. Confirm the case (and any skill) will be surfaced by `wiki_recall` / `wiki_recall_skill` in future sessions.
|
|
32
|
+
|
|
33
|
+
**Rules:**
|
|
34
|
+
- Only record tasks worth learning from — non-trivial debugging, refactors, integrations, multi-step workflows. Skip trivial one-shot answers.
|
|
35
|
+
- The raw trajectory packet under `raw/trajectories/` is immutable. Edit the `case`/`skill` pages, never the packet.
|
|
36
|
+
- One trajectory per `wiki_capture_trajectory` call.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Capture and decompose a concept into atomic, traceable wiki requirements. Clarifies ambiguous requirements, splits them into atomic pieces, and persists them as wiki/requirements/ pages with status tracking.
|
|
3
|
+
argument-hint: "<concept description>"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-req
|
|
9
|
+
|
|
10
|
+
Capture a concept and decompose it into atomic, traceable requirements in the wiki.
|
|
11
|
+
|
|
12
|
+
Transforms natural language descriptions into structured `wiki/requirements/` pages, preserving the original clarified concept as an immutable source packet in `raw/sources/`.
|
|
13
|
+
|
|
14
|
+
## User Arguments
|
|
15
|
+
|
|
16
|
+
$ARGUMENTS
|
|
17
|
+
|
|
18
|
+
Read the LLM Wiki skill at `.pi/skills/llm-wiki/SKILL.md` first to understand the wiki conventions, architecture, and page type rules.
|
|
19
|
+
|
|
20
|
+
## Steps
|
|
21
|
+
|
|
22
|
+
1. **Clarify the concept**
|
|
23
|
+
- Discuss with the user: unpack ambiguous terms, surfaces implicit assumptions, identify scope boundaries
|
|
24
|
+
- Ask targeted questions to resolve unknowns (e.g., "Which providers?", "What's the fallback behavior?", "Who are the actors?")
|
|
25
|
+
- Reach mutual clarity before proceeding
|
|
26
|
+
|
|
27
|
+
2. **Capture the clarified concept**
|
|
28
|
+
- Call `wiki_capture_source(text=...)` with the clarified conversation as markdown
|
|
29
|
+
- This creates an immutable record in `raw/sources/SRC-YYYY-MM-DD-NNN/`
|
|
30
|
+
- The source captures the original intent verbatim — no interpretation, no decomposition
|
|
31
|
+
|
|
32
|
+
3. **Decompose into atomic requirements**
|
|
33
|
+
- Break the clarified concept into the smallest meaningful units of functionality
|
|
34
|
+
- Each requirement should represent one independently verifiable behavior
|
|
35
|
+
- For each atomic requirement, call `wiki_ensure_page(type="requirement", title="...", content="...")` where content includes:
|
|
36
|
+
- `type: requirement` and `status: draft` in frontmatter
|
|
37
|
+
- A clear `## Description` section
|
|
38
|
+
- `## Acceptance Criteria` as a checkbox list (the threshold for "done")
|
|
39
|
+
- `source_id` linking back to the source capture
|
|
40
|
+
- `depends_on` linking to any prerequisite requirements
|
|
41
|
+
- `[[wikilinks]]` to relevant entities, concepts, and other wiki pages
|
|
42
|
+
- Set priority based on user input: `p0` (blocking), `p1` (critical), `p2` (important), `p3` (nice-to-have)
|
|
43
|
+
|
|
44
|
+
4. **Cross-link and finalize**
|
|
45
|
+
- Ensure each requirement page has bidirectional wikilinks to related pages
|
|
46
|
+
- Update any existing entity or concept pages that these requirements reference
|
|
47
|
+
- Report the results: how many requirements created, their priorities, and the source capture ID
|
|
48
|
+
|
|
49
|
+
**Rules:**
|
|
50
|
+
- One atomic requirement per `wiki_ensure_page` call — each must be independently testable
|
|
51
|
+
- Always capture the clarified concept first via `wiki_capture_source` before decomposing
|
|
52
|
+
- Requirements live in `wiki/requirements/` — they are editable wiki pages, not immutable sources
|
|
53
|
+
- Use status values: `draft` → `clarified` → `active` → `implemented` → `deferred` → `rejected`
|
|
54
|
+
- Use priority values: `p0` (blocking), `p1` (critical), `p2` (important), `p3` (nice-to-have)
|
|
55
|
+
- Do not create requirements in `raw/` — that layer is for external source artifacts only
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Save an atomic insight from the current task into the wiki. Creates a single markdown file that layered recall surfaces in future sessions.
|
|
3
|
+
argument-hint: "<title> [--category <category>]"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-retro
|
|
9
|
+
|
|
10
|
+
Save an atomic insight from a completed task into the wiki.
|
|
11
|
+
|
|
12
|
+
Captures what you learned as a single markdown file so that layered recall surfaces it in future sessions.
|
|
13
|
+
|
|
14
|
+
## User Arguments
|
|
15
|
+
|
|
16
|
+
$ARGUMENTS
|
|
17
|
+
|
|
18
|
+
Read the LLM Wiki skill at `.pi/skills/llm-wiki/SKILL.md` first to understand the wiki conventions.
|
|
19
|
+
|
|
20
|
+
## Steps
|
|
21
|
+
|
|
22
|
+
1. Identify the key insight(s) from the current task — non-obvious learnings, patterns, or decisions worth preserving
|
|
23
|
+
2. For each insight, call `wiki_retro` with:
|
|
24
|
+
- `slug`: unique kebab-case identifier (e.g., `jwt-revocation-pattern`)
|
|
25
|
+
- `title`: short descriptive phrase, ≤60 chars, noun phrase not a sentence
|
|
26
|
+
- `body`: markdown explanation with `[[wikilinks]]` to related wiki pages
|
|
27
|
+
- `category`: optional (frontend, architecture, devops, bugfix, design, etc.)
|
|
28
|
+
3. Confirm the insight was saved and will be surfaced by layered recall in future sessions
|
|
29
|
+
4. If the insight relates to existing wiki pages, update those pages with cross-references
|
|
30
|
+
|
|
31
|
+
**Rules:**
|
|
32
|
+
- One atomic insight per `wiki_retro` call. Use multiple calls for multiple insights.
|
|
33
|
+
- Don't save obvious things. Save non-obvious patterns, tradeoffs, and design decisions.
|
|
34
|
+
- Always add `[[wikilinks]]` to connect the new insight with existing wiki knowledge.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run the full wiki cycle: discover → ingest → lint. Optionally schedule for auto-updates.
|
|
3
|
+
argument-hint: "[--schedule daily|weekly]"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-run
|
|
9
|
+
|
|
10
|
+
Run the complete wiki maintenance cycle: discover new sources, ingest them, and lint for health.
|
|
11
|
+
|
|
12
|
+
## User Arguments
|
|
13
|
+
|
|
14
|
+
$ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. **Discover:** Use web search to find new sources on the wiki's topic, then capture each with `wiki_capture_source(url=<url>)` (max 5-10).
|
|
19
|
+
2. **Ingest:** Call `wiki_ingest(batch_size=3)` and process returned sources — read extracted.md, update source pages, create entity/concept pages, add cross-references.
|
|
20
|
+
3. **Lint:** Call `wiki_lint(auto_fix=false)` to run a health check.
|
|
21
|
+
4. If critical gaps found → optionally run one more discover+ingest cycle.
|
|
22
|
+
5. Save summary to `.llm-wiki/outputs/run-YYYY-MM-DD.md` using the `write` tool.
|
|
23
|
+
6. Report final summary.
|
|
24
|
+
|
|
25
|
+
### Scheduling
|
|
26
|
+
|
|
27
|
+
If `--schedule` is provided, call `wiki_watch(interval=<daily|weekly|hourly>)`.
|
|
28
|
+
|
|
29
|
+
**Important:** `wiki_watch` does NOT install a schedule. It only prints a `crontab` line.
|
|
30
|
+
Report the printed line to the user verbatim and tell them to install it themselves with
|
|
31
|
+
`crontab -e`. Do not claim the schedule is active until they confirm they have done so.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Search the wiki's distilled skills and past cases for patterns relevant to the current task — "have I done something like this before?".
|
|
3
|
+
argument-hint: "[query] [--kind skill|case]"
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-skills
|
|
9
|
+
|
|
10
|
+
Search the agent working-memory layer of the wiki: reusable **skills** distilled from past trajectories, and specific past **cases**.
|
|
11
|
+
|
|
12
|
+
## User Arguments
|
|
13
|
+
|
|
14
|
+
$ARGUMENTS
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. Call `wiki_recall_skill` with:
|
|
19
|
+
- `query`: the current task description or key terms (defaults to `$ARGUMENTS`)
|
|
20
|
+
- `kind`: optional — `skill`, `case`, or `any` (default)
|
|
21
|
+
- `max_results`: optional (default 5)
|
|
22
|
+
2. Read the most relevant skill/case pages with `read`.
|
|
23
|
+
3. Apply the recalled pattern to the current task, citing the source page with `[[skills/...]]` or `[[cases/...]]` where helpful.
|
|
24
|
+
4. If no relevant skill/case exists, proceed with the task and consider running `/wiki-record` afterward so the next attempt benefits.
|
|
25
|
+
|
|
26
|
+
**Tip:** Skills generalize across many trajectories ("how I do X"); cases are concrete past runs ("the time I did X for project Y"). Search `any` first, then narrow.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show wiki health overview — source count, page stats, orphan count, last activity dates.
|
|
3
|
+
argument-hint: ""
|
|
4
|
+
section: LLM Wiki
|
|
5
|
+
topLevelCli: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /wiki-status
|
|
9
|
+
|
|
10
|
+
Show a quick overview of wiki health and statistics.
|
|
11
|
+
|
|
12
|
+
## Steps
|
|
13
|
+
|
|
14
|
+
1. Call `wiki_status()` to get the current wiki health report.
|
|
15
|
+
2. Present the results to the user.
|
|
16
|
+
3. If health shows warnings (orphans > 5, many gaps), suggest running `/wiki-lint` for a detailed analysis.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { getAgentDir } from "@mariozechner/pi-coding-agent";
|
|
4
|
+
/** Project config directory name per host. */
|
|
5
|
+
const CONFIG_DIR = { pi: ".pi", omp: ".omp" };
|
|
6
|
+
/** Settings file names inside a config directory, lowest → highest precedence. */
|
|
7
|
+
const SETTINGS_FILES = ["settings.json", "config.yml", "config.yaml"];
|
|
8
|
+
/**
|
|
9
|
+
* Detect which agent is hosting this extension.
|
|
10
|
+
*
|
|
11
|
+
* Ordered by reliability:
|
|
12
|
+
* 1. `LLM_WIKI_HOST` — explicit escape hatch (tests, exotic embeddings).
|
|
13
|
+
* 2. The agent directory path: pi resolves `~/.pi/agent`, omp `~/.omp/agent`.
|
|
14
|
+
* A `PI_CODING_AGENT_DIR` override that keeps the marker segment still
|
|
15
|
+
* classifies correctly; anything else falls through.
|
|
16
|
+
* 3. `OMP_PROFILE`, which omp sets on itself whenever a profile is active.
|
|
17
|
+
* 4. Default `pi` — the historical behaviour.
|
|
18
|
+
*/
|
|
19
|
+
export function detectHost() {
|
|
20
|
+
const forced = process.env.LLM_WIKI_HOST?.trim().toLowerCase();
|
|
21
|
+
if (forced === "omp" || forced === "pi")
|
|
22
|
+
return forced;
|
|
23
|
+
let agentDir = "";
|
|
24
|
+
try {
|
|
25
|
+
agentDir = getAgentDir();
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
agentDir = "";
|
|
29
|
+
}
|
|
30
|
+
if (agentDir) {
|
|
31
|
+
const segments = agentDir.split(/[\\/]/);
|
|
32
|
+
if (segments.includes(".omp"))
|
|
33
|
+
return "omp";
|
|
34
|
+
if (segments.includes(".pi"))
|
|
35
|
+
return "pi";
|
|
36
|
+
}
|
|
37
|
+
if (process.env.OMP_PROFILE !== undefined)
|
|
38
|
+
return "omp";
|
|
39
|
+
return "pi";
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Every project settings file that may hold `llm-wiki` configuration, ordered
|
|
43
|
+
* from lowest to highest precedence so callers can merge left-to-right.
|
|
44
|
+
*
|
|
45
|
+
* The host's *native* directory is last (wins). The foreign directory is still
|
|
46
|
+
* read so a vault configured under pi keeps working after omp takes over the
|
|
47
|
+
* repository, and vice versa. Within a directory `config.yml` follows
|
|
48
|
+
* `settings.json`, matching omp's own project-settings precedence.
|
|
49
|
+
*/
|
|
50
|
+
export function listProjectSettingsFiles(cwd, host = detectHost()) {
|
|
51
|
+
const foreign = host === "omp" ? "pi" : "omp";
|
|
52
|
+
const files = [];
|
|
53
|
+
for (const kind of [foreign, host]) {
|
|
54
|
+
const dir = join(cwd, CONFIG_DIR[kind]);
|
|
55
|
+
for (const name of SETTINGS_FILES)
|
|
56
|
+
files.push(join(dir, name));
|
|
57
|
+
}
|
|
58
|
+
return files;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* User-level settings files, lowest → highest precedence.
|
|
62
|
+
*
|
|
63
|
+
* `getAgentDir()` already resolves per host (`~/.pi/agent` vs `~/.omp/agent`),
|
|
64
|
+
* so only the file names differ: omp migrates `settings.json` into `config.yml`
|
|
65
|
+
* on first start, and a migrated install has *only* the YAML file.
|
|
66
|
+
*/
|
|
67
|
+
export function listGlobalSettingsFiles() {
|
|
68
|
+
let agentDir = "";
|
|
69
|
+
try {
|
|
70
|
+
agentDir = getAgentDir();
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
if (!agentDir)
|
|
76
|
+
return [];
|
|
77
|
+
return SETTINGS_FILES.map((name) => join(agentDir, name));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The project settings file this extension writes to.
|
|
81
|
+
*
|
|
82
|
+
* Always JSON (`settings.json`) — both hosts read it, and rewriting a user's
|
|
83
|
+
* hand-authored `config.yml` would destroy comments and formatting.
|
|
84
|
+
*
|
|
85
|
+
* Directory choice: an already-existing project config directory wins (so a
|
|
86
|
+
* repo that only has `.pi/` keeps a single settings file), otherwise the
|
|
87
|
+
* detected host's native directory is created.
|
|
88
|
+
*/
|
|
89
|
+
export function resolveProjectSettingsPath(cwd, host = detectHost()) {
|
|
90
|
+
const native = join(cwd, CONFIG_DIR[host]);
|
|
91
|
+
if (existsSync(native))
|
|
92
|
+
return join(native, "settings.json");
|
|
93
|
+
const foreign = join(cwd, CONFIG_DIR[host === "omp" ? "pi" : "omp"]);
|
|
94
|
+
if (existsSync(foreign))
|
|
95
|
+
return join(foreign, "settings.json");
|
|
96
|
+
return join(native, "settings.json");
|
|
97
|
+
}
|
|
@@ -239,6 +239,11 @@ export function buildReminderText() {
|
|
|
239
239
|
* `options.display` (issue #77) controls whether the reminder is shown to the
|
|
240
240
|
* user (`true`, the default) or injected silently into model context only
|
|
241
241
|
* (`false`). Pass a resolver so the live `notices` config is read at send time.
|
|
242
|
+
*
|
|
243
|
+
* `options.enabled` gates the reminder entirely — note that `display: false`
|
|
244
|
+
* still injects it into model context, so it is NOT a way to switch the
|
|
245
|
+
* reminder off. Callers pass a resolver that answers "does a wiki apply to the
|
|
246
|
+
* current working directory", evaluated per turn because the session can move.
|
|
242
247
|
*/
|
|
243
248
|
export function registerObservationReminder(pi, reminderState, options) {
|
|
244
249
|
const REMINDER_INTERVAL = options?.turnsBetweenReminders ?? 5;
|
|
@@ -267,6 +272,10 @@ export function registerObservationReminder(pi, reminderState, options) {
|
|
|
267
272
|
// errors cause multiple retries, each firing agent_end).
|
|
268
273
|
if ("willRetry" in event && event.willRetry)
|
|
269
274
|
return;
|
|
275
|
+
// No wiki applies here: never nag, and never accumulate a pending reminder
|
|
276
|
+
// that would fire the moment the session moves into a wiki-bearing project.
|
|
277
|
+
if (options?.enabled && !options.enabled())
|
|
278
|
+
return;
|
|
270
279
|
turnsSinceLastReminder++;
|
|
271
280
|
if (turnsSinceLastReminder < REMINDER_INTERVAL)
|
|
272
281
|
return;
|