kyvvu-claude changelog¶
All notable changes to kyvvu-claude are documented in this file.
This file starts at 0.4.0. Releases 0.1.0 through 0.3.0 shipped without a
changelog; their contents are recoverable from the claude-v* tags and the
commit history rather than reconstructed here.
[1.0.0] - 2026-10-30¶
Released with kyvvu-engine 1.0.0; 0.8.0 was never published, and its
changes ship here.
-
Changed: depends on
kyvvu-templates>=1.0.0,<2.0.0, which now ships the behaviour templates the engine no longer exports. -
Breaking: the standalone
kyvvu-claudecommand is removed. Usekyvvu claude setup,kyvvu claude status,kyvvu claude refresh,kyvvu claude set,kyvvu claude hooks install, andkyvvu claude hooks remove. Setup reuses the API URL saved bykyvvu auth; the agent API key comes from--api-key,KV_API_KEYor a prompt.kyvvu-claudeis installed withuv tool install "kyvvu-cli[claude-code]"and requireskyvvu-cli>=1.0.0,<2.0.0. - Changed: the installed hooks call the
kyvvu-claude-hookscript by its absolute path, and hooks written by an earlier release are repointed to it. - Changed: per-user state moves from
~/.kyvvu-claudeto~/.kyvvu/integrations/claude-code. The firstkyvvu claudecommand moves every file across unchanged; a file already in the new directory is kept. -
Changed: registration, policy fetch, trace and incident delivery go through the engine's
PlatformClient, and tool inputs and outputs are recorded with the engine's capture functions. -
Changed: requires
kyvvu-engine>=1.0.0,<2.0.0. -
Breaking: requires Python 3.11 or newer (
requires-python = ">=3.11"), withkyvvu-engine1.0. On 3.10, pip keeps resolving the newest 0.x release. -
Added:
_flush_logssendsseqandhashon every step (the engine's v1 hash chain). Each hook is a new process, so the chain head is kept in the task's.deliveredcursor file, written in the same atomic replace as the acknowledged step and only after the API's 201: a batch that was not acknowledged is chained identically when it is resent under the same delivery key. When a split flush is accepted in part, the cursor advances past the batches the API took. A cursor written by an older release has no head, and the rest of that task is sent withouthash(the platform computes its chain). -
Fixed: a cached policy set served for another agent than the config names no longer passes for enforcement. The policy cache records the served
agent_idandagent_key(policy_cache.write()andrecord_fetch_outcome()take them;init/refreshread theX-Kyvvu-Agent-Idheader andSessionStartthe runner'spolicy_status().agent_id), and an envelope from before is read from the one agent its policies name (PolicyCacheEnvelope.served_agent_id). A malformed recordedagent_idis an unreadable cache.load_from_cache()takes a requiredagent_id=and reports a mismatch, or a config naming no agent, as unavailable with the newUnavailableCause.agent_mismatch: a deny underenforce,UNCHECKEDin monitor mode, and a message naming both ids and the setup command (nowkyvvu claude setup). A matching set is loaded withserved_agent_id=, so the runner refuses any otheragent_idin the hook process as well.SessionStartchecks the agent its fetch was served for the same way, and does not mark the cache untrusted for it.AgentBindingErrorfromevaluate(),restore_task()or anywhere else in a hook denies aPreToolUseunderenforce(orfail_mode: closed) and is logged; at the task start it is logged (agent_binding_refused) and the start recorded unevaluated.PreToolUseon an uninitialised config denies underenforceas it already did underfail_mode: closed. The status command (nowkyvvu claude status) printsPolicies for:and flags aMISMATCH.
[0.7.0] - 2026-10-17¶
-
Fixed: refused as too old by the platform, kyvvu-claude says so consistently.
SessionStartno longer prints the engine's "nothing can be enforced" line before loading a cache it then enforces; one line names the cached set. The status command (nowkyvvu claude status) names the too-old cause andpip install -U kyvvu-claudefor a cached set, and drops the strayKYVVU: 0 policies in effectnotice. With nothing cached,PreToolUsedenies with the upgrade reason instead of "no policy cache recording a successful fetch" (a recorded refusal no longer marks the session's cache untrusted; the decision is unchanged). The refresh command (nowkyvvu claude refresh) names what the cache still holds. -
Added: a blocked registration (
PolicyStatus.registration_blocked) is mapped like an unavailable policy set, with its ownUnavailableCause.registration_blocked: aPreToolUseunderenforceis denied, monitor mode logs itUNCHECKED, and the banner and status name the blocking policies. -
Changed: a hook
tool_use_idoutside the engine'saction_idgrammar (letters, digits and. _ : -, 1-255 characters) is mapped tox-plus 32 hex digits of its SHA-256, deterministically, so PreToolUse and PostToolUse still pair; a tool name used asstep_namehas control characters replaced and is cut to 255 characters. Neither can fail a hook. -
Breaking: A completed
AskUserQuestionemits a human gate withoutput.decision: pass; its input is kept out of exported properties. -
Breaking: Recorded steps carry the per-task ordinal as
seq, and the sub-agent stamp underproperties["kyvvu.subagent"]names the parent spawnspawn_seq(wasspawn_step). Session files written by an earlier version stay readable. -
Breaking: The behaviour field is
kindand its enum isActionKind; the retired field and enum names are rejected. Policy kind parameters aretarget_kinds,trigger_kinds,forbidden_kind,forbidden_kinds,required_kind,taint_kind, andforbidden_predecessor_kinds; old parameter names are rejected. A step policy'sfieldneeds a complete path such asinput.recipientorproperties.message.recipient(that is,input.<name>orproperties.<name>); bare data field names are rejected.
[0.6.0] - 2026-10-01¶
Requires the matching kyvvu-engine release.
Breaking changes¶
- The environment defaults to
productionand readsKV_ENVIRONMENT. It used to default todevelopment. A value saved in the config file still wins. - An unloadable cached policy set is reported as unavailable. The
engine raises
PolicyLoadErrorrather than dropping policies; the hooks turn any exception into an allow, sopolicy_state.load_from_cachecatches it and reports the set as unavailable (unloadable_set), which denies underenforce. The per-policy "dropped" lines are gone fromkyvvu-claude's status output.
Changed¶
- Incident reports and trace flushes are asynchronous in the engine. A hook
is a short-lived process; it relies on the engine's
atexitflush, which waits up toKV_REPORT_EXIT_FLUSH_SECONDS(default 2 seconds) for queued reports.
[0.4.0] - 2026-08-27¶
Breaking. Follows kyvvu-engine 0.10.0 in restoring the task.*
action-type namespace. Requires kyvvu-engine>=0.10.0.
Breaking changes¶
- The four task-lifecycle step types return to the
task.*namespace:step.task_start→task.start,step.task_end→task.end,step.task_error→task.error,step.task_idle→task.idle. TheStepTypemembers are renamed to match, so the hook and mapper code fails at import against an older engine rather than silently emitting a value nothing matches.
claude-code.template.yaml needed no change: it maps Claude Code tool events
onto the eight behavioral step.* types only. The task-boundary markers are
emitted programmatically from hooks.py (SessionStart opens a task,
Stop closes it), which is where the rename lands.
- The
kyvvu-enginedependency floor moves to>=0.10.0,<1.0.0. Installing 0.4.0 against engine 0.9.0 raisesAttributeErroron the renamed members at import time.