Skip to content

feat(core): mine durable decisions from agent session transcripts#775

Merged
RaghavChamadiya merged 3 commits into
mainfrom
feat/session-decisions
Jul 11, 2026
Merged

feat(core): mine durable decisions from agent session transcripts#775
RaghavChamadiya merged 3 commits into
mainfrom
feat/session-decisions

Conversation

@RaghavChamadiya

@RaghavChamadiya RaghavChamadiya commented Jul 11, 2026

Copy link
Copy Markdown
Member

What

repowise init and repowise update now mine coding-agent session transcripts for durable decisions and promote them into the decision layer. A repo indexed for the first time on a machine with existing session history gets them from day zero. A user correcting the agent, a choice made for a stated reason, or a failed approach replaced by a working one no longer evaporates when the session ends.

How

  1. Deterministic gates first (core/sessions/miners/decisions.py, pure pass over the shared Event stream, no LLM):
    • user corrections: interrupts with guidance, pushback-leading messages;
    • explicit choices: a sentence pairing a decision verb with a causal cue near file-touching tool activity;
    • dead ends: repeated failures of one command/target followed by a pivot to a different one.
      Each candidate carries verbatim transcript quotes plus the files in play.
  2. One batched LLM structuring pass per update over pending candidates (same provider as indexing). Every produced field is grounded against the verbatim quotes: source_quote must verify exact/fuzzy, the decision text is held to a content-word overlap, and an ungrounded rationale is dropped rather than invented.
  3. Staging sidecar .repowise/sessions/sessions.db (WAL, same pattern as the omissions store): raw candidate queue, observation counts per distinct session, and DB-backed transcript cursors that only advance in the same commit that stages what was read under them. A failed LLM call leaves candidates staged for the next update; only appended transcript lines are ever re-read.
  4. Promotion: observed in 2+ distinct sessions, or a single observation for a direct user correction, upserts through the existing bulk_upsert_decisions path as active with source: session (rank 7, below cli/adr, above commit archaeology). Re-observations add proposed evidence rows and can never overwrite a status a human set; dismissals stay sticky. Everything downstream (get_why, evidence, node links, CLAUDE.md standing decisions) comes for free.

Config and privacy

decisions.session_mining: true by default; false turns the whole pipeline off (documented in CONFIG.md). Transcripts never leave the machine; only distilled decision text about the codebase is stored, with the verbatim quote as evidence.

Validation

  • 24 new unit tests (gates, grounding, staging store, cursors, end-to-end with a fake provider); full unit suite green (6978 passed).
  • Dogfooded on this repo's full 342-transcript history: 250 candidates staged, 184 rejected by the gates, 64 staged decisions, 10 promoted, and the promoted set is dominated by genuinely durable rules (writing-style bans, branch-naming rules, an MCP response-shape decision observed independently in two sessions).

Sessions are the highest-grade decision source a repo has: a user
correcting the agent, a choice made for a stated reason, a failed approach
replaced by a working one. Today that evaporates when the session ends.
This adds session mining on top of the shared core/sessions layer:

- core/sessions/miners/decisions.py: deterministic candidate gates over the
  Event stream (user corrections via interrupts/pushback, explicit choices
  pairing a decision verb with a causal cue near file activity, dead ends
  of repeated failures followed by a pivot), then one batched LLM
  structuring pass per update over pending candidates.
- core/sessions/staging.py: .repowise/sessions/sessions.db WAL sidecar
  (OmissionStore pattern) holding the raw candidate queue, observation
  counts per distinct session, and DB-backed transcript cursors that only
  advance in the same commit that stages what was read under them. A failed
  LLM call leaves candidates staged for the next update.
- Grounding: source_quote must verify verbatim against the transcript
  excerpt; the decision text is held to a punctuation-stripped content-word
  overlap; an ungrounded rationale is dropped rather than invented.
- Promotion: 2+ distinct sessions, or one observation for a user
  correction, upserts through the existing bulk_upsert_decisions path as
  active with source "session" (rank 7). Re-observations emit proposed
  evidence and never overwrite a human-set status. Dismissals stay sticky.
- Config gate decisions.session_mining (default on), documented in
  CONFIG.md. Everything stays local.

Dogfood over this repo's full 342-transcript history: 250 candidates
staged, 184 rejected by the LLM and grounding gates, 64 staged decisions,
10 promoted.
@repowise-bot

repowise-bot Bot commented Jul 11, 2026

Copy link
Copy Markdown

✅ Health: 7.6 (unchanged)

📋 At a glance
1 file changed health · 3 hotspots touched · 14 new findings introduced · 5 co-change pairs left out · 3 files with recent fix history. Scoped to packages.

🚨 Change risk: high (riskier than 89% of this repo's commits · raw 9.7/10)
This change's risk is driven by:

  • more lines added than baseline
  • more scattered than baseline

🩹 Review priority (files here with the most recent bug-fix history — defects cluster, so review these first)

File Score Δ Why
.../phases/analysis.py 3.6 → 2.6 ▼ -0.9 🔻 introduced nested complexity, complex method, large method · ✅ resolved function hotspot, error handling

💡 .../phases/analysis.py: Flatten the control flow. Pull early-return guards to the top, extract the deepest branch into a helper, and consider replacing nested conditionals with a strategy table or dispatch dict.

🔎 More signals (2)

🔥 Hotspots touched (3)

  • .../update_cmd/command.py — 12 commits/90d, 3 dependents · primary owner: Raghav Chamadiya (90%)
  • .../decisions/provenance.py — 4 commits/90d, 5 dependents · primary owner: Swati Ahuja (98%)
  • .../phases/analysis.py — 7 commits/90d, 3 dependents · primary owner: Swati Ahuja (64%)

🔗 Hidden coupling (1 file)

  • .../update_cmd/command.py co-changes with these files (not in this PR):
    • .../update_cmd/persistence.py (6× — 🟢 routine)
    • docs/CLI_REFERENCE.md (4× — 🟢 routine)
    • .../cli/helpers.py (4× — 🟢 routine)
    • .../workspace/update.py (3× — 🟢 routine)
    • .../update_cmd/reporting.py (3× — 🟢 routine)

📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-07-11 07:31 UTC
Silence on a single PR with [skip repowise] in the title · Per-repo toggle on repowise.dev/settings?tab=bot

A repo indexed for the first time on a machine that already has agent
session history gets its session-sourced decisions from day zero: the
full-index decision phase now runs the transcript miner after extract_all
(appended past the substring gate on purpose, since the miner enforces its
own grounding contract) under the same decisions.session_mining config
gate. Server-side indexing has no transcript directory and no-ops. The
cold-start cap still bounds the LLM pass; the backlog drains over later
updates.
@RaghavChamadiya

Copy link
Copy Markdown
Member Author

Went through the bot's coupling flags one by one:

  • update_cmd/persistence.py: intentionally untouched. Session decisions merge into the existing decision list at the call site in command.py, so the persist path (bulk upsert, supersession, staleness) runs unchanged.
  • docs/CLI_REFERENCE.md: real catch. The update section documented every other side effect but not session mining; added in 35b181d.
  • cli/helpers.py: only consumed (resolve_provider), nothing to change.
  • workspace/update.py: workspace refreshes mirror update --index-only and never resolve a provider, so mining deliberately does not run there. Per-repo docs-mode updates and init cover it.
  • update_cmd/reporting.py: the completion panel picks up promoted session decisions through the existing decisions_changed count; the verbose report stays marker-only, which is accurate since promotions are also listed separately when verbose.

On the risk callouts: the two hotspots got additive, pattern-matching changes (the mining block mirrors the adjacent decision re-scan block, incl. the degraded-step contract), and the new-findings count is concentrated in the new miner module, where the gate loop is one function by design. Full suite green at 6978 passed.

@RaghavChamadiya RaghavChamadiya merged commit bed0cbd into main Jul 11, 2026
7 checks passed
@RaghavChamadiya RaghavChamadiya deleted the feat/session-decisions branch July 11, 2026 07:34
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.

2 participants