HQ Mechanics + Audit Bundle Feature

Consolidated design report · id 44 / operator-mavis · 2026-09-17 14:22 BST · session 418281651208440

State

Shipped Direction 1 locked (FreshCards UI → HQ).

Shipped Home page = Task Bundle cards (replaces Overview).

Precoded Build plan: A demo today · B 1.5d persistent · C 2h auto-trigger · D 2h weekly digest.

Action Awaiting operator sign-off on bundle shape + version-check mechanism + FreshCards extraction scope.

id 44 / operator-mavis | session 418281651208440 | 2026-09-17 14:22 BST

This is the consolidated record of the design conversation on 2026-09-17 between operator G and id 44. It covers:


§1 — How HQ Works (background)

What HQ is

A coordination panel at panel.freshvibeapps.com/mavis. Every Mavis agent registers on first connect and gets back a token saved to ~/.mavis/hq_token. From then on, every action uses the header X-Mavis-Token: .

What gets captured in HQ

| Endpoint | Captures | |---|---| | `POST /api/mavis/heartbeat` | Alive ping, updates `hq_threads.last_heartbeat_at`. No payload worth reading. | | `POST /api/mavis/bulletin` | Event reports — agent's curated milestones. **2000 char HARD LIMIT** on JSON body. Levels: info / error / success / warn. | | `POST /api/mavis/report` | End-of-turn structured summaries. **No size limit.** | | `POST /api/mavis/prompt` | The prompt the operator sent. Captured automatically as its own row in `hq_prompts`. | | `POST /api/mavis/artifacts` | Files (plans, docs, mockups, reports). Required 20-500 char description. | | `POST /api/mavis/plan/...` | Multi-step task plans with checkboxes, verifications, ownership. |

What does NOT get captured

Real bulletin shapes from the recent stream

Short (status ping):

b003543 — Mavis brief: 50 bulletins in last 10min, 0 tasks queued

Long (shipped fix, full sections):

b003542 — [id8] | G12 | 2026-09-17 00:35 Europe/Paris Root cause (one sentence) Files changed (commit, line count) tsc + vite build results Commit hash + push status Cron deploy result

Gotchas


§2 — The Connection Mechanism (how prompts link to activity)

Two ways prompts connect to bulletins

By thread (loose grouping). Every bulletin and every prompt has a thread_id. Same thread = same Mavis. All of id9's bulletins share thread_id=9; all of the operator's prompts to id9 share thread_id=9. They cluster naturally in the SPA per-thread view: prompts at top, then bulletins in chronological order.

By plan (tight grouping). For multi-step work, the agent creates a plan first (uploaded to HQ as type=plan artifact). Every bulletin posted during that work includes ref_plan: aNNN in the body. That creates a queryable trail: "all bulletins for plan a437".

API + SPA access

GET /api/mavis/bulletins?ref_plan=a437 # filter to one plan's activity GET /api/mavis/prompts?thread_id=44 # all prompts operator sent to id 44 GET /api/mavis/bulletins?thread_id=N&limit=20&since=<ts>

SPA surfaces:

  • `panel.freshvibeapps.com/mavis/thread/` — heartbeats + bulletins + reports + prompts + repos for one Mavis
  • `panel.freshvibeapps.com/mavis/plans/` — plan detail with checklist + targeting + activity
  • Explicit vs implicit links

    Explicit (hard link via id field):

    Implicit (loose link via thread_id + time):


    §3 — The Audit Bundle Feature

    Why (operator-locked, 2026-09-17)

    Operator wants one view per task that bundles prompt + activity + summary, audit-style. Currently the operator has to stitch together 5 tabs (Timeline, Thread, Plans, Artifacts, Reports) in their head to know "what was id9 actually doing yesterday?". This feature collapses that into one page per task.

    Shape (audit-style, sections per concern)

    === TASK: aNNN — title === 1. PROMPT — text operator sent (captured as hq_prompts row) 2. CONTEXT — who triggered, state at the time (RULES version, branch, repo) 3. ACTIONS — chronological list of every HQ event (bulletins + reports + heartbeats) 4. ARTIFACTS — files uploaded with descriptions 5. CHAT REPLY — agent's full response to the prompt (posted as report) 6. VERIFICATION — did it ship? push status, build status, deploy status 7. CONNECTIONS — parent plan, child plans, blocks/blocked-by, follows
    
    

    Not chronological dump — sections per concern. Same shape as an accountant's audit.

    What it does for the operator


    §4 — Where It Lives (operator-locked, 2026-09-17 11:22 BST)

    Home page = Task Bundle cards

    Direction decided: Task Bundles become the home page. Each card = one piece of work. The current Overview (thread-centric) moves to a "Mavis" or "Agents" tab.

    Home page shape

    Where liveness goes

    "is id9 alive right now?" stays visible — small chip on each task card ("@id9, last seen 5 min ago"). The Overview tab keeps thread cards too, just not as the default.

    Why Direction 1 not 2 or 3


    §5 — Build Approach (Direction 1)

    Lift, don't reinvent

    Reuse FreshCards' primitives:

    One thing to figure out: data source

    Three options:

    | Option | What | Effort | |---|---|---| | **A. Read both** | FreshCards server queries PB + panel.db, joins in server | ~half day | | **B. Mirror** | Small cron syncs audit data from panel.db → PB nightly | ~half day | | **C. Lift UI only** | Lift FreshCards components into HQ, render against panel.db only | ~half day |

    My take: A or C (similar effort). B is cleaner long-term but has sync lag.


    §6 — Research Findings

    FreshCards (id 11) architecture

    Gallery (id 8) relationship

    Vibecoder (id 9) vendor pattern


    §7 — Module / Versioning / Dynamic-Update Pattern (operator validation)

    What's right

    What's slightly off

    1. FreshCards repo publishes new version (v1 → v2)

    2. HQ's package.json gets updated to point at v2

    3. HQ rebuilds + redeploys

    4. Now HQ has the new FreshCards code

    What's missing from the mental model

    a) FreshCards isn't a module YET. It's a standalone React app. To make HQ import it, we'd first extract the reusable bits into a separate package. One-time refactor.

    b) Closest existing example: Gallery already imports FreshCards as file:../freshcards. Pattern works, but only between sibling repos.

    c) Version-check mechanism — four options:

    d) Compatibility contract — when FreshCards goes v1 → v2, if v2 is breaking, HQ's existing usage might break. Semver discipline matters.

    What's wrong

    Nothing. Just incomplete on the "how" of dynamic updates + extraction step.


    §8 — Build Plan

    | Phase | What | Effort | |---|---|---| | **A** | One-off collation today (demo bundle on a recent task, markdown output) | ~10 min | | **B** | Persistent feature (DB tables + endpoint + SPA route + new home page) | ~1-1.5 days | | **C** | Auto-trigger (after every report, post pointer bulletin to bundle URL) | ~2 hours | | **D** | Weekly digest (Sunday-night cron, one bulletin with week's audit links) | ~2 hours |

    Cumulative: A alone = today, A+B = 1.5 days, A+B+C = 2 days, A+B+C+D = 2.5 days.

    Recommended order: A first (low risk, validates shape), B next (the persistent home), C/D only after A confirms shape and we know what we want automated.


    §9 — Decisions Pending + Open Questions

    Decisions pending

    Open questions


    Sandbox State

    - /workspace/.plan/418281651208440-hq-mechanics-and-audit-bundle-consolidated-2026-09-17.md (this document)

    - Local backup at /workspace/.plan/418281651208440-audit-bundle-design.md (the original design doc)

    - b003675 (bulletin on operator-mavis thread pointing to artifact a1133 — the earlier design-only artifact)


    [id44] | end PROMPT — HQ mechanics + audit bundle feature consolidated report