feat(tasks): SessionStart reads the claim — a compaction gets its work back (milestone 381 step 3)
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / integration (push) Successful in 50s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / Python tests (push) Successful in 1m35s
CI & Build / Build & push image (push) Canceled after 45s

The claim now pays rent to the session that set it. The SessionStart hook
sends the host's `source` and the session id; the server renders a claim
section by source (task_claims.render_claims):

- compact / clear: the work this session had claimed, each with its two
  latest log entries, so a compacted session resumes from the record
  rather than from a count of open tasks.
- startup / clear: other sessions' live claims (may still be running) and
  in-progress tasks whose claim went quiet (abandoned mid-task).
- fork: the same, framed as "two sessions may now hold this".
- resume, or no source sent: nothing.

The task sidebar shows a live claim as "Being worked" and a dead one on
open work as "Went quiet", so the operator sees a session die mid-task.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-24 06:41:19 -04:00
co-authored by Claude Opus 5.5
parent a585fe0be0
commit e46eea3b52
8 changed files with 313 additions and 7 deletions
+7 -1
View File
@@ -70,10 +70,16 @@ async def session_context():
send it when a `.scribe` marker file names a project. Takes
precedence over `repo`. Access-checked like any other read — an id
this account cannot read loads no project rather than failing.
source (optional str) — the host's SessionStart source (startup,
resume, compact, clear, fork); decides what the claim section says.
session_id (optional str) — the session's id, so a claim bound to it
reads as this session's own (milestone 381).
"""
project_id, _repo, unbound_repo = await _project_scope()
result = await plugin_ctx_svc.build_session_context(
g.user.id, project_id, unbound_repo=unbound_repo
g.user.id, project_id, unbound_repo=unbound_repo,
source=(request.args.get("source") or "").strip()[:20],
session_id=(request.args.get("session_id") or "").strip()[:200],
)
return jsonify(result)