Skip to content

Wiki: add librarian, strengthen prompt, fix delete button#5

Merged
sysread merged 1 commit intomainfrom
claude/wiki-strengthen-and-librarian
May 9, 2026
Merged

Wiki: add librarian, strengthen prompt, fix delete button#5
sysread merged 1 commit intomainfrom
claude/wiki-strengthen-and-librarian

Conversation

@sysread
Copy link
Copy Markdown
Owner

@sysread sysread commented May 9, 2026

=head1 SYNOPSIS

Three changes addressing observations from production traffic on the
just-shipped wiki:

  • Delete button on the article view is blank - the local .danger
    CSS painted red text on a red background.
  • The per-conversation agent generates one new article per
    conversation instead of updating existing ones.
  • Add a second background agent (the librarian) that
    consolidates duplicates and fact-checks against conversation
    history.

=head1 PURPOSE

After the initial wiki ship landed, two issues surfaced in
production:

  1. The Delete button on an open article had no visible label. CSS
    inspection showed the global button.danger rule fills the
    button red and uses light text, while the local .danger
    override I added re-set color to red - red text on red
    background = invisible.
  2. The autonomous wiki agent was generating one wiki_create call
    per settled conversation - the per-thread invocation shape
    biased it hard toward "this conversation is its own topic, so
    write a new article". The wiki was accumulating near-duplicates
    instead of coherent topical pages.

The user also asked for a separate "librarian" agent whose job is
to organise the wiki by subject and fact-check articles against the
conversation history.

=head1 DESCRIPTION

=head2 Layer 1: how the existing wiki behaves

Wiki.svelte renders the open article with three trailing
buttons (Edit / Ask agent to update / Delete). The local
stylesheet block defines .danger { color: var(--error) } to
border-and-color the Delete button red. The global
button.danger rule already paints the button solid red with
contrasting light text via --ink-on-danger.

The autonomous wiki agent (src/lib/agents/wiki/) claims one
settled thread per cycle, builds a prompt out of
WIKI_AUTONOMOUS_PROMPT, and runs runHeadlessToolLoop against
wikiToolbox (search + create + update + delete). The prompt
told the agent to "search before write", but its workflow steps
landed equally on update vs create - and there was no instruction
to retry the search with different angles before falling back to
create.

There is no second agent. Articles only mutate from the per-
conversation agent's tool calls or from manual user edits.

=head2 Layer 2: what this PR changes, parallel to layer 1

Delete button. Drop the local .danger block from
Wiki.svelte and inline a comment explaining why. The global
rule wins; the button now reads "Delete" in light text on the red
fill, matching the Memories panel's delete styling.

Autonomous prompt. Rewrite WIKI_AUTONOMOUS_PROMPT:

  • New leading paragraph: "The single most important
    discipline: UPDATE is the default, CREATE is rare.
    " Plus an
    explicit framing that zero edits is a normal outcome on
    chitchat / tactical conversations.
  • Workflow step 1 now mandates "Search broadly first, with
    multiple query angles" - at least TWO different wiki_search
    calls with different phrasings before concluding nothing
    exists. Includes concrete examples ("kombucha" might already
    exist as "fermented drinks").
  • Workflow step 2 emphasises: "Even a loosely-related existing
    article is usually the right home for new information". The
    goal is to extend rather than fragment.
  • Workflow step 3 explicitly frames wiki_create as "the last
    resort", with three preconditions before firing.

The rationale block above the prompt now records the historical
"one article per conversation" failure mode so a future revisit
won't quietly relax the discipline.

Wiki librarian (the new agent):

  • SQL: profiles.wiki_librarian_last_run_at column +
    claim_wiki_librarian_run(int) RPC. UPDATE-with-WHERE
    atomically returns true at most once per min_interval_seconds
    across all of a user's devices.
  • Worker: src/lib/agents/wiki-librarian/{types,prompt,agent, loop,worker,manager}.ts. Lock name
    nak:wiki-librarian-worker, lease partition
    'wiki-librarian', defaults to 12h minimum interval and a
    1h idle nap.
  • Toolbox: wikiLibrarianToolbox bundles wiki_search + wiki_update + wiki_delete + conversation_search. No
    wiki_create
    - the librarian only consolidates.
  • Agent flow: snapshot all articles via listWikiArticles,
    project to (id, title, excerpt), render into the prompt,
    run runHeadlessToolLoop. Skips when fewer than 3 articles
    (LIBRARIAN_MIN_ARTICLES) or when the cross-device claim
    returned too-soon.
  • Settings: new independent wikiLibrarianEnabled toggle on
    Settings -> Wiki. Default-on. The two toggles
    (wikiAutomaticEnabled and wikiLibrarianEnabled) are
    independent so the user can run one without the other.
  • Model: pinned to deepseek-v4-flash (same as the per-
    conversation wiki agent and journal/reflection); rationale
    documented inline above AGENT_MODELS.

=head2 Layer 3: how that resolves PURPOSE

  • The delete button now renders correctly. Same global treatment
    as every other delete button in the app.
  • The autonomous agent now biases hard toward updating existing
    articles. New article creation should be rare; chitchat
    conversations should produce zero edits, which the prompt
    explicitly names as a correct outcome.
  • The librarian provides a second pass over time: even if the
    per-conversation agent occasionally lets a duplicate slip
    through, the librarian's 12h cycle catches it, consolidates,
    and fact-checks against conversation history.

=head1 Notes for AI reviewers

  • The librarian intentionally has no wiki_create. New articles
    flow from the per-conversation agent or the user. Removing this
    constraint would let the librarian invent articles at every
    cycle.
  • Pointer-advance on the per-conversation wiki worker is still
    unconditional on done (no change). With the strengthened
    prompt, "no edits" cycles will be more common than before;
    that's deliberate.
  • The 12-hour interval is enforced server-side by the claim RPC;
    client-side timing is just an optimisation to not spam Postgres.
    Two devices that both wake up will both call the RPC; only one
    succeeds.
  • LIBRARIAN_MIN_ARTICLES = 3 is a soft floor - the librarian
    has nothing useful to do on a brand-new wiki with one or two
    articles. Bump if you want.

https://claude.ai/code/session_015XcR7xzLdij66ZbYERUdLH


Generated by Claude Code

…utton

Three changes addressing observations from production traffic.

**Delete button visibility**: Wiki.svelte's local `.danger` CSS reset
the button's `color` to red on top of the global red background fill,
painting the button text invisible. Drop the local override and trust
the global `button.danger` rule (matches the inline note in
Memories.svelte's stylesheet section).

**Per-conversation wiki agent prompt**: production traffic showed the
agent generating one new article per conversation - the per-thread
shape biased it hard toward "this conversation is its own topic,
write a new article". The prompt now opens with an explicit rule
("UPDATE is the default, CREATE is rare") and workflow step 1
mandates at least two different `wiki_search` query angles before
considering `wiki_create`. Most conversations should produce zero
edits; chitchat / tactical Q&A should produce nothing at all. Bumps
the rationale comment block accordingly.

**Wiki librarian agent**: a second background agent whose job is to
make the wiki more coherent than it found it. Reads the full
alphabetical article list, fact-checks specific claims against
conversation history via `conversation_search`, consolidates
duplicates via `wiki_update` + `wiki_delete`. Critically, the
librarian has NO access to `wiki_create` - new articles flow from
the per-conversation agent or the user. The librarian only
consolidates what exists.

  - schema: `profiles.wiki_librarian_last_run_at` plus
    `claim_wiki_librarian_run(int)` RPC. UPDATE-with-WHERE
    atomically returns true at most once per min-interval across
    all of a user's devices.
  - timing: 12h minimum interval; 1h idle nap so a too-soon device
    rechecks the claim hourly without spamming.
  - lease partition `'wiki-librarian'` and lock
    `nak:wiki-librarian-worker`, distinct from the per-
    conversation wiki worker so both run alongside each other.
  - new toolbox `wikiLibrarianToolbox` (search/update/delete +
    conversation_search) parallel to the existing `wikiToolbox`.
  - new `AgentRole 'wikiLibrarian'` pinned to deepseek-v4-flash;
    rationale documented next to the existing wiki entry.
  - new `wikiLibrarianEnabled` setting, independent toggle from
    `wikiAutomaticEnabled` so the user can run one without the
    other. Default-on. Settings -> Wiki has both toggles.

User and dev docs updated to describe the librarian, the dual
toggles, and the `update-is-default` discipline.

https://claude.ai/code/session_015XcR7xzLdij66ZbYERUdLH
@sysread sysread merged commit a9b1626 into main May 9, 2026
1 check passed
@sysread sysread deleted the claude/wiki-strengthen-and-librarian branch May 9, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants