[AI-1915] Inject a SessionStart work-items nudge across all harnesses - #548
Conversation
Registering kcap-workitems everywhere (its companion change) is not enough on its own: no harness was told to USE it. This adds a short, standing SessionStart nudge that tells the agent it is in a recorded session (with the current session id, rendered verbatim so a harness without an ambient KCAP_SESSION_ID can pass it explicitly) and to register the session with declare_work_item and declare its structure with declare_work_breakdown / declare_work_relation as it works. Design: - WorkItemsNudgeEmitter builds the static nudge from the session id — a pure function, no server round-trip and no lease. - It is composed at the OUTPUT layer (SessionStartMemoryOutputAdapters.Render, marker-first when it stands alone) AFTER the lease-gated memory/guidelines fragment is decided, so its presence never changes the acquire/complete/retry state of those lanes. A null nudge is byte-identical to the pre-nudge render. - WorkItemsNudgeAvailability gates the nudge on the invoking harness's ACTUAL materialized MCP config carrying an enabled kcap-workitems entry (config-level, not a runtime health probe); fail-closed on absent/disabled/malformed/unreadable so a stale install is never nudged toward a tool it lacks. Claude always had it. - disable_workitems_nudge profile opt-out (default off), wired through kcap config and all nine hooks; OpenCode additionally respects its plugin fragment-capability gate. Wired into all 9 SessionStart hooks (Claude via BuildEnvelope; the 8 others via Render), preserving each hook's existing no-content byte-identity. Tests: emitter contract (session-id verbatim, all three tools + blocks/blocked_by directionality, opt-out/unavailable suppression), the availability gate per representative harness (present/absent/malformed/disabled, fail-closed), and the Render composition + isolation (marker-first-alone; null nudge == baseline). Ships in the same release as AI-1914. Fixes AI-1915 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR Summary by QodoInject SessionStart work-items nudge across all harness hooks
AI Description
Diagram
High-Level Assessment
Files changed (16)
|
- JSON gate: require the matching entry to be an object; a null/string/array value is malformed and suppresses. An explicit `enabled` must be a Boolean true — a false or a non-Boolean (e.g. "false") suppresses. - Pi gate: match "workitems" inside the actual KCAP_MCP_SERVERS array literal, not any stray token (a comment mention no longer counts). - Codex gate: use ReadMcpServerCommands (requires a command) so a malformed, command-less table does not count. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Code Review by Qodo
1.
|
The first-occurrence scan could select a commented-out KCAP_MCP_SERVERS declaration before the real one. Now strip JS line/block comments first, find the real declaration, and require "workitems" as an exact array element (not a substring). Tests: commented declaration before the real one, block comment, and a non-exact element all suppress. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- WorkItemsNudgeEmitter.Build now suppresses a session id carrying a backtick or any control char (newline/CR/tab) — it would otherwise break the Markdown code span or smuggle formatting into agent context. A uuid/hex/file-path id (Pi's is a file path) passes untouched. Tests added. - README: document the SessionStart work-items nudge + disable_workitems_nudge opt-out, and correct the now-stale "kcap-workitems is Claude-Code-only" claims (it is registered on every harness as of the companion change). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ests
The Claude availability gate was hardcoded true, so the work-items nudge was
emitted in the ClaudeHookCommand SessionStart tests (which run against the real
~/.claude), breaking six byte-exact memory-output assertions on any machine with
the kcap plugin installed. Fixes:
- Claude gate now uses ClaudePluginInstaller.IsEffectivelyInstalled (matching the
spec: available exactly when the plugin's bundled .mcp.json is loadable), so a
plugin-free environment (CI, isolated test home) fails closed → no nudge.
- ClaudeHookCommandTests.Fixture isolates CLAUDE_CONFIG_DIR to its temp home
(safe under the class's [NotInParallel("HomeEnvVarMutation")] lock), making the
whole Claude config surface hermetic. The 6 tests pass unchanged.
- Availability tests: Claude no-plugin → false, effective-plugin fixture → true;
the two Resolve tests use an explicit Codex config instead of ambient Claude.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
What
Registering
kcap-workitemson every harness (AI-1914) is not enough on its own — no harness was told to use it. This adds a short, standing SessionStart work-items nudge: it tells the agent it is in a recorded Kurrent Capacitor session (with the current session id, rendered verbatim so a harness without an ambientKCAP_SESSION_IDcan pass it explicitly), and todeclare_work_itemwhen it starts on a tracked item anddeclare_work_breakdown/declare_work_relationas it discovers structure. So work-item topology (Home "Blockers & dependencies", progress figures) stops being empty.Design
WorkItemsNudgeEmitterbuilds the static nudge from the session id — a pure function, no server round-trip and no lease. The nudge contract names all three tools with explicitblocks/blocked_bydirectionality, and says to attach to the real issue key/PR (create-by-title only when there is genuinely no tracker item, never fabricating an id).SessionStartMemoryOutputAdapters.Render, marker-first when it stands alone) after the lease-gated memory/guidelines fragment is decided, so its presence never changes the acquire/complete/retry state of those lanes. A null nudge is byte-identical to the pre-nudge render (tested across all 8 non-Claude harnesses).WorkItemsNudgeAvailabilitygates the nudge on the invoking harness's actual materialized MCP config carrying an enabledkcap-workitemsentry (JSONmcpServers/mcp, Codexconfig.toml, Pi extension content; Claude always had it). Config-level, not a runtime health probe; fail-closed on absent/disabled/malformed/unreadable — a stale install is never nudged toward a tool it lacks.disable_workitems_nudge(default off), wired throughkcap configand all nine hooks. OpenCode additionally respects its plugin fragment-capability gate.Wired into all 9 SessionStart hooks (Claude via
BuildEnvelope's variadic slot; the 8 others viaRender), preserving each hook's existing no-content byte-identity.Tests
WorkItemsNudge*Tests(20): emitter contract (session-id verbatim, all three tools + directionality, opt-out/unavailable suppression), the availability gate per representative harness (present / absent / malformed / disabled → fail-closed), and the Render composition + isolation (marker-first when alone; null nudge == baseline). All 266 existing SessionStart hook/memory tests still pass unchanged.Spec + codex spec-review (clean, 5 rounds) recorded on the Linear issue.
Ships in the same release as AI-1914.
Fixes AI-1915