Skip to content

Keep drafts and fixes watched; stale drafts and Re-analyze - #32

Merged
iamwhatever merged 1 commit into
mainfrom
feat/stale-drafts-reanalyze
Oct 1, 2026
Merged

iamwhatever merged 1 commit into
mainfrom
feat/stale-drafts-reanalyze

Conversation

@iamwhatever

Copy link
Copy Markdown
Owner

Summary

Two owner complaints, both verified on the live ledger: dispatched fixes stop getting thread re-checks once resolved or older than 7 days (3 of 15 dispatched items were 18–22 h stale), and 30 of 63 unsent drafts are older than the thread's newest reply, with nothing on the Board saying so.

  • Re-check window. An item is pinned while it has an unsent reply_draft, a dispatched fix whose session is not closed (fix_handoff.dispatch.state, stored by dispatch.record_states on every poll and /needs read), or status == investigating. Pinned items are re-checked whatever their status and recheck_days, go first within recheck_max_per_cycle, and keep their replies.
  • Stale drafts. reply_draft.stale = {since, new_replies} is set by the re-check, judged once at load for existing drafts, and starts null on every rewrite; a send clears the draft. slack_radar_record refuses it.
  • Board. Row chip N new replies since draft; in the detail view newer replies are marked new and a warning sits above Send to thread (still one click); stale rows sort first within a priority; dispatched fixes show replies · last HH:MM.
  • Re-analyze. Re-analyze N stale in the Needs-you header (and Re-analyze this in the detail view) posts POST /items/reanalyze (≤20 keys, owner only). The app hands the Lead ONE prompt on its own slot (owner-message path), stamps reanalyze_requested_at, records a crew event, and refuses with 409 while a request is in flight (until each item moves or 10 min). No poll or timer sends it; the Lead never posts. Brief v8 has a matching section and tells the Lead to leave drafts alone on ordinary thread updates.
  • Docs: README (both halves), CHARTER, CONTRACT, crew brief; app 0.9.6.

Tested

  • python -m pytest tests -q -p no:cacheprovider: 329 passed (new tests/test_stale_drafts.py: pinned re-check past the horizon and while resolved, unpinned resolved skipped, closed dispatch unpins, pinned-first ordering, replies kept, stale set/cleared/migrated, record tool refuses app-only fields, /needs stale fields and sort, /items/reanalyze one prompt with ≤20 keys, 409 in flight, owner gate, paused crew undoes stamps).
  • npm run build clean; ui/dist/index.mjs regenerated.
  • Screenshot harness: all DOM checks pass, including the new ones (row chip text, detail warning and new markers, Send posts once, Re-analyze 2 stale posts /items/reanalyze once with 2 keys and then reads Re-analyzing…). PNGs regenerated.
  • Read-only probe of the live ledger shape: after load, 30 drafts read stale and 15 open items count toward Re-analyze.

Needs you
Reply detail

The thread re-check covers pinned items whatever their status and age: an
unsent reply draft, a dispatched fix whose session is not closed, or an
investigation. Pinned items go first within recheck_max_per_cycle and keep
their replies. The dispatched session's observed state is stored on
fix_handoff.dispatch.state so the poller can tell.

reply_draft.stale ({since, new_replies}) is set by the re-check when replies
arrive after the draft, judged once at load for existing drafts, and starts
null on every rewrite. The record tool refuses it.

The Board shows "N new replies since draft" on the row, marks newer replies
"new" in the detail view with a warning above Send to thread, sorts stale rows
first within a priority, and shows "replies · last HH:MM" on dispatched fixes.

Re-analyze N stale (and Re-analyze this) is the only way a draft changes after
the Lead's first look: POST /items/reanalyze hands the Lead ONE prompt for up
to 20 items, stamps reanalyze_requested_at, records a crew event, and is
refused while a request is in flight. No poll or timer sends it.

Brief v8, README (both halves), CHARTER, CONTRACT; app 0.9.6.
@iamwhatever
iamwhatever merged commit eb9549f into main Oct 1, 2026
2 checks passed
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.

1 participant