Commit Graph
11 Commits
Author SHA1 Message Date
Nirav PatelandClaude Fable 5 2952b0c289 fix(intake): resolve the hermes CLI per call, prefer the release shim
The shared checkout's venv is deleted and recreated by release cutovers; a
cutover mid-run left every intake tick failing ENOENT on
<checkout>/venv/bin/python. ~/.local/bin/hermes is repointed by the release
recipe itself, so resolve it fresh on each call and keep the checkout venv as
a fallback.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-22 22:33:38 -04:00
Nirav PatelandClaude Fable 5 eb0033b952 migrate write+read path from mib007 comms to the unified message envelope
Pulse's Activity UI (verified live on :5520, Vite dev serving the checkout
at 7293d857) now reads AND writes /api/workspaces/:ws/messages, so the
bridge follows:

- writes: POST /messages with server-side idempotencyKey (ledger:<id> for
  roots, (id,op,at) for feed comments, pulse-* keys for intake replies);
  replay returns the ORIGINAL message, so the v0 find-existing recovery
  scan and drop-on-500 comment policy are gone (5xx now retries safely,
  only 400/404/410 drop)
- reads: intake ingests envelope roots (kind=post), normalized to the old
  comms row shape at the boundary; comms GET would miss envelope-native
  user posts entirely
- state carries over unchanged: backfill 0103 + mirror trigger 0104
  preserve comms ids, so the ledger→post map and channel id stay valid and
  old threads accept replies (verified via /messages/threads/<old-id>)
- self-recognition: envelope posts carry no userName override, so intake
  now skips the service actor id (00000000-…-0001) structurally
- codex P2 fixed: adopt unmapped v0-era posts (no idempotency key) by
  ledger:<id> body scan before creating, so an old insert-then-error
  survivor cannot be duplicated

Known cosmetic tradeoff (documented in README): no byline override on the
envelope route — new posts render under the service actor, not "Ledger".

E2E on the live feed: post 715f52ec, stage comment 74d19219, needs-you
@rapidnir comment 2f898b75 + comment.mention notification row for
rapidnir-admin, close comment 9f0a5097; timed-out create retried into the
same row (idempotency proven, count=1).

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YECpkAwQUwgu7NVy91R8fW
2026-08-22 22:21:34 -04:00
Nirav PatelandClaude Fable 5 5896d6cab1 intake: configurable chat-only opt-out prefixes (💬, chat:)
Posts starting with an opt-out prefix (PULSE_BRIDGE_INTAKE_OPTOUT,
case-insensitive) are never turned into a ledger item or kanban task and
get no bridge reply. Codex review: no findings.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YECpkAwQUwgu7NVy91R8fW
2026-08-22 16:12:35 -04:00
Nirav PatelandClaude Fable 5 aaedf758d9 suppress outbound mirror comments for intake-managed items (double-comment fix)
intake_track() already narrates status on the user's post; mirroring the
same item's ledger update/close ops added near-duplicate comments (seen in
the E2E smoke: 'stage → build' next to '▶️ running').

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YECpkAwQUwgu7NVy91R8fW
2026-08-22 15:06:19 -04:00
Nirav PatelandClaude Fable 5 2bc7d510c1 intake: assign kanban tasks to the default profile so the dispatcher claims them
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YECpkAwQUwgu7NVy91R8fW
2026-08-22 15:04:10 -04:00
Nirav PatelandClaude Fable 5 208cee9830 README: document accepted intake caveats
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YECpkAwQUwgu7NVy91R8fW
2026-08-22 15:03:45 -04:00
Nirav PatelandClaude Fable 5 827b816eeb intake review fixes: idempotent ledger add, inclusive ms checkpoint, FIFO promotion
- ledger_add_for_post adopts an existing open item carrying post:<id>
  before adding (crash between add and state save no longer duplicates)
- intake window is now inclusive (ts >= cp, init cp = newest+1) with the
  post-id map as the dedupe, so same-millisecond posts can't be lost to a
  crash between them
- newcomers can't jump the queued backlog: loop order is track -> promote
  -> ingest, and ingest queues when a backlog exists even if a slot is free
- documented the kanban --idempotency-key crash-recovery contract

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YECpkAwQUwgu7NVy91R8fW
2026-08-22 15:03:19 -04:00
Nirav PatelandClaude Fable 5 54b705b073 v1 intake: Pulse posts become ledger items + dispatched kanban tasks
- new top-level non-bridge posts in the activity channel -> shre-items
  pipeline item (tag pulse-intake) + hermes kanban task (idempotency-key
  pulse-<post id>, created-by pulse-bridge) + ack comment
- outbound dedupe: ledger->post map seeded with the user's post id before
  the op:add hits the feed, so the mirror adopts the post
- status tracking via one 'kanban list --json' per poll: running/blocked/
  done comments on the post, ledger stage build -> done
- cap 3 concurrent intake tasks; overflow queued with a comment and
  promoted when slots free; intake state in the same atomic state.json
- first intake run only sets the checkpoint (no history ingestion)

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YECpkAwQUwgu7NVy91R8fW
2026-08-22 15:00:35 -04:00
Nirav PatelandClaude Fable 5 e005931cb5 codex review fixes: duplicate-post recovery, fsync, fatal corrupt state, narrower comment drop
- create_post: on HTTPError, look for an existing post tagged ledger:<id>
  (insert-then-error recovery) and adopt it before retrying
- save_state: fsync tmp file before rename
- load_state: corrupt state is fatal (auto-reseed would duplicate every
  open item's post)
- comment: drop only on 500/404/410; 401/403/429/502/503 retry next poll

Accepted as-is (with rationale): same-second ordering relies on the feed
replaying the JSONL in append order + Python's stable sort; seed-window
add+close races reduce to the documented 'predates bridge' skip.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YECpkAwQUwgu7NVy91R8fW
2026-08-22 14:47:34 -04:00
Nirav PatelandClaude Fable 5 1a3ab878b4 harden against mib007 mention-path 500 (insert-then-error)
Smoke test found: any @handle in a comms message 500s AFTER the row is
inserted (agents.url_key column missing on this instance), so a retry
duplicates the message. Neutralise ALL '@' the bridge emits (incl. its
own @nir escalation, zwsp renders identically) and make comment HTTP
errors non-retryable best-effort drops; posts still retry.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YECpkAwQUwgu7NVy91R8fW
2026-08-22 14:45:19 -04:00
Nirav PatelandClaude Fable 5 9a862bee2b pulse-bridge v0: mirror shre-items ledger into Pulse (mib007 comms) posts
- daemon polls shre-items feed every 30s with inclusive-window (id,op,at) dedupe
- op:add -> post in 'activity' channel; op:update -> threaded comment
  (stage/kind/attempt/note, needs-you escalation mentions @nir);
  op:close -> done/dropped comment
- first run seeds currently-open items only
- state (checkpoint + ledger->post map) atomic at ~/.shre/pulse-bridge/state.json
- launchd ai.shre.pulse-bridge (KeepAlive, logs to bridge.log)
- '@' in ledger-derived text neutralised (zwsp) so comms agent-mention
  regex can never fire an AI reply from item content

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YECpkAwQUwgu7NVy91R8fW
2026-08-22 14:41:31 -04:00