4 Commits
Author SHA1 Message Date
janvanwanandClaude Opus 5 6d6aa8bdb0 refactor(playbooks): drop the standalone Ponyman playbook
package / wheel (push) Waiting to run
Now that Ponyman is folded into main's instructions it is always in the
active system prompt, so the order-9 copy was duplicate text. Several of
its tags (minimal, lazy, shortest) do occur in ordinary development chat,
so _route_playbooks would periodically inject a second copy of guidance
already present verbatim.

Checked before removing: nothing in the codebase referenced the id or the
title. The only other "Ponyman" hit is .github/agents/ponytail-caveman.agent.md,
an unrelated Claude Code agent definition, not a playbook-store record.

Diffed the two texts first. One sentence existed only in the standalone -
"Lazy means efficient, never careless" - and is now on main's PONYMAN MODE
header. The other two gaps were phrasing: the standalone's "stay in this
mode until the user says normal mode" is covered by main's stronger version,
which relaxes only brevity and voice and keeps RULE 1 and RULE 2 in force.

This matches the reference setup, where Ponyman lives in main and no
standalone playbook exists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 20:06:05 -05:00
janvanwanandClaude Opus 5 a06366001b fix(playbooks): bring the shipped set up to date with v1.2.0
package / wheel (push) Waiting to run
The distributed playbooks had drifted well behind the code they run on:

- `main` and `NexusOS Developer` declared no `tools:` at all, so a fresh
  install advertised zero tool schemas to Ollama. The tool-calling loop,
  the per-playbook allowlist and the action-tool consent gate all shipped
  in v1.2.0 with nothing wired to use them. `main` now gets read_file,
  list_files and remember; `NexusOS Developer` gets the read/search set.
- `NexusOS Developer` still described the memory extractor as a separate
  FastAPI service on port 8001 backed by `synapse/memory/service.py`.
  That module is gone; curation runs in-process via curator.py/extractor.py.
  It also pointed at `synapse/playbooks/` for playbook data (that is the
  store code; the data lives in `data/playbooks/`), described a two-layer
  system prompt that is now six layers, and documented a model-selection
  heuristic that no longer exists.
- `Ponyman` had a stray third-person "he" left over from the owner scrub.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 19:50:12 -05:00
janvanwanandClaude Opus 5 5294ab7c78 feat(playbooks): Ponyman covers both the build method and the voice
Rewritten from a coding-rules-only playbook into the full mode: minimal
solutions AND compressed speech, triggered per conversation by tag.

Two rules lead the prompt because a small local model drops whatever is buried
in the middle. Rule 1: anything destructive gets a full-sentence warning BEFORE
the command, naming what is lost and what to back up - brevity never applies
there. Rule 2: an abstraction asked for with a single use gets a one-line
"not needed" and the small version instead. Rule 1 is repeated at the very end,
which is what made it hold in testing.

Tags carry the trigger words. A reference playbook is injected only when one of
its tag words appears in the message (_route_playbooks), so a playbook with no
matching tag never routes in at all.

Known limits, measured against llama3.1:8b: as a reference playbook only the
voice holds reliably. The build ladder and the warning-before-command ordering
need the playbook promoted to first position, because the chat endpoint appends
memory facts, conversation snippets and documents AFTER the reference block - a
reference playbook cannot own the end of the prompt, so a rule needing recency
weighting cannot get it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 17:45:47 -05:00
janvanwanandClaude Opus 5 8691a67803 fix(sync,memory,gpu): restorable memory dump, curator grounding, GPU + Models fixes
Ported from downstream development. Four independent defects.

1. The memory dump was unrestorable. iterdump() serializes sqlite_vec virtual
   tables as a raw INSERT INTO sqlite_master(...) followed by inserts into a
   table the replaying connection cannot see, so replaying memory.db.sql died
   on "no such table: vec_messages" and left ZERO tables behind. dump_db() now
   loads the vec0 extension and filters the derived vec tables out of the
   iterdump stream, matched on each statement's target table rather than as a
   substring - a chat message whose text mentions vec_messages is an
   INSERT INTO "messages" and has to survive.

   compare() reported an unreadable dump as "diverged", which read like a real
   verdict and made both guards refuse backup AND restore, locking the machine
   out of syncing in either direction. Unreadable is now its own verdict.

   _extra() compared updated_at against a "" default, but the column is REAL,
   so the comparison raises TypeError on the first conversation the other side
   lacks - exactly the case it counts. It tests membership first now. The
   direction test declared updated_at TEXT, which is why this survived: the
   test compared str to str while the field compared str to float.

2. The memory curator invented facts. It attributed the ASSISTANT's words to
   the user, wrote absence claims read off the existing-memory block, and added
   judgements ("favorite") the user never used. The prompt now scopes the USER
   line as the only source, and two deterministic guards drop absence claims
   and facts whose distinctive tokens appear nowhere in the user's message -
   prompt wording alone did not hold on a 7B curator.

3. _best_vulkan_device scored Mesa's llvmpipe above an integrated GPU, pinning
   Ollama to a software rasterizer advertising 31 GiB of "VRAM" - CPU inference
   with Vulkan overhead on top. Software rasterizers are dropped.

4. Models.jsx compared catalog names to installed names literally, but Ollama
   resolves a bare name to ":latest", so an untagged entry (nomic-embed-text)
   read as missing forever and the Required gate never opened. Chatbot.jsx
   fetched the model list once on mount although App keeps the page mounted
   behind display:none, so a newly pulled model never appeared in the picker
   until a full browser reload.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 17:33:43 -05:00