Repository navigation
Releases: funcpn/volens
Release list
volens 0.4.2 — DSH messages survive Session format v4
The DSH half works on a v4 harness again. Session format v4 made a message's source.kind producer-owned: admission rejects an empty kind and rejects the literal plugin. volens was still emitting the v3 wrapper { kind: 'plugin', plugin: 'volens' }, so on a v4 host the injected documentation message failed admission and took the whole turn with it:
format v4 message requires a producer-owned source kind
This was not a label problem. A failed admission ends the turn, so a project's sync stopped running instead of merely rendering an anonymous row.
One field changed. Both injected messages now carry { kind: 'volens' }; the notice keeps form: 'notice' and its summary, so the row still renders as the notice it was.
Why the bare name and not plugin:volens. Both are admitted by v4 — the historical V3-to-V4 migration writes the prefixed spelling for third-party producers — but the two generations render the row differently. v4 uses the kind itself as the context-row label, while v3 falls back to a bare kind for a producer it does not know, having used the plugin id before. The bare name therefore reads volens on both, and one artifact serves 0.1.5/0.1.6 and 0.1.7+ without branching. That is why this is a patch release.
What did not change. The three sync branches, the cursor, the notice and context wording, the language selection, the skill provider, and every file under hooks/ are untouched. Claude Code and Codex keep the same hook commands and the same behavior; the version bump is the only thing they see, and no hook re-trust follows because the registered command strings are unchanged.
Verified. The suite passes 28 cases, including a new one that pins the emitted source (kind is the plugin name, no plugin property, notice summary preserved) so the wrapper cannot return unnoticed. Against the published @deepseek-ai/dsh-session-format-v3-to-v4@0.1.7-rc.2 row admission, the old wrapper is rejected with the message above while { kind: 'volens' } is admitted. The remaining check is end to end on a real v4 runtime: install this release and trigger one injection.
Install. Claude Code: /plugin marketplace add https://github.com/funcpn/volens.git, then /plugin install volens@volens. Codex: codex plugin marketplace add https://github.com/funcpn/volens, then codex plugin add volens@volens — the first session asks once to trust the hook; choose Trust all and continue. In the ChatGPT desktop app, installing does not authorize the hook: open the plugin's manage page and choose Trust all. DSH: dsh plugin --profile web add volens-dsh@0.4.2, then restart DSH.
Upgrading. Claude Code and Codex update the marketplace as usual; no hook re-trust is expected. DSH users can install this exact release with volens-dsh@0.4.2, or update without knowing the next version number using volens-dsh@latest. If the harness core is still on 0.1.5/0.1.6, this release works there too — there is no reason to wait for a core upgrade, and no reason to skip one.
Package. volens-dsh@0.4.2 contains the expected eight runtime and skill files. The reproducible tarball SHA-1 is 91b6fdf613df9c08db23fdd779806841a57f9a77.
Requirements. git on your PATH, git able to reach GitHub, and a bash to run the hook with (macOS and Linux ship one; on Windows it comes from Git for Windows — the bash.exe under System32 is WSL's launcher and does not count). DSH needs neither: its half runs in-process and its skill arrives with the package.
volens 0.4.1 — sync notices name the decisions they are syncing
The notice now says what arrived. Instead of reporting only DECISION-LOG grew (3→8), a delta notice names the number of new decision records, the exact line range, and each decision title in log order:
📝 DECISION-LOG gained 2 decision records (lines 4–8): 1. First decision title; 2. Second decision title. volens will update DESIGN.md accordingly.
The Chinese notice carries the same information in its own language. A single title stays unnumbered; multiple titles use standard ordered-list numbering (1., 2., and so on).
This is extraction, not model summarization. volens reads the ### YYYY-MM-DD — <title> headings from the exact N+1..M delta and displays those authored titles verbatim. It does not ask a model to summarize, translate or rewrite them. A malformed delta with no valid heading falls back to the old line-count notice, and the full rebuild notice remains generic rather than listing the entire history.
The next action is clearer too. volens will sync DESIGN.md could sound as if the file were being copied somewhere else. The delta notice now says volens will update DESIGN.md accordingly / 「如意」将据此更新 DESIGN.md. The wording remains future tense because the notice is emitted when the task is injected, before the agent has proved that the write succeeded.
Everything else stays where it was. The three sync branches, line-count cursor, rebuild behavior, title ordering, language selection and harness event points do not change. Both implementations — the shared shell hook used by Claude Code and Codex and the in-process DSH plugin — now render the same title list and numbering, with tests covering one title, multiple titles, malformed headings, CRLF input and language fallback.
Updating DSH is now documented with @latest. A bare dsh plugin --profile web add volens-dsh is suitable for a first install, but pnpm can leave an installed package alone while its recorded version range is already satisfied. Use dsh plugin --profile web add volens-dsh@latest to update; name a specific version only to pin or roll back.
Install. Claude Code: /plugin marketplace add https://github.com/funcpn/volens.git, then /plugin install volens@volens. Codex: codex plugin marketplace add https://github.com/funcpn/volens, then codex plugin add volens@volens — the first session asks once to trust the hook; choose Trust all and continue. In the ChatGPT desktop app, installing does not authorize the hook: open the plugin's manage page and choose Trust all. DSH: dsh plugin --profile web add volens-dsh@0.4.1, then restart DSH.
Upgrading. Claude Code and Codex can update the marketplace as usual; no hook re-trust is expected because the registered command strings are unchanged. DSH users can install this exact release with volens-dsh@0.4.1, or update without knowing the next version number using volens-dsh@latest.
Package. volens-dsh@0.4.1 contains the expected eight runtime and skill files. The reproducible tarball SHA-1 is 273b7938479421159eda23b7cce08c6c24a62ad6.
Requirements. git on your PATH, git able to reach GitHub, and a bash to run the hook with (macOS and Linux ship one; on Windows it comes from Git for Windows — the bash.exe under System32 is WSL's launcher and does not count). DSH needs neither: its half runs in-process and its skill arrives with the package.
volens 0.4.0 — the DSH install is one command, and the skill ships in the package
The DSH half used to be two installs. The plugin came from npm, and the skill had to be placed by hand — a symlink from a clone of this repository into a directory the harness scans. Both halves travel in one package now: dsh plugin --profile web add volens-dsh installs the plugin, registers its bundle, and hands the skill to the harness's skill registry, so /volens is in the menu once DSH has restarted, and the skill updates with the package instead of with the clone.
What moved. dsh/ is gone. The package manifest, index.js and cordis.patch.yml sit at the repository root, files carries skills/, and the tests moved to tests/. That is not tidiness: it is what puts the skill inside the package, and it is the shape this ecosystem's multi-harness packages already use.
Nothing changes for Claude Code or Codex. Same marketplaces, same hook commands, no re-trust — both commands are written with ${CLAUDE_PLUGIN_ROOT}/${PLUGIN_ROOT}, and nothing they consume ever referenced dsh/. The package page now shows this project's README rather than a DSH-specific one.
Updating names the version. dsh plugin --profile web add volens-dsh@0.4.0. A bare add volens-dsh reports "Lockfile is up to date" and leaves an installed copy alone; if a release is newer than the profile's supply-chain policy allows, the CLI says so and adds it to minimumReleaseAgeExclude in the profile's pnpm-workspace.yaml before installing it.
Install. Claude Code: /plugin marketplace add https://github.com/funcpn/volens.git, then /plugin install volens@volens. Codex: codex plugin marketplace add https://github.com/funcpn/volens, then codex plugin add volens@volens — the first session asks once to trust the hook; choose Trust all and continue. In the ChatGPT desktop app, installing does not authorize the hook: open the plugin's manage page and choose Trust all. DSH: dsh plugin --profile web add volens-dsh, then restart DSH.
Requirements. git on your PATH, git able to reach GitHub, and a bash to run the hook with (macOS and Linux ship one; on Windows it comes from Git for Windows — the bash.exe under System32 is WSL's launcher and does not count). DSH needs neither: its half runs in-process and its skill arrives with the package.
volens 0.3.1 — the Chinese sync notice brackets the tool name
The Chinese notice read as a typo. Both implementations announce every sync with a one-line notice, and the Chinese one read 📝 DECISION-LOG 新增 0→25 行,如意将同步 DESIGN.md. The clean-install test report's own first draft read 如意 as a misspelling — the reading an unbracketed alias invites when it sits between technical identifiers like DECISION-LOG and DESIGN.md. It now reads 「如意」将同步 DESIGN.md, using the corner brackets the README already puts around the name.
What changed. One string per implementation, identical in both. The English notice still says volens will sync DESIGN.md; the rebuild branch and the injected instruction are untouched.
Upgrading. Claude Code and Codex: upgrade the marketplace as usual — no re-trust is needed, because the trusted hash covers the command string and not the script's text. DSH: re-run dsh plugin --profile web add volens-dsh (reinstalling is how an update arrives there), then restart DSH.
Install. Claude Code: /plugin marketplace add https://github.com/funcpn/volens.git, then /plugin install volens@volens. Codex: codex plugin marketplace add https://github.com/funcpn/volens, then codex plugin add volens@volens — the first session asks once to trust the hook; choose Trust all and continue. In the ChatGPT desktop app, installing does not authorize the hook: open the plugin's manage page and choose Trust all. DSH: dsh plugin --profile web add volens-dsh, then link the skill with ln -s /path/to/volens/skills/volens ~/.agents/skills/volens and restart.
Requirements. git on your PATH, git able to reach GitHub, and a bash to run the hook with (macOS and Linux ship one; on Windows it comes from Git for Windows — the bash.exe under System32 is WSL's launcher and does not count). DSH needs no bash: its half runs in-process.
volens 0.3.0 — DSH support, and the DSH half ships as an npm package
A third harness. volens now runs on DeepSeek Harness (DSH), which loads plugins into its own process rather than running a hook command. The sync logic is reimplemented there as a native cordis plugin: one registration point (agent/pre-step, gated to the first step of a turn), the same three branches, the same newline-count cursor, with the shell script still the reference. No bash is involved on that path.
The DSH half is on npm. DSH has no marketplace, so its plugin reaches users as volens-dsh — and dsh/ in this repository is exactly what npm publishes, five files, so the source a user reads is the source they installed. The skill stays a separate step: DSH discovers skills from filesystem roots, and a plugin manifest cannot declare one.
The rebuild branch was asking for the wrong thing. It told the model to read the whole rewritten log, while the paragraph it shared with the delta branch had just told it not to. The two branches now say what is true of each: a delta names its exact slice and forbids reading the whole log; a rebuild names 1..M and asks for all of it, reporting the position the stale snapshot had actually reached.
Both READMEs. They name all three harnesses from the first line, list the DSH install among the alternatives, and describe the sync by what each harness actually does instead of calling all of it "the hook".
Install. Claude Code: /plugin marketplace add https://github.com/funcpn/volens.git, then /plugin install volens@volens. Codex: codex plugin marketplace add https://github.com/funcpn/volens, then codex plugin add volens@volens — the first session asks once to trust the hook; choose Trust all and continue. In the ChatGPT desktop app, installing does not authorize the hook: open the plugin's manage page and choose Trust all. DSH: dsh plugin --profile web add volens-dsh, then link the skill with ln -s /path/to/volens/skills/volens ~/.agents/skills/volens and restart.
Requirements. git on your PATH, git able to reach GitHub, and a bash to run the hook with (macOS and Linux ship one; on Windows it comes from Git for Windows — the bash.exe under System32 is WSL's launcher and does not count).
volens 0.2.1 — the content-language pin is validated
One string came in unvalidated. The instruction the hook delivers carries exactly one project-controlled value — the content language read from .volens/lang — and it was embedded as found, after stripping ASCII whitespace only. A no-break space, or a whole sentence, survived that; the JSON stayed valid; and the text arrived in a channel framed as instructions, on the machine of anyone who cloned the project.
What changed. The pin is now read as a language tag and nothing else: zh, en, zh-CN, zh-Hans-CN pass. A value that is not a tag is treated like a missing pin — the hook falls back to your preference — and the next sync notice says which language is actually in force, so an ignored pin and a working one no longer look alike. The skill writes a tag rather than the language's own name, and the READMEs say the same. Your user-level preference at ~/.config/volens/lang is your own file and still falls back silently.
Upgrading. codex plugin marketplace upgrade volens pulls the marketplace snapshot and the plugin cache together, and no re-trust is needed: the trusted hash covers the command string, not the script.
If you added the marketplace with --ref (the branch the Codex side was developed on), that ref no longer moves. Remove the marketplace and add it again without a ref so it follows main, which is what the install instructions do.
Also in this release. The opening line names the ChatGPT desktop app among the supported surfaces, where the README already documented installing.
Install. Claude Code: /plugin marketplace add https://github.com/funcpn/volens.git, then /plugin install volens@volens. Codex: codex plugin marketplace add https://github.com/funcpn/volens, then codex plugin add volens@volens — the first session asks once to trust the hook; choose Trust all and continue. In the ChatGPT desktop app, installing does not authorize the hook: open the plugin's manage page and choose Trust all under "1 hook needs review before it can run".
Requirements. git on your PATH, git able to reach GitHub, and a bash to run the hook with: macOS and Linux ship one, and on Windows it comes from Git for Windows (the bash.exe under System32 is WSL's launcher and does not count).
v0.2.0 — brought to Codex, and verified on Windows
Codex support. Codex gets its own manifest, marketplace entry and hook config. The hook registers UserPromptSubmit only: Codex fires SessionStart at the head of a turn, where it would inject the same slice a second time, and a session opened and left silent syncs nothing either way.
One command form, two platforms. The command reaches the shared sync script through a new polyglot dispatcher, hooks/volens-hook.cmd — a batch script to cmd and a shell script to bash. It finds a usable bash (skipping the WSL launchers that are also named bash.exe) and hands over; no sync logic lives there.
Two Windows defects, found before release. The shipped command could not run on Windows at all — the shell there evaluates it as PowerShell — and the dispatcher's argument probe aborted cmd at parse time, so every run exited 255 with no output. Both are fixed, and the chain was then verified on Windows, on WSL/Linux and in the ChatGPT desktop app.
Installing in the desktop app. The app never asks to trust a hook, and an untrusted hook is skipped in silence: the plugin looks healthy while DESIGN.md quietly stops updating. The READMEs now say where the entry is — the plugin's manage page, Trust all under "1 hook needs review before it can run" — and that the sync notice is a hover tooltip there.
Upgrading. codex plugin marketplace upgrade volens pulls the marketplace snapshot and the plugin cache together, and existing hook trust carries over: the trusted hash covers the command string, not the script.
Also in this release. The contract module is chosen by harness (CLAUDE.md on Claude Code, AGENTS.md on Codex) and no longer names its own file, so one template serves every harness; the content-language pin moves to .volens/lang; and the user-level language preference honors XDG_CONFIG_HOME.
Install. Claude Code: /plugin marketplace add https://github.com/funcpn/volens.git, then /plugin install volens@volens. Codex: codex plugin marketplace add https://github.com/funcpn/volens, then codex plugin add volens@volens — the first session asks once to trust the hook, choose Trust all and continue.
Requirements. git on your PATH, git able to reach GitHub, and a bash to run the hook with: macOS and Linux ship one, and on Windows it comes from Git for Windows (the bash.exe under System32 is WSL's launcher and does not count).
v0.1.4 — the Stop-hook loop fix
volens keeps a project's documentation in step with its decisions: an append-only decision log, a design snapshot derived from it, and a hook that refreshes the snapshot automatically — no hand-maintenance.
/plugin marketplace add https://github.com/funcpn/volens.git
/plugin install volens@volens
This is the fifth release and the first one published. The four before it were tagged retroactively, so the version history is complete — what each of them fixed is below.
0.1.4 — the Stop-hook loop (fixed)
The most serious bug so far. When the DESIGN.md write never landed, the hook re-injected the same delta on every Stop — 98 injections over 240 seconds, burning tokens with nothing to show for it. Two defects underneath:
- the script never read its hook input, so it could not see
stop_hook_active - the injected instruction said only "never skip the write", which gave the model no way out
Both fixed. The guard is scoped to Stop only, since that field is not sent to SessionStart. A write that gets refused is now reported instead of failing silently.
Reproduced end to end after the fix: 2 hook executions, 18 seconds, normal exit — and the second Stop produced no output at all, which is the guard firing.
0.1.3 — escape hook output
Hook output was being concatenated into JSON rather than escaped.
0.1.2 — the skill no longer asks the model to judge whether the hook is live
The skill told the model to hand-update DESIGN.md when it found no hook installed. To evaluate that condition the model inspected ~/.claude/plugins/installed_plugins.json — which is correct and expected to be empty there, because that file tracks marketplace installs only. A skills-directory install never appears in it. So the model concluded the hook was missing and took over a job the hook was already doing.
Both conditionals deleted. The always-loaded CLAUDE.md contract module already carries the governing rule.
0.1.1 — the notice was invisible
systemMessage was nested inside hookSpecificOutput, where Claude Code silently ignores it. It has to be top-level.
0.1.0 — first release as a plugin
The documentation model ships as a plugin: the sync hook now lives in the plugin's hooks/ instead of being written into your project.