Files
redmine/docs/karpathywiki_plugin_inspection.md
Jason Thistlethwaite 9ee9eb3ec6 Organized
2026-10-17 20:50:35 -04:00

291 lines
8.6 KiB
Markdown

# KarpathyWiki Obsidian Plugin Inspection
**Date:** 2026-07-09
**Plugin:** `karpathywiki` / `green-dalii/obsidian-llm-wiki`
**Repo inspected:** `https://github.com/green-dalii/obsidian-llm-wiki`
**Fresh clone verification:** commit `0979d50`
**License:** Apache-2.0
**Version observed:** 1.24.0
## Why inspected
Jason observed that the Obsidian Karpathy LLM Wiki plugin is doing much of what the Redmine ticket decomposition process should do: entity/concept extraction, knowledge graph page generation, links, indexes, and conversational query. The question was whether we can trigger it headlessly/CLI or mirror its logic.
## Repository / structure findings
The plugin is a compact TypeScript Obsidian plugin.
Important files:
```text
src/main.ts
src/wiki/wiki-engine.ts
src/wiki/source-analyzer.ts
src/wiki/page-factory.ts
src/wiki/prompts/ingestion.ts
src/wiki/prompts/generation.ts
src/wiki/prompts/merge.ts
src/wiki/prompts/lint.ts
src/wiki/query-engine/
src/core/
```
Package metadata:
```json
{
"name": "karpathywiki",
"version": "1.24.0",
"main": "main.js"
}
```
Fresh clone verification confirmed `package.json` has no `bin` entry:
```text
PACKAGE {'name': 'karpathywiki', 'version': '1.24.0', 'main': 'main.js', 'bin': None, 'license': 'Apache-2.0'}
```
There is no package `bin` entry and no obvious standalone CLI exposed by the project.
## Obsidian command entry points
`src/main.ts` registers Obsidian commands:
```text
ingest-source
ingest-folder
ingest-multiple-files
query-wiki
lint-wiki
regenerate-index
cancel-ingestion
ingest-active-file
view-ingestion-history
recreate-welcome-note
```
These are Obsidian command palette commands, not shell commands.
If Obsidian is running, it may be possible to trigger commands through Obsidian/Advanced URI style automation, but that would still depend on Obsidian being open and the plugin being loaded. It is not a true headless pipeline.
## Core engine dependency
The core class is `WikiEngine` in `src/wiki/wiki-engine.ts`.
It is separate from the plugin UI, but its constructor requires Obsidian types and APIs:
```ts
constructor(
app: App,
settings: LLMWikiSettings,
getLLMClient: () => LLMClient | null,
schemaManager: SchemaManager,
onFileWrite?: (path: string) => void,
onProgress?: (message: string) => void,
onDone?: (report: IngestReport) => void
)
```
It uses:
- `app.vault.read`
- `app.vault.getMarkdownFiles`
- `app.vault.process`
- `app.vault.create`
- `app.vault.getAbstractFileByPath`
- `app.metadataCache.getFileCache`
- `TFile`, `TFolder`, `Notice`, `normalizePath`
Therefore, the engine cannot be called directly from Node/Python CLI without either:
1. running inside Obsidian, or
2. writing an adapter/shim that emulates enough of Obsidian's `App/Vault/metadataCache/TFile` behavior.
## Portable logic worth mirroring
The useful logic is not locked to Obsidian conceptually. It can be mirrored or adapted:
### Source analysis
`src/wiki/source-analyzer.ts`:
- reads source content
- checks blank/duplicate content
- prompts LLM for structured JSON
- extracts entities and concepts
- includes aliases
- collects verbatim quotes / provenance
- identifies contradictions, related pages, key points
- normalizes irregular LLM JSON
The core ingestion prompt is in `src/wiki/prompts/ingestion.ts`.
Notable extraction output shape:
```json
{
"source_title": "...",
"summary": "...",
"entities": [
{
"name": "...",
"type": "person|organization|project|product|event|place|other",
"aliases": [],
"summary": "...",
"mentions_in_source": [],
"mentions_with_provenance": [],
"related_entities": [],
"related_concepts": []
}
],
"concepts": [],
"contradictions": [],
"related_pages": [],
"key_points": []
}
```
### Page generation
`src/wiki/page-factory.ts`:
- slugifies entities/concepts
- checks existing pages
- resolves duplicates via slug/alias/LLM semantic match
- generates entity/concept pages
- merges into existing pages
- protects reviewed pages
- corrects polluted wikilinks
- injects provenance/mentions
### Prompts
`src/wiki/prompts/generation.ts` includes high-value generation prompts for:
- entity pages
- concept pages
- source summary pages
- preserving reviewed pages
### Query / graph retrieval
The README claims zero-embedding graph retrieval via Personalized PageRank over the wiki link graph. Source references in `WikiEngine` show:
```ts
buildGraphFromContent(...)
getOrBuildGraph(...)
```
and query pipeline files exist under:
```text
src/wiki/query-engine/pipeline/
```
This is useful design inspiration, but not required for the first Redmine decomposition tool because gbrain already supplies search/indexing and the vault graph itself supplies wikilinks.
## Recommendation
Do **not** depend on Obsidian running for Redmine ticket decomposition.
Instead:
1. Mirror the plugin's source-analysis and page-generation logic in our own CLI-oriented tool.
2. Reuse its prompt structure and output schema ideas.
3. Write directly to the filesystem vault, but outside the plugin-owned `wiki/` tree by default.
4. Use gbrain for indexing/search after files are written.
5. Keep Redmine contact updates as a separate explicit apply phase.
6. Preserve compatibility with Obsidian/KarpathyWiki by using normal Markdown, wikilinks, and frontmatter fields the plugin understands where practical.
Compatibility rule: the plugin owns `wiki/entities`, `wiki/concepts`, `wiki/sources`, `wiki/index.md`, and `wiki/log.md`. The headless decomposer should default to LDR-owned paths like `Timeline/`, `entities/organizations/`, and `Processes/Redmine/`, linking to `wiki/...` pages when useful but not editing them.
This gives us the same broad effect without requiring a GUI Obsidian session and without competing with the existing plugin state.
## Possible implementation paths
### Path A — Thin TypeScript headless port
Build a Node/TypeScript CLI in `/home/jason/projects/redmine` or a sibling project that imports/copied logic from the plugin and supplies a fake Obsidian adapter.
Pros:
- Closer to upstream code.
- Easier to vendor future prompt improvements.
- Can reuse zod/AI SDK provider setup.
Cons:
- Need to emulate enough of Obsidian `Vault`, `TFile`, metadata cache, and settings.
- Adds Node/TypeScript toolchain complexity to Redmine workflow.
### Path B — Python mirror using existing Redmine tooling
Implement the same conceptual pipeline in Python alongside `redmine_tickets.py`:
- source normalization
- LLM JSON extraction
- entity/concept dedup via filesystem search + slug rules
- page generation templates
- timeline/entity writers
- gbrain sync hooks
Pros:
- Fits current Redmine tooling.
- Easier to integrate with ticket cache and contact updates.
- No Obsidian runtime needed.
Cons:
- We do not directly reuse TypeScript implementation.
- Need to maintain our own prompt/schema logic.
### Path C — Obsidian-driven automation
Use Obsidian command automation / Advanced URI to trigger plugin commands.
Pros:
- Minimal code if it works.
Cons:
- Requires Obsidian running.
- Harder to make deterministic/headless/cron-safe.
- Harder to feed Redmine tickets and capture structured contact-update proposals.
## Best fit for LDR Redmine decomposition
Path B is the best first implementation path.
Reasons:
- Redmine tickets are already fetched/cached in Python.
- We need Redmine contact updates and safety gates.
- We need Onyx URLs and gbrain sync hooks.
- We need headless/cron/agent execution.
- We already proved manual note generation format in the decomposition pilot.
Use the plugin as a reference for:
- `src/wiki/prompts/ingestion.ts` — source analysis prompt and entity/concept output shape
- `src/wiki/prompts/generation.ts` — entity/concept/source page generation prompts
- `src/wiki/prompts/merge.ts` — classify-then-route merge strategy for updating existing pages
- `src/wiki/prompts/lint.ts` — wiki quality checks and contradiction review ideas
- `src/wiki/source-analyzer.ts` — JSON normalization, duplicate/blank source handling, provenance mentions
- `src/wiki/page-factory.ts` — slug/alias resolution, cross-type collision handling, merge-vs-append routing
- `src/wiki/query-engine/` — graph retrieval ideas for later, not first pass
Do not try to invoke it via Obsidian as the primary production pipeline; use the source as a design reference for a headless Python mirror.
## Immediate next action
Update `ticket_decomposition_knowledge_ingestion_plan.md` so Phase 2 says:
- use KarpathyWiki plugin prompt/schema as reference
- implement a Python headless mirror first
- consider TypeScript adapter later only if Python mirror becomes too costly
Then implement a `decompose --dry-run` engine using the pilot tickets as fixtures.