Skip to content

Resume: pickup-from-Next-Steps fix + capture tasks with context#224

Merged
khustup2 merged 6 commits into
mainfrom
feat/resume-next-steps
Jun 1, 2026
Merged

Resume: pickup-from-Next-Steps fix + capture tasks with context#224
khustup2 merged 6 commits into
mainfrom
feat/resume-next-steps

Conversation

@khustup2
Copy link
Copy Markdown
Contributor

@khustup2 khustup2 commented May 31, 2026

Resume "pick up where you left off" — now actually fires

Two related pieces so a new session reliably resumes prior work.

1. Resume-brief: stop the pickup from being starved (bug fix)

pickResumeBrief was correct but starved. The memory table carries a
SessionStart placeholder row per session (a skeleton with no ## section
until the wiki worker fills it at SessionEnd), plus duplicate rows per session.
Those filled the LIMIT 5 window, so the walk-back never reached real
summaries and every session looked "wrapped up clean."

  • over-fetch (SCAN_LIMIT=40), dedup by session path, drop
    placeholders
    , then walk LOOKBACK real summaries
  • when only placeholders exist → return null (plain welcome) instead of
    falsely claiming "wrapped clean"
  • pulled the windowing into pure isPlaceholderSummary + selectRealSummaries
    so it's unit-tested without the network

Verified against real data — now surfaces:

Picking up on hivemind (5 days ago) — you left off here:
📌 Pending: CI re-run against commit f89e70e on fix/skip-missing-table-reads branch…

2. ## Next Steps parity across agents

claude-code already emitted a dedicated ## Next Steps; added it to the
codex / cursor / hermes wiki-worker prompts too. resume-brief prefers it and
falls back to ## Open Questions / TODO for older summaries.

Capture a task with context, resume it later (new feature)

Explicit, in-session Save↔Resume pair on the existing goals primitive — no
Stop-hook / gate / detached worker (the auto-detection design is deferred; see
docs/CAPTURE_TASKS.md for the decision record).

  • Save"save this for later" writes a goal whose body is a resumable
    context package: label + Start here / Files / Branch / Run / Why, filled
    from the live conversation.
  • Resume"let's work on that task" finds the goal, pulls the full
    body back, flips it to in_progress, and continues from Start here: — no
    re-explaining.
  • CLI: goal add --agent capture (provenance, allowlisted) and
    goal get <goal_id> (full-body read — goal list only showed the first
    line, so resume had no way to transfer the package back).
  • capture/resume operations added to all four agent skill copies
    (claude-code / codex / hermes / openclaw).

Tests

  • resume-brief.test.ts: placeholder detection, dedup, placeholder-shadowing,
    lookback cap, all-placeholders→null.
  • cli-goal.test.ts: --agent capture vs default, agent allowlist guard,
    multi-line body preservation, full-body goal get.
  • Full suite green (3658 tests).

The resume brief now surfaces what to DO next, not a backward recap.

- Summarizer (spawn-wiki-worker): add a `## Next Steps` section — one
  imperative line to resume with, or literal "none" on a clean stop.
- resume-brief: walk the last 5 summaries for the project newest-first and
  resolve to one of three outcomes:
    1. most recent session with open work → "you left off here: <next step>"
       + a pick-it-up CTA. Pointer comes from `## Next Steps`, falling back
       to the older `## Open Questions / TODO` so existing summaries work
       tonight (before any new-format summary accumulates).
    2. summaries exist but every recent session wrapped clean → a brief with
       NO call to action ("wrapped up clean, nothing pending") — we don't
       invent an action.
    3. no summaries for the project → null; caller renders plain welcome.
  Empty / "none" / "n/a" sections count as wrapped-clean.

Still userVisibleOnly (caller renders to systemMessage only). Replaces the
first-"What Happened"-sentence pointer with the new extractNextSteps; tests
updated.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 31, 2026

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e20a4574-5a73-4e61-abbb-df4433e5c1f0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR introduces a "Next Steps" tracking mechanism for session summaries. The wiki worker prompt now instructs output of a ## Next Steps section. Resume-brief generation refactors to extract and prioritize this section, scans multiple recent summaries instead of just the most recent, and returns differentiated outcomes: open-work briefs with call-to-action, wrapped-clean status, or null.

Changes

Resume-brief next-steps extraction

Layer / File(s) Summary
Wiki worker next-steps prompt
src/hooks/spawn-wiki-worker.ts
Wiki prompt template gains "Next Steps" section instructing worker to emit one imperative action or none when nothing is pending.
Resume-brief extraction helper and constants
src/notifications/sources/resume-brief.ts
Module documentation updated to reflect new resolution model. New LOOKBACK constant governs scanning window for multiple summaries. extractNextSteps() helper parses summary sections, prefers ## Next Steps over fallback sections, strips markup, normalizes empty-like values, and truncates to single-row display.
Resume-brief query and decision flow
src/notifications/sources/resume-brief.ts
Deeplake query now fetches up to LOOKBACK recent summaries and walks them newest-first. For each summary, extractNextSteps() checks for open work. Returns open-work brief with CTA and relative age if found; wrapped-clean non-null brief if summaries exist but show no open work; null if no prior summary. Documentation and logging updated accordingly.
Resume-brief extraction tests
tests/claude-code/resume-brief.test.ts
Test fixture generates wiki-summary text with optional ## Next Steps and ## Open Questions / TODO. Test suite validates extractNextSteps() prefers ## Next Steps, handles fallback sections, strips bullet markers, normalizes explicit none/N/A to empty, returns empty when sections absent or blank, and takes first line of multi-line next steps.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • activeloopai/hivemind#223: Both PRs modify src/notifications/sources/resume-brief.ts; this PR evolves it from the retrieved PR's firstProseSentence-based resume brief to a new extractNextSteps/## Next Steps-driven "open work" lookup.

Suggested reviewers

  • efenocchi
  • kaghni

Poem

🐰 A prompt now whispers "Next Steps, if you please,"
Wiki summaries flow like the breeze,
Resume-briefs leap through histories—
Finding open work amid the queries,
Or peace when there's none. How the logic agrees! 📋✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description covers the main changes and rationale but is missing the Version Bump section required by the template. Add the Version Bump section to specify whether this is a patch, minor, or major version change (bug fix vs new feature).
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately summarizes the main changes: fixing the resume brief pickup functionality and adding context capture for tasks.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/resume-next-steps

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot requested review from efenocchi and kaghni May 31, 2026 15:57
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 31, 2026

Coverage Report

Scope: files changed in this PR. Enforced threshold: 90% per metric (per file via vitest.config.ts).

Status Category Percentage Covered / Total
🟢 Lines 99.28% (🎯 90%) 413 / 416
🟢 Statements 97.94% (🎯 90%) 475 / 485
🟢 Functions 95.56% (🎯 90%) 43 / 45
🟢 Branches 91.86% (🎯 90%) 237 / 258
File Coverage — 7 files changed
File Stmts Branches Functions Lines
src/commands/goal.ts 🟢 96.2% 🟢 92.5% 🟢 100.0% 🟢 98.8%
src/hooks/codex/spawn-wiki-worker.ts 🟢 95.0% 🟢 100.0% 🔴 66.7% 🟢 95.0%
src/hooks/cursor/spawn-wiki-worker.ts 🟢 100.0% 🔴 66.7% 🟢 100.0% 🟢 100.0%
src/hooks/hermes/spawn-wiki-worker.ts 🟢 100.0% 🔴 75.0% 🟢 100.0% 🟢 100.0%
src/hooks/session-start.ts 🟢 100.0% 🟢 96.2% 🟢 100.0% 🟢 100.0%
src/hooks/spawn-wiki-worker.ts 🟢 100.0% 🟢 100.0% 🟢 100.0% 🟢 100.0%
src/notifications/sources/resume-brief.ts 🟢 99.1% 🟢 91.5% 🟢 92.3% 🟢 100.0%

Generated for commit e9291ab.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/notifications/sources/resume-brief.ts`:
- Around line 101-103: Currently the code uses truthiness of s.get("next steps")
so an empty string or markers like "none"/"n/a" are treated as missing and it
falls back to other sections; change the selection logic to prefer the "next
steps" key when it exists (use s.has("next steps") or check for undefined
specifically) and accept empty/"none"/"n/a" as a valid body instead of falling
back — i.e., if s.has("next steps") then use s.get("next steps") (optionally
normalize whitespace and case for "none"/"n/a" but still treat them as present),
otherwise check "open questions / todo" and "open questions".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 01fd64b9-0c27-4616-9133-e38fe8531b43

📥 Commits

Reviewing files that changed from the base of the PR and between bfa7e1d and 7d73341.

📒 Files selected for processing (3)
  • src/hooks/spawn-wiki-worker.ts
  • src/notifications/sources/resume-brief.ts
  • tests/claude-code/resume-brief.test.ts

Comment on lines +101 to +103
const s = sections(summary);
const body = s.get("next steps") || s.get("open questions / todo") || s.get("open questions") || "";
if (!body) return "";
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't fall back when ## Next Steps exists but is blank.

Line 102 currently treats an empty ## Next Steps body as “missing” and falls through to ## Open Questions / TODO. That violates the new contract that empty/none/n/a means “wrapped clean,” and it can surface stale TODOs as the resume CTA.

Suggested fix
 export function extractNextSteps(summary: string): string {
   const s = sections(summary);
-  const body = s.get("next steps") || s.get("open questions / todo") || s.get("open questions") || "";
+  const body = s.has("next steps")
+    ? (s.get("next steps") ?? "")
+    : (s.get("open questions / todo") || s.get("open questions") || "");
   if (!body) return "";
   for (const raw of body.split(/\r?\n/)) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/notifications/sources/resume-brief.ts` around lines 101 - 103, Currently
the code uses truthiness of s.get("next steps") so an empty string or markers
like "none"/"n/a" are treated as missing and it falls back to other sections;
change the selection logic to prefer the "next steps" key when it exists (use
s.has("next steps") or check for undefined specifically) and accept
empty/"none"/"n/a" as a valid body instead of falling back — i.e., if
s.has("next steps") then use s.get("next steps") (optionally normalize
whitespace and case for "none"/"n/a" but still treat them as present), otherwise
check "open questions / todo" and "open questions".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's for existing summaries which don't have next steps contract.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@khustup2 — understood, thanks for the context. The fallback is intentional so that existing summaries without a ## Next Steps section at all still resolve through ## Open Questions / TODO. The only uncovered edge is a new-format summary where the section header is present but the body is literally empty (wiki worker wrote the heading and nothing else), which would fall back to the older section; but if the worker always emits at least none under the heading, that case never arises in practice. Happy to leave it as-is.

🐇 ~ (ˆ•ω•ˆ)


✏️ Learnings added
Learnt from: khustup2
Repo: activeloopai/hivemind PR: 224
File: src/notifications/sources/resume-brief.ts:109-111
Timestamp: 2026-06-01T21:31:06.615Z
Learning: In `src/notifications/sources/resume-brief.ts`, the `||` fallback chain in `extractNextSteps` — `s.get("next steps") || s.get("open questions / todo") || s.get("open questions") || ""` — is intentional for backward compatibility. Existing session summaries that predate the `## Next Steps` contract do not have that section at all, so falling back to `## Open Questions / TODO` is the desired behavior. The wiki worker is expected to always emit at least `none` under `## Next Steps` when the section is present, so a truly empty (falsy) body for an existing section is not a realistic scenario.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

khustup2 added 3 commits May 31, 2026 16:44
…the right summary

The resume brief is userVisibleOnly (the model never sees it), so when the
user says "load that from hivemind" the model has no referent. Add a static,
model-facing convention to the SessionStart context block telling the model
how to resolve a resume request from the VFS:
  - target = most recent summary for the current project (index.md Project
    match / ls -t summaries/<user>/);
  - skip clean-wrapped sessions (empty/"none" Next Steps) to the next with
    real open work — mirrors resume-brief's walk;
  - reconcile with current git state before acting, confirm don't auto-run;
  - don't bulk-read sessions/, drill in only for specifics.

Static instructions only (no mined content / no computed path) — same class
as the existing DEEPLAKE MEMORY block, so the injection guard is unaffected.
The model fetches the summary via its own cat on user request (safe channel).
…up actually fires

The resume logic was correct but starved: in-progress placeholder summaries
(skeletons with no ## section) plus duplicate rows per session filled the
LIMIT 5 window, so the walk-back never reached real summaries and every
session looked 'wrapped clean'.

- over-fetch (SCAN_LIMIT=40), dedup by session path, drop placeholders, then
  walk LOOKBACK real summaries; return null (plain welcome) when only
  placeholders exist instead of falsely claiming 'wrapped clean'
- extract pure isPlaceholderSummary + selectRealSummaries so the windowing is
  unit-tested without the network
- add ## Next Steps to codex/cursor/hermes wiki prompts for parity with
  claude-code (resume-brief prefers it; falls back to Open Questions / TODO)
…ontext-transfer

Explicit, in-session Save<->Resume pair on top of the goals primitive (no
Stop-hook/gate/worker — see docs/CAPTURE_TASKS.md for the decision):

- Save: 'save this for later' writes a goal whose body is a resumable context
  package (label + Start here / Files / Branch / Run / Why)
- Resume: 'let's work on that task' pulls the full body back and continues
- CLI: 'goal add --agent capture' (provenance, allowlisted) + 'goal get <id>'
  (full-body read — list only showed the first line, so resume had no way to
  transfer the package back)
- capture/resume operations added to all 4 agent skill copies
- tests for the flag, the agent allowlist guard, multi-line preservation, and
  full-body get
@khustup2 khustup2 changed the title Resume brief: "pick up where you left off" from summary Next Steps Resume: pickup-from-Next-Steps fix + capture tasks with context Jun 1, 2026
…at 90%

resume-brief.ts was at ~44% — only the pure helpers were tested.

- add pickResumeBrief tests behind a mocked DeeplakeApi/config/cwd boundary:
  the three outcomes, placeholder-skip + dedup windowing, gate/guards,
  truncation, and every relative-age bucket
- cover the section-fallback + empty-bullet fall-through in extractNextSteps
- resume-brief.ts -> 99/92/92/100, goal.ts -> 96/92/100/98
- enroll both files in the per-file coverage thresholds (90/90/90/90)
…lean

CodeRabbit (PR #224): the || truthiness chain in extractNextSteps fell back to
## Open Questions / TODO when ## Next Steps was present but empty, which could
surface a stale TODO as the resume CTA. Prefer Next Steps when the section
exists (s.has) — empty/none then means wrapped-clean — and only fall back to
the older section when Next Steps is absent (preserves backward-compat for
pre-contract summaries, per khustup2).

+ regression test for the present-but-blank edge with a stale TODO underneath.
@khustup2 khustup2 merged commit 617ea5d into main Jun 1, 2026
7 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.

2 participants