Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,13 +379,10 @@ When the user has explicitly green-lit merging this branch to `main`:
message covering the whole change
4. `git push origin main`
5. Delete the feature branch locally (`git branch -d <feature-branch>`).
Do NOT try to delete the remote feature branch - Anthropic's GitHub
app doesn't carry the `delete_ref` scope, so `git push origin
--delete <feature-branch>` returns HTTP 403 by design. That's not a
fixable condition from inside the session; the user cleans up stale
remote branches on their own cadence. No need to mention the skipped
remote delete in the end-of-turn summary either - it's the expected
shape of every merge.
Leave the remote feature branch alone - the user runs a periodic
cleanup script over stale remote branches. No need to mention the
skipped remote delete in the end-of-turn summary either; it's the
expected shape of every merge.

**Claude Code CLI** (interactive local sessions): commit to whatever branch
is currently checked out and stop. Do not rebase, do not merge, do not push,
Expand Down
16 changes: 16 additions & 0 deletions docs/dev/wiki.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,22 @@ JSON).

## Gotchas

- **The wiki is user-centric, not a general encyclopedia.** The
per-conversation prompt has historically slipped on this - a
brainstorm about app naming that mentioned the 1980s "Kermit"
protocol produced a standalone "Kermit protocol" article. Both
the per-conversation prompt and the librarian prompt now carry
an explicit scope block (IN: projects, people, places,
learning, work, hobbies, experiments / OUT: generic technical
concepts, world history, public figures the user does not
know, tutorials). The librarian's workflow step 1 is "delete
out-of-scope articles", deliberately ahead of duplicate
consolidation so it doesn't tidy two off-topic articles into
one off-topic article. External topics referenced inside a
user-centric article get a Markdown link (Wikipedia
conventionally), not their own page. If you relax the scope
rule, leave the historical failure mode noted somewhere or
the per-thread shape will silently re-introduce it.
- **Use `messages.created_at` for the day-gate, not
`threads.updated_at`.** The journal RPC reads
`threads.updated_at` because journals fired on a same-day
Expand Down
48 changes: 45 additions & 3 deletions docs/user/wiki.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Wiki

The Wiki is a flat encyclopedia about you. Every entry is a titled
article in encyclopedic third-person prose - about a project, a person
in your life, a place, an interest, a recurring situation. There's no
The Wiki is a flat encyclopedia **about you** - your projects, the
people in your life, places you live or care about, things you're
learning or reading, work, hobbies, experiments. Every entry is a
titled article in encyclopedic third-person prose. There's no
nesting; everything sits at the same level and the drawer lists
articles alphabetically.

Expand All @@ -13,6 +14,47 @@ topical pages that cover what something IS - "the recipe project",
"Maya", "Lisbon trip planning". An article sits across many
conversations.

## Scope: about you, not about the world

The wiki is deliberately user-centric. Articles describe things in
your life. They do **not** describe generic topics that came up in
conversation. So:

**In scope** - article-worthy when discussed:

- Projects you are building, planning, or running.
- People in your life - family, friends, colleagues, contacts.
- Places you live, work, travel to, or care about.
- Things you are learning or reading - books, courses, papers,
skills you are practising.
- Habits and experiments you are tracking - a running streak,
a sourdough starter, an elimination diet.
- Your career, current job, prior roles, ongoing work.
- Hobbies and interests you have invested time in.

**Out of scope** - even if the conversation discussed them at length:

- General technical concepts, libraries, protocols, or frameworks
not specific to one of your projects.
- World-knowledge topics: historical events, scientific concepts,
geography.
- Public people you don't know personally - celebrities, authors of
books you're reading, historical figures.
- News, current events.
- Tutorials and one-off help interactions.

When an external topic gets mentioned inside a user-centric article
(say, you're building an app whose name references a 1980s
file-transfer protocol), the agent will add a Markdown link to a
public source like Wikipedia rather than creating a separate
article. External topics are linked, never given their own pages.

Both the per-conversation agent and the librarian enforce this
scope. The librarian will delete out-of-scope articles it finds on
its periodic sweep, so any encyclopedic-but-not-about-you articles
that slipped through earlier should disappear over the next 12 to
24 hours.

## Opening the Wiki

Click the **Wiki** tab in the left drawer. The sidebar shows the
Expand Down
78 changes: 61 additions & 17 deletions src/lib/agents/wiki-librarian/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,24 @@
* - Input shape. The librarian gets a flat list of every article
* (title + short excerpt) instead of a conversation. The opening
* paragraph reflects that.
* - Goal. Reorganise, fact-check, consolidate. Not "react to a
* conversation". The librarian's win condition is "the wiki is
* more coherent than it was at the start of this run", which
* usually means fewer articles or sharper boundaries between
* them, not more.
* - Goal. Reorganise, fact-check, consolidate, and enforce scope.
* Not "react to a conversation". The librarian's win condition
* is "the wiki is more coherent than it was at the start of
* this run", which usually means fewer articles or sharper
* boundaries between them, not more.
* - Tools. Has wiki_search + wiki_update + wiki_delete +
* conversation_search. NO wiki_create - the librarian does not
* invent new articles.
*
* The scope-cleanup pass is workflow step 1, deliberately ahead of
* the duplicate / staleness / boundary passes. The per-conversation
* agent has historically slipped out-of-scope articles into the wiki
* (a Kermit-protocol article from a brainstorm about app naming,
* for example - see src/lib/agents/wiki/prompt.ts for the matching
* scope rule). Getting those out before the rest of the workflow
* runs avoids "consolidating" two off-topic articles into one
* tidier-but-still-off-topic article.
*
* Voice and "preserve facts" discipline are shared with the per-
* conversation agent's prompt - same encyclopedic third-person
* register, same "do not fabricate / do not discard facts" rules.
Expand All @@ -28,14 +37,30 @@ export function buildWikiLibrarianPrompt(opts: {
'list below is every article in the wiki right now, by title, with',
'a short excerpt of each. Your job is to make the wiki more',
'coherent than you found it - not by adding articles, but by',
'consolidating duplicates, fact-checking against conversation',
'history, and tightening the boundaries between articles that',
'overlap.',
'consolidating duplicates, removing out-of-scope articles, fact-',
'checking against conversation history, and tightening the',
'boundaries between articles that overlap.',
'',
'Articles in the wiki:',
'',
articleList,
'',
'**Scope: this wiki is about the user, not the world.** Every',
"article must be about the user's life, projects, people, work,",
'learning, or interests. Articles whose subject is a generic world-',
'knowledge topic (a programming concept, a protocol, a historical',
'event, a public figure the user does not know personally, a',
'tutorial or explainer of something external) DO NOT belong in the',
'wiki and should be deleted - even if they are well-written. The',
'concrete failure mode the wiki must defend against: a brainstorming',
'conversation mentioned that an app is named after the 1980s "Kermit"',
'protocol, and the per-conversation agent created a standalone',
'"Kermit protocol" article. The fix is to delete that article (and,',
'if the relevant user-centric article exists, e.g. one about the',
'app the user is building, optionally edit a single Markdown link',
'into it that references Kermit). External topics get LINKED from',
'user-centric articles; they do not get their own articles.',
'',
'**Tools you can use**:',
'',
'- `wiki_search` - read the full body of any article (search by',
Expand All @@ -49,10 +74,15 @@ export function buildWikiLibrarianPrompt(opts: {
' that are still accurate; integrate facts from a duplicate',
' article you intend to delete; correct stale information you',
' verified is contradicted by recent conversations.',
'- `wiki_delete` - hard-delete an article. ONLY use this for',
' consolidation: when you have just updated another article to',
' cover everything the deleted article said. Never delete an',
' article whose content has not been merged elsewhere.',
'- `wiki_delete` - hard-delete an article. Use for two cases:',
' (a) consolidation - you just updated another article to cover',
' everything the deleted article said.',
' (b) out-of-scope cleanup - the article is about a generic world-',
" knowledge topic that does not belong in the user's wiki",
' (see the scope rule above). For these, no merge is required;',
' the article should not exist at all.',
' Never delete a user-centric article whose content has not been',
' merged into another user-centric article.',
'',
'**You DO NOT have wiki_create.** New articles flow from the per-',
'conversation wiki agent or directly from the user. Your job is',
Expand All @@ -63,20 +93,34 @@ export function buildWikiLibrarianPrompt(opts: {
'',
'**Workflow**:',
'',
'1. **Scan the list above for duplicates and near-duplicates.**',
' Two articles whose titles or excerpts strongly overlap are',
' the highest-value consolidation targets. Use wiki_search to',
'1. **Scan for out-of-scope articles first.** Look at the list',
' above for any title or excerpt that reads as a generic',
' encyclopedia topic rather than something specific to the',
' user (technical concepts, protocols, world events, public',
' figures the user does not know personally, generic tutorials,',
" debug-session writeups). For each suspicious article: read",
' the full body via wiki_search to confirm it is not in fact',
" about a project the user is building or someone in their life,",
' and only after confirming, wiki_delete it. If a related user-',
' centric article exists where the topic is referenced (e.g. an',
' article about the app whose name references the deleted topic),',
' wiki_update that article first to add a short Markdown link to',
' a public reference (Wikipedia conventionally) so the connection',
' is preserved.',
'2. **Scan the list for duplicates and near-duplicates.** Two',
' articles whose titles or excerpts strongly overlap are the',
' next-highest-value consolidation targets. Use wiki_search to',
' read full bodies before deciding. If you confirm overlap:',
' wiki_update the article that is the better home (longer,',
' broader, or more accurate) to absorb the unique facts from',
' the duplicate, then wiki_delete the duplicate.',
'2. **Check for stale facts.** When an excerpt makes a specific',
'3. **Check for stale facts.** When an excerpt makes a specific',
' claim that could plausibly have changed (a job title, a',
' relationship status, a project status, a date), use',
' conversation_search to look for recent mentions. If you find',
' a clear contradiction, wiki_update the article. If you find',
' nothing or only ambiguous evidence, leave it alone.',
'3. **Tighten subject boundaries.** When two articles cover',
'4. **Tighten subject boundaries.** When two articles cover',
' adjacent topics that confusingly bleed into each other (a',
' "Maya" article and a "household" article that both cover',
' the same person), decide which article is the right home',
Expand Down
77 changes: 76 additions & 1 deletion src/lib/agents/wiki/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,24 @@
* Refer to the subject directly (their first name, the project
* name) rather than "the user" so articles read as encyclopedia
* entries rather than session-scoped notes.
* - **User-centric scope.** Earlier production traffic also
* surfaced the agent writing standalone articles about generic
* world-knowledge topics that came up in conversation - e.g.
* after a brainstorm about app naming that mentioned the 1980s
* "Kermit" file-transfer protocol, the agent created a "Kermit
* protocol" article. The wiki is meant to be ABOUT the user
* (their projects, people in their life, things they're
* learning, their work), not a general encyclopedia of topics
* that came up. The prompt now carries an explicit scope block
* with concrete IN / OUT examples and a rule that OUT-of-scope
* references inside a user-centric article get a Markdown link
* to a public source (Wikipedia conventionally) rather than a
* separate article. Do not relax this without leaving the
* historical failure mode noted somewhere - the per-conversation
* shape pushes the model toward "this came up so it deserves a
* page" by default.
* - "Update is the default; create is rare." Earlier production
* traffic showed the agent generating one new article per
* traffic also showed the agent generating one new article per
* conversation - the per-thread shape biased it toward
* "this conversation is its own topic, write a new article".
* The prompt now leads with the bias hard the other way:
Expand Down Expand Up @@ -57,6 +73,55 @@ export const WIKI_AUTONOMOUS_PROMPT = [
'situation. Articles are NEVER auto-injected into the chat; the user',
'and assistant only reach them through wiki_search.',
'',
'**Scope: this wiki is about the user, not the world.** Every article',
"must be about the user's life, interests, projects, or context.",
'External topics that came up in conversation but have no specific',
"connection to the user do NOT get their own article, even if the",
'conversation discussed them at length. They get linked from a user-',
'centric article instead.',
'',
'IN scope (article-worthy when discussed):',
"- Projects the user is building, planning, or running.",
"- People in the user's life - family, friends, colleagues, contacts.",
"- Places the user lives, works, travels, or cares about.",
"- Things the user is learning or reading - books, courses, papers,",
' skills they are practising.',
"- Habits and experiments the user is tracking - a running streak,",
' a sourdough starter, an elimination diet.',
"- The user's career, current job, prior roles, ongoing work.",
"- Hobbies and interests the user has invested time in.",
'- The user themselves (a single article about them as the subject).',
'',
'OUT of scope (do NOT create articles for these, even if the',
'conversation went deep on them):',
"- General technical concepts, libraries, protocols, or frameworks",
" that are not specific to one of the user's projects (e.g.",
' JavaScript closures, the Kermit protocol, HTTP semantics, regex).',
"- World-knowledge topics: historical events, scientific concepts,",
' geography, biology, finance fundamentals.',
"- Public people the user does not know personally (celebrities,",
' authors of books they are reading, historical figures).',
"- News, current events, things in the wider world.",
"- Tutorials, debug sessions, or one-off help interactions where the",
' user was just looking up information.',
'',
'When an OUT-of-scope topic comes up INSIDE a user-centric article',
'(e.g. the conversation mentioned that the app being built is named',
"after a 1980s file-transfer protocol called \"Kermit\"), link to a",
'public reference rather than creating a separate article. The link',
'goes inside the relevant user-centric article in standard Markdown',
'form, e.g.',
' "The name comes from [Kermit](https://en.wikipedia.org/wiki/Kermit_(protocol)),',
' a 1980s file-transfer protocol."',
'Wikipedia URLs are the conventional choice; any stable public URL',
'works. Do NOT fabricate URLs - only use links you can write from',
'memory of well-known articles, or omit the URL and just bold or',
'italicize the term.',
'',
'If a conversation is mostly out-of-scope - tutorials, generic',
'technical Q&A, news, debugging unrelated libraries - produce zero',
'edits. That is a correct outcome.',
'',
'**The single most important discipline: UPDATE is the default,',
'CREATE is rare.** A new article should be the exception, not the',
'rule. Most conversations should result in zero or one wiki_update',
Expand Down Expand Up @@ -148,6 +213,16 @@ export const WIKI_MANUAL_PROMPT = [
'person. Refer to the subject directly (a first name, the project',
"name) rather than \"the user\" unless the article's topic IS the user.",
'',
'**Scope**: this wiki is about the user, not the world. Articles',
"describe the user's life, projects, people, work, learning, and",
'interests. References to external topics (a generic library, a',
'historical event, a public figure the user does not know) belong',
"as Markdown links inside a user-centric article, NOT as their own",
'articles. If the user instructs you to add information that would',
'pull the article away from being about them - e.g. asks you to',
'expand the article into a general explainer of an external topic',
'- prefer a noop with a one-sentence reason over silently drifting.',
'',
'**Rules**:',
'',
"- Do exactly what the user asks. Their instructions are the binding",
Expand Down
Loading
Loading