feat(tasks): the hand-off — SessionEnd releases a session's claims; the practice is written down (milestone 381 step 4)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 59s
CI & Build / Python tests (push) Successful in 1m40s
CI & Build / Build & push image (push) Successful in 24s

Release is the mechanical half: scribe_session_end.sh sends the ending
session's id to /api/plugin/release-session, which releases the claims it
held. A tidy-up, not the guarantee (no SessionEnd on a crash; the lease
covers that), and skipped on /clear so SessionStart(clear) can still
hand the claimed work back.

Saying what happened is the half only the model can do. It is stated as a
practice where it is read: the using-scribe skill owns it ("Hand off before
this session's context stops existing", pinned in test_guidance_ownership),
the static context points at it for the wrap-up moment, and add_task_log's
docstring says a log claims the task. _INSTRUCTIONS is untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-24 06:43:14 -04:00
co-authored by Claude Opus 5.5
parent e46eea3b52
commit 952e56ee75
11 changed files with 161 additions and 1 deletions
+6
View File
@@ -395,6 +395,12 @@ SMOKE_EVENTS: dict[str, str] = {
"tool_input": {"task_id": 1, "content": "smoke"},
"tool_response": {}}
),
# The SessionEnd claim release (milestone 381 step 4). Silent: nobody reads
# a SessionEnd hook's output, and with no instance it must exit first.
"scribe_session_end.sh": json.dumps(
{"session_id": "smoke", "cwd": ".", "hook_event_name": "SessionEnd",
"reason": "prompt_input_exit"}
),
# The shared library is sourced, never run; executed bare it defines
# functions and exits — silent by construction.
"scribe_defs.sh": "",