Files
coorl-lost-cities/docs/plans/librarian.md
T
coolguyandClaude Opus 4.7 b9bbb4fcf7 Bootstrap librarian Stage 1 with lychee link checker
Captures the full librarian design (two-layer architecture, three-stage
pipeline, vendor-agnostic via LIBRARIAN_LLM env, propose-only / no
auto-apply) in docs/plans/librarian.md. Lands the first concrete Stage 1
piece: scripts/librarian_check_links.py, a lychee --offline wrapper
ported from ~/dev/coolrl/src/coolrl/dev/check_doc_links.py.

Also moves the librarian prompt from .claude/agents/ (Claude Code only)
to scripts/librarian-prompt.md so any CLI can load it as a system
prompt later. Fixes one stale README link the new checker caught:
docs/classic-port-notes.md → docs/archive/classic-port-notes.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 23:15:06 +09:00

133 lines
5.3 KiB
Markdown

# Plan: Vendor-Agnostic Librarian
**Status:** Design phase. AGENTS.md "Docs & Experiment Workflow" section
landed in commit `09d5815` (2026-05-07). Shell script and prompt-file
move not yet started.
**Owner:** operator-driven; Claude/Codex/Gemini may execute parts.
**Background:** A `librarian` subagent at `.claude/agents/librarian.md`
already drafts research notes and surveys docs, but it is Claude-only,
read-mostly, and cannot be triggered periodically. Doc placement rules
also lived inside that prompt instead of AGENTS.md, so non-librarian
agents never saw them.
## Goal
Split documentation hygiene into two layers:
1. **Authoring rules in AGENTS.md** — every agent reads these on every
turn, so docs land in the right place at write time.
2. **`scripts/librarian.sh`** — periodic, vendor-agnostic, never
auto-applies. Catches drift that Layer 1 missed.
Layer 1 already exists (commit `09d5815`). This plan covers Layer 2.
## Non-Goals
- Replacing the existing `librarian.md` prompt content. The note-drafting
prompt is reused as a Stage 2 backend; only its location moves.
- Modifying `docs/archive/` or `runs/archive/`. Read-only forever.
- Editing code, configs, or running training/benchmarks from the
librarian. Doc/memory work only.
- Any `auto-apply` mode. Librarian only proposes; humans (or a follow-up
PR) apply.
## Architecture
Three stages, run in order. Each stage is independently invocable for
debugging.
### Stage 1 — Deterministic lint (no LLM)
Pure shell + `rg`/`find`/small Python helpers + [`lychee`](https://github.com/lycheeverse/lychee).
Output: a JSON report at `runs/tmp/librarian-<timestamp>.json`. Checks:
- **Markdown link integrity** (lychee): every `[text](path)` link in
`docs/**` and `README.md` resolves; anchors point to real headers.
Run `lychee --offline --root-dir . docs/**/*.md`. Precedent:
`~/dev/coolrl/src/coolrl/dev/check_doc_links.py` wraps the same call
for the sibling repo. We can lift that wrapper as-is.
- **Code-docs parity** (custom; lychee does not cover this): every
`path/to/file.py:NN` citation in `docs/**` resolves (file exists,
line within range). These are inline prose, not markdown links, so
lychee ignores them. Short Python helper required.
- **Stale plans**: `docs/plans/*.md` with mtime > N days and no recent
git commit referencing them.
- **Promotable archive**: `docs/archive/<name>-*.md` with no
`docs/research/<name>.md` counterpart, where the archive body
contains durable-conclusion language.
- **MEMORY.md drift**: index lines in `~/.claude/projects/.../MEMORY.md`
that disagree with the target file's `description:` frontmatter.
- **Duplicate prose**: pairs of docs with high text overlap (e.g., a
research note that copies an archive body instead of linking it).
- **Oversize**: files past the 500-line soft cap in AGENTS.md.
No LLM calls in Stage 1. Cheap to run frequently.
### Stage 2 — LLM judgment (vendor-agnostic)
Reads the Stage 1 report and the relevant doc bodies, dispatches to an
LLM CLI selected by env var:
```bash
LIBRARIAN_LLM=claude # claude code
LIBRARIAN_LLM=codex # codex cli
LIBRARIAN_LLM=gemini # gemini cli
```
The system prompt is loaded from `scripts/librarian-prompt.md` (moved
from `.claude/agents/librarian.md`; same content). LLM produces:
- Research-note drafts for promotable archive entries.
- MEMORY.md drift fixups (one-line diffs).
- Duplicate-doc merge proposals.
Output format: a unified diff + a short rationale per change. Never
written to disk by the LLM directly — emitted as a patch file under
`runs/tmp/librarian-<timestamp>.patch`.
### Stage 3 — Dry-run apply (default) / human apply
Default: print the patch and exit. With `--apply`: `git apply` the patch
(still requires the human to commit). Conflicts surface as standard
patch failures — operator resolves manually.
`docs/archive/` and `runs/archive/` are filtered out of any patch
target before apply.
## Concurrency Policy
Librarian is **never invoked from within an active agent session**. It
runs on demand by the operator (or via cron / post-commit hook). Because
Stage 3 is propose-only by default, two parties editing the same file
cannot corrupt each other — git's 3-way merge handles overlap when the
operator applies the patch.
## Open Questions
- Cron cadence? (start with manual-only; add cron once Stage 1 is
stable)
- "Durable-conclusion language" detection in Stage 1 — keyword heuristic
vs. defer to Stage 2 entirely. Default to deferring; Stage 1 just
flags every archive without a research counterpart.
- Where the Stage 1 ignore-list lives once false positives accumulate.
Tentatively `scripts/librarian-ignore.txt` with one rg-style pattern
per line.
## Progress
- ✅ AGENTS.md "Docs & Experiment Workflow" section landed
(commit `09d5815`, 2026-05-07).
- ✅ Plan drafted at `docs/plans/librarian.md` (this file).
- ✅ Prompt moved: `.claude/agents/librarian.md`
`scripts/librarian-prompt.md`. Claude-specific subagent registration
removed.
## Next Concrete Step
Build a minimum viable Stage 1: port coolrl's `check_doc_links.py`
into `scripts/` as `librarian_check_links.py` (one-file lychee wrapper),
verified to run against `docs/**`. No JSON aggregation yet — just exit
code 0/non-zero. This proves the deterministic-lint layer works on this
repo before adding the custom checks (code citations, stale plans,
etc.).