daybook/planning/daybook-issues-log.md

7.9 KiB

Daybook — Issues Found During LLM-Posting Testing

Date: 2026-06-10 Context: Found while smoke-testing the deployed instance (192.168.1.36:8000) and hardening the daybook-posting skill's daybook_post.py helper. Auth/ reachability items are tracked separately in planning/next_steps/llm-posting-skill-plan.md and not duplicated here.

Severity key: High = blocks a stated feature · Med = degrades UX or correctness · Low = cosmetic. Status: Open / Fixed / By design.


Open — Server-Side

S1 · Multipart metadata field is not parsed as a JSON object — High / Open

  • Symptom: Any file upload (multipart) that includes a metadata field returns HTTP 400 {"detail":"metadata must be an object"}.
  • Repro: python daybook_post.py test.svg --meta run_id=1 (or any --file + --meta). Text artifacts (JSON path) are unaffected — they send a real object.
  • Root cause: The multipart handler reads metadata as a raw form string and type-checks it against dict without json.loads. A stringified {} or {"k":"v"} therefore fails the check.
  • Impact: Machine-readable metadata (run_id, model, etc.) cannot be attached to image/pdf/binary artifacts — only to text artifacts.
  • Fix: In the multipart code path, json.loads the metadata form field before validating, mirroring the JSON path. Confirm tags is handled consistently (currently sent as a comma string and split server-side).
  • Client workaround in place: the helper now omits metadata from multipart when empty, so metadata-less uploads work. Non-empty metadata on uploads still needs this server fix.

S2 · Users cannot delete or archive artifacts (artifacts are immutable) — High / Open

  • Requirement: Users need to be able to archive and delete artifacts — both as API endpoints and as controls in the web UI.
  • Symptom: There is no delete endpoint, and content/kind/persona/day are not editable. The malformed test deck 5df27410 and the session's test artifacts can only be superseded, never removed or hidden.
  • Impact: Test and mistake artifacts accumulate permanently in the feed with no way for a user to clean it up.
  • Fix — two distinct actions:
    • Archive: user-initiated, hides the artifact from the default feed but retains it and allows restore. Needs an archive/unarchive endpoint, a default feed filter that excludes archived items, and a UI control (plus an "archived" view).
    • Delete: user-initiated permanent removal (or a soft-delete tombstone). Needs a DELETE endpoint, a UI control with a confirm step, and removal of the stored content/raw file.
  • Related: consider allowing content replacement for an existing id (revision), which would also address re-posting a corrected artifact.

S3 · No renderer for CSV / JSON / code — Med / Open

  • Symptom: These upload as download-only binary (e.g. test.csv → c562128b, kind binary).
  • Impact: Tabular/code artifacts aren't viewable inline.
  • Fix: Add a renderer, or formally bless the client's --as-markdown fenced- block convention as the interim path and document it.

S4 · Favorites and project/group labels — Med / Open

  • Requirement: Users want to (a) mark artifacts as favorites, and (b) label artifacts as belonging to a group / project. The group/project label must be settable at upload time (and editable afterward). Favorite is primarily a UI toggle but should also be settable at upload.
  • Design notes:
    • Keep this distinct from tags. Tags are many free-form filter labels; a project/group is a first-class, usually single container used for navigation and grouping. Recommend a dedicated project (or group) field rather than overloading tags. favorite is a boolean, not a tag.
    • Data model: add favorite: bool = false and project: str | null to the artifact record.
  • Scope — server / client / UI:
    • Server: accept favorite and project on POST; add endpoints to toggle favorite and set/clear project after upload; support ?project= and ?favorite=true feed filters.
    • Client (daybook_post.py): add --project NAME and --favorite flags, sent as first-class JSON/form fields — NOT inside metadata (see S1, which breaks for multipart string fields).
    • UI: a favorite (star) toggle and a favorites view; group/filter the feed by project.

Open — Web UI

U1 · Feed does not refresh when new artifacts arrive — Med / Open

  • Symptom: The web UI renders a static snapshot of the feed. Artifacts posted after the page loads do not appear until the user manually reloads.
  • Impact: Agents publish continuously, but a human watching the feed silently misses new arrivals — which undercuts Daybook's purpose as a live journal of agent output. Observed throughout this session: each test post required a manual browser refresh to show up.
  • Fix options (simplest first):
    • Client-side polling of the list endpoint on an interval (e.g. every few seconds), diffing against the loaded set.
    • Server-sent events (SSE) for push updates — a natural fit for this publish-only, append-mostly model and lighter than WebSockets.
    • To avoid disrupting scroll position, surface a "N new artifacts — click to load" indicator rather than auto-injecting items at the top.

By Design — Worth a Decision

D1 · Strict rendering, no normalization — By design

  • Behavior: "Daybook does not fix malformed content." Wrong-shaped content is stored and rendered as-is.
  • Observed consequence: Markdown sent to deck (5df27410) was stored and rendered malformed — no error, just broken output.
  • Implication: A validating client is load-bearing. The server's per-kind structure rules and the client's pre-flight checks must stay in sync; if the server adds a kind, the client's validation/sniffing must follow.
  • Optional improvement: Consider rejecting obviously-malformed content with a 422 (e.g. deck with no <section>) so it fails loud at post time rather than rendering broken later. This complements, not replaces, the client guard.

Fixed — Client (recorded for traceability)

C1 · Empty metadata broke all multipart uploads — Fixed

  • The helper serialized empty metadata as the string "{}" into the multipart body, triggering S1's 400 even when no metadata was supplied.
  • Fix: omit empty optional fields (metadata, tags, source_id, source_prompt) from the multipart body, restoring the minimal known-good shape.

C2 · html_full client validation was over-strict — Fixed

  • Originally required BOTH <!doctype AND <html>; an auto-sniffed full page lacking an explicit doctype was rejected.
  • Fix: require <html> only (doctype recommended, not mandatory).

Minor / Cosmetic

M1 · deck title inference picks the first slide heading — Low / Open

  • Auto mode derived the title "Slide One" from a deck's first <h1> (ac6da43f). Correct but awkward as a title.
  • Fix: for deck, prefer the filename over the first <h1>.

M2 · CSV content-type guessed as application/vnd.ms-excel on Windows — Low / Open

  • Python's mimetypes maps .csv to application/vnd.ms-excel on this host rather than text/csv. Harmless — the server still stores it as binary — but inconsistent with the earlier manual text/csv upload.
  • Fix (optional): force text/csv for .csv in the client's content_type_for.

Test Artifacts Created (for cleanup once S2 lands)

Auto-mode validation posts under persona claude, tag auto-test: e7a769c5 (markdown), 2d162697 (html_full), 49291e85 (html_fragment), ac6da43f (deck), 3ad914cc (image), 794d29e8 (pdf), c562128b (binary). Plus earlier manual smoke-test artifacts and the malformed deck 5df27410.