Releases: open-coder-ai/chock
Release list
v0.8.0 — Vendor facts derived, not duplicated; a real lint bar
The big one: chock stops hand-maintaining facts agentseam already knows, closes the
loop on every gap that surfaced along the way, and adopts a Sonar-class lint bar.
Every emitted byte for the four previously-enforced vendors stays identical
throughout — proven by full before/after artifact diffs at each step, not assumed.
Derive from agentseam's vendor config, not hand-copied tables
Config paths, event spellings, the cursor envelope, and the Claude shell matcher now
come from agentseam.vendor_config/agentseam.adapters through one chock.vendors
module, collapsing three per-vendor emitters and three installers down to one of
each. A witness ledger replaces hand-asserted coverage cells, so every claim carries
its own evidence and basis cap instead of a bare assertion.
Seven new vendors, membership computed not listed
IN_AGENT_TODAY and friends stop being hand-maintained lists — membership is now
matrix.can_block() capped by what a repo-scoped installer may actually touch.
antigravity, codex_cli (repo-level), devin, gemini_cli, grok, tabnine, and windsurf
all get real pre-tool coverage; junie joins as advisory-only (its config lives
outside what chock sync can write, pinned by a tripwire that flips the day
upstream changes that).
Externalized: templates, the CLI command table, and now the dependency itself
Following externalize, don't hardcode: every non-Python emitted template — CI-gate
steps, git-hook shims, scaffolded configs, vendored runtime fragments — moves from
Python string literals into real template files, each valid and linted in its own
language. The CLI's command table becomes data. And two of chock's own longstanding
stopgaps — codex_cli/vscode_copilot's shell-tool vocabulary and claude_code's
${CLAUDE_PROJECT_DIR} token — are now read live from agentseam 0.2.1's vendor
config instead of hardcoded, closing gaps chock's own tripwire tests found and
tracked until upstream could close them.
A Sonar/Checkstyle/FindBugs-class lint bar
Turned on ruff's complexity, naming, boolean-trap, exception-hygiene, dead-code, and
CLI-print-discipline rule families across src/, plus a new literal-duplication
guard. Every finding fixed category-by-category — pure refactor, zero behaviour
change.
Also in this release
- A guard that ran and couldn't decide now asks for confirmation instead of silently
allowing; a timed-out guard no longer leaks the command (credentials included) it
was gating. - A fourth in-agent coverage tier,
fail-to-ask, with an honest ordering. - Every published plugin package carries its own
LICENSE; the Codex manifest gains
itsinterfaceblock; the emitted icon ships as real package data.
Verification
Full suite green throughout every step, chock check/sync --check clean, the
acceptance suite green, and full before/after artifact diffs (compiled fragments,
installed configs, vendored runtimes, all plugin formats) byte-identical wherever no
new vendor was involved.
Full changelog: https://github.com/open-coder-ai/chock/blob/main/CHANGELOG.md
v0.7.0
0.7.0 — Migrate primitives-generation to agentseam
BREAKING-ISH: chock's file layout, coverage vocabulary, and vendored runtime bytes all
change. agentseam==0.1.0 is a real dependency (staged, not yet published — CI on this
change stays red by design until go-live; see the PR). Every adopter's next chock sync
rewrites .chock/bin/, .claude/settings.json, .cursor/hooks.json, and most per-agent
instruction files; some previously-written instruction files (for agents that read
AGENTS.md natively) are deleted outright, and coverage.json re-grades several
enforcement claims to a more honest, finer-grained word. All five migration-map axes land
in this release (owner decision #7, "Option B"); the full accounting is in the wave's
report, plan/spine-a/reports/w7.md on open-coder-ai/org-plan (private).
- Runtime: vendored PreToolUse/SessionStart runners are now agentseam's bundle, not a
hand-written cross-vendor adapter..chock/bin/pretooluse.pyand
.chock/bin/sessionstart.pyare gone, replaced by.chock/bin/claude_code.py,
.chock/bin/cursor.py, and.chock/bin/vscode_copilot.py— one self-contained,
stdlib-only file per agent (agentseam.bundler.bundle()plus chock's own guard-running
handler spliced in, seegate/runtime_bundle.py), instead of one file that sniffed which
vendor sent a payload by its shape. Claude Code's deny now rides entirely in the JSON
response body on a clean exit rather than exit code 2 — a deliberate, verified
improvement (avoids a PowerShell-wrapper exit-code collapse and a command-line leak into
the UI on some vendors), not a regression. Plugin packages (chock plugin buildfor
claude/cursor/copilot/codex) ship the matching per-agent runtime instead of a shared one. - Runtime:
installed_*_policy_idskeeps its content-comparison identity, verified
against agentseam's own new opt-in mode. agentseam'sinstall()/installed()gained a
content-comparison mode this wave (built by a prior worker specifically so a
multi-fragment consumer like chock would not have to keep re-deriving it). chock's own
threeinstalled_*_policy_idsfunctions keep their existing, already-correct
content-comparison logic rather than delegating to it: agentseam's mode does an exact
string compare with no hook for machine-independent normalization, and chock's committed
.claude/settings.jsonmust compare equal across machines with different baked
interpreter paths — delegating would have reintroduced the exact cross-machine
coverage-flip bug_normalize_fragmentexists to prevent. The required behavior (a
guard's compiled fragment changing drops its installed claim) is intact and tested. - Permissions:
claude_managed.pyis unchanged, on verified evidence. Checked directly
against Claude Code's own documentation (code.claude.com/docs/en/permissions, read
2026-08-29): permission rules cannot match a tool's content field at all — the docs name
this explicitly and say Claude Code rejects an attempt to do so at parse time — and a
request for regex/content matching there was closed "not planned" upstream
(anthropics/claude-code#37509).scan-secrets's regex-based managed-setting fragment
has no equivalent inagentseam.permissions.plan()'s model and none is being forced
through; no protection changes. - Instructions: whole-file branded templates are gone, replaced by agentseam's
marker-block / shared-file model (owner decision #8). Most agents chock scaffolds for
readAGENTS.mdnatively (agentseam.instructions.reads_shared()) and now get no
dedicated file at all:.cursor/rules/*.mdc,.cursorrules,.windsurf/rules/*.md,
.windsurfrules,codex.md,.kimi-code/AGENTS.md,.github/copilot-instructions.md,
.gemini/GEMINI.md, and.github/agents/*.agent.mdare no longer written — their
content lives only inAGENTS.md's own managed pointer block. Agents that do not read
AGENTS.mdnatively (claude, aider, devin, grok, replit, tabnine, antigravity) get a
marker-delimited block in their own file instead of a whole-file claim, so adopter
content elsewhere in that file survives untouched — coexistence a whole-file template
could never offer. Claude Code's own file moves from.claude/CLAUDE.mdtoCLAUDE.md
at the repo root (agentseam's preferred path). Aider is the one exception: agentseam's
model cannot express.aider.conf.yml(a real config file, not a marker-block target),
so chock still ships it directly alongside the marker block it writes into
CONVENTIONS.md. - Coverage:
coverage_level()adopts agentseam's five-tier vocabulary for in-agent
surfaces (owner decision #9).pre-tool-use/agent-hooks, once installed, no longer
read a flatenforced— they return whichever ofenforced/enforceable/best-effort
the mapped agent's own verified capability row earns
(agentseam.matrix.enforcement_level). claude_code's PreToolUse is FAIL_OPEN, so it now
readsbest-effort, neverenforced; cursor's is FAIL_CONFIGURABLE, so it reads
enforceable.enforced-at-commitandadvisorystay chock's own words for its
git-hook/CI-gate and ambient-rule surfaces, which are outside agentseam's per-agent-hook
model;unsupportedis renamednone, agentseam's own word for the same claim. A
companionopen-coder-ai/chock-catalogPR re-renders the seven guard-shipping policies'
docs and coverage matrix to the same honest wording (their own descriptions already said
"best-effort"; only the machine-readable label was overclaiming).
v0.6.0
Agent-hooks py launcher fallback and INT-3 verb list
MINOR: the agent-hooks emitter output changes, so an adopter's next chock sync /
chock plugin build rewrites .github/hooks/*.json. No credited enforcement surface
changes — the guard runs the same, just with one more way to find an interpreter.
Changed
- Agent-hooks Bash resolver adds the
pylauncher fallback. The Bash branch resolved
command -v python3 || command -v python; the PowerShell branch already triedpy. On a
Windows checkout where only thepylauncher is on PATH, the Bash hook exited
"no python interpreter found" and the guard failed open. It now also triespy,
matching the PowerShell branch, so the two agree about where enforcement holds. (#71) - INT-3 recognises
pinas a verb. Policy ids likepin-github-actionsno longer draw
a spurious "does not start with a verb" warning. (#71) - Docs: dropped a stale hardcoded published-version snapshot from the compatibility
page; the GitHub Action example now pins v0.6.0. (#72)
Release verification
The full pre-tag routine ran at zero failures on the tagged lineage: 844 tests green,
83% statement coverage, docs-accuracy and emitter-golden checks pass, catalog truth-check
251/251 eval cases (block and allow), and a byte-identical rebuild of the published
distribution trees. Post-tag verification (PyPI publish attestation, cold install, and
distribution republish from this tag) runs next and the distribution repos will republish
against v0.6.0.
v0.5.0
0.5.0 — Managed-setting and SKILL honesty
MINOR: the Claude managed-setting emitter and the generated SKILL note change, so an
adopter's next chock sync / chock plugin build rewrites those artifacts. No credited
enforcement surface changes — both are non-credited/advisory outputs being brought into
line with what they can actually deliver (do-not-claim, applied to the emitter itself).
protect-main-branchmanaged-setting is now empty. It previously emitted a
branch-blind command-text deny (commit.*\b(main|master)\b) that missed a plain
git commiton main and false-positived on "main" in a message. A static managed
setting cannot resolve branch state, so the honest managed-setting for branch
protection carries no deny — enforcement lives in its git-hook and ci-gate surfaces,
which do read the branch.scan-secretsmanaged-setting aligned to the gate. Addedjks|keystoreto the
credential-file pattern and more high-confidence credential prefixes (xoxb, sk/rk_live,
sk-ant, AIza, npm_) so the in-session echo is less of a silent subset of the git-hook.
Kept lookahead-free for cross-client regex-engine safety; the git-hook remains
authoritative.- SKILL advisory note is conditional on artifact. A
rule(advise-tier) policy no
longer claims it "becomes a git hook that exits non-zero" when compiled — it ships rule
text and stays advisory. Onlyhookpolicies carry that line; guard-script policies
still get the enforced note in the per-client plugin formats.
v0.4.0
0.4.0 — Witnessed enforcement on Cursor and Codex
MINOR: plugin packaging output changes (spec fixes and three new formats), and the
vendored PreToolUse adapter changes -- the deny-dialect and payload-decoding fixes below
mean an adopter's next chock sync rewrites it. Every other compiled enforcement
surface is unchanged.
-
Per-vendor marketplace indexing:
chock marketplace build --tree cursor|codex
indexes a vendor's own format tree with the index file its client actually reads --
Cursor's.cursor-plugin/marketplace.jsonin Cursor's schema, and for Codex the
legacy.claude-plugin/marketplace.jsonshape it was witnessed consuming from git
marketplaces -- so each vendor-named distribution repo carries exactly one vendor's
packages instead of every format tree. Default (--tree claude) is byte-unchanged. -
cursorandcodexplugin formats:chock plugin build --format cursor|codex
packages a policy for Cursor and OpenAI Codex, with the enforcing hook each vendor
actually reads. Same guard, same adapter, byte-identical to every other format --
only the envelope differs.--format allnow emits five trees.- Cursor (
.cursor-plugin/plugin.json+ flathooks/hooks.json) subscribes to
beforeShellExecution, the shell-scoped eventchock syncalready installs, so a
plugin install and a repo install run the identical hook. Nomatcheris emitted:
under this event the matcher is a regex over the COMMAND TEXT, not a tool name, so
the other formats'"Bash"would match almost nothing and silently disable the
guard. Cursor ignores Agent Plugins hooks entirely, so this is the only format that
enforces there. - Codex (
.codex-plugin/plugin.json+ nestedhooks/hooks.json) subscribes to
PreToolUsewith matcherBash-- Claude's protocol exactly. The legacy
.codex-plugin/manifest is deliberate: Codex's loader DISCARDS hooks from an
Agent-Plugins-format manifest (codex-rs/core-plugins/src/loader.rs), so shipping
the Copilot package there would install a plugin whose enforcement is deleted at
load time while its description still claimed it.
- Cursor (
-
Codex packages claim witnessed enforcement -- via JSON deny, not exit codes.
Probed on a real Codex Desktop install (Windows 11): a trusted PreToolUse hook
returning the documented exit-2 deny ran the command three times, because Codex wraps
Windows hook commands inpowershell -Command, which collapses exit 2 into 1 -- and
Codex's parser treats that as a failed hook and FAILS OPEN (its only stdout-parsing
arm is exit 0). With the deny carried inhookSpecificOutput.permissionDecisionJSON
on a clean exit, the same command was witnessed BLOCKED (2026-08-24). The adapter now
speaks that dialect to Codex-shaped payloads (turn_idpresent); Claude Code keeps
its witnessed exit-2 path. Conditions stated in the package posture: Codex hooks are
UNTRUSTED on install until a human approves a per-hook trust review, that trust is
bound to a hash of the hook command so a plugin update silently voids it until
re-approved, and every hook failure fails open. The emitted hooks.json also carries no
top-leveldescription: Codex < 0.143.0 rejects the whole file over that one key and
silently drops every hook in it (openai/codex#30397). -
Cursor packages DO claim enforcement, witnessed blocking on a real install after the
two fixes below, with a benign command in the same session still allowed. -
Two silent fail-opens fixed, both found by probing a real Cursor install (neither
is visible in any documentation, and each would have shipped a package that advertised
enforcement and delivered none):- Payload decoding. Cursor prefixes its hook payload with a UTF-8 BOM, and
sys.stdin.read()decoded those bytes with the platform locale (cp1252 on Windows),
turning the BOM into three stray characters.json.loadsthen failed, the adapter
reported "not checked", and returned 0 -- every command ALLOWED. The payload is now
read as bytes and decodedutf-8-sig, which also stops non-ASCII paths being mangled. - Deny signalling. Cursor documents exit 2 as "equivalent to returning
permission: deny". For plugin hooks that is false: a hook returning exit 2 with the
reason on stderr was witnessed NOT blocking -- the command ran. The adapter now also
emits Cursor's stdout response ({"permission": "deny", "user_message", "agent_message"}) for Cursor-shaped payloads only; Claude and Copilot still get
exit 2 with an empty stdout, asserted by test.
Witnessed blocking on a real Cursor install after both fixes, with a benign command in
the same session still allowed.
- Payload decoding. Cursor prefixes its hook payload with a UTF-8 BOM, and
-
A silent guard can no longer become a silent allow: the PreToolUse adapter now
guarantees a reason on stderr for every deny. Codex records exit 2 with an empty
stderr as a FAILED hook ("did not write a blocking reason to stderr",
codex-rs/hooks/src/events/pre_tool_use.rs) and lets the command run, so a guard that
denied without explaining itself would have enforced nothing there while every other
client showed a deny. Harmless elsewhere; load-bearing on Codex. -
The marketplace lockfile test now derives its expected tree set from
FORMATSrather
than an enumerated list -- the same under-coverage a hand-written list caused once
before, where a newly added tree escaped the check while it still read as complete. -
Bundled authoring skills use the same flat metadata: the five shipped skills
(chock-init, eval, optimize, policy-init, validate) carried the nestedchock:
object the packaged-policy fix removed — two metadata dialects in one project.
Their frontmatter is now the same flat string map (lists comma-joined, booleans
as "true"/"false"), and manifest ingestion decodes the typed fields; the derived
manifests are proven identical. Old nested frontmatter still loads, so
third-party skills are unaffected. -
SKILL.md
metadataspec fix: the Agent Skills spec (which Agent Plugins 1.0
defers to for SKILL.md) requiresmetadatato map string keys to string values;
the packaged skills nested achock:object there, which awesome-copilot'svally
linter rejected ("Metadata values must be strings"). Now a flat map with dotted
keys (chock.artifact,chock.enforcement,chock.coverage_without_chock) —
same facts, spec-conformant shape. A parsed-not-substring test pins the constraint. -
Posture-aware skill frontmatter: a hook-carrying package's SKILL.md used to
statecoverage_without_chock: advisorynext to the very hook that enforces —
one package stating and refuting a claim at once. The frontmatter now swaps the
advisory claim for the shipped hook's path (chock.hooks), the same substitution
the hook emitters already made in plugin.json and the closing note. -
copilotplugin format:chock plugin build --format copilotemits the Agent
Plugins 1.0 layout — rootplugin.json,skills/— with the enforcing PreToolUse
hook undercom.github.copilot/hooks/hooks.json, the namespace directory VS Code
documents for Agent Plugins hook bundles and non-Copilot clients must ignore. This
is the shape spec-validating marketplaces (awesome-copilot) accept; the Claude
layout, which Copilot also reads, keeps its manifest in.claude-plugin/and fails
their intake. Hook command, adapter and guard are byte-identical to the Claude
package's (asserted in tests): two formats, one enforcement system. The posture is
scoped to this format's audience — generic Agent Plugins clients are required to
ignorecom.github.copilot, so the description names where the hook enforces
(documented for VS Code agent mode) and that a namespace-ignoring client gets the
advisory skill only. Hook-carrying packages replace thecoverage_without_chock
extension claim with the hook's location, and the danglingmanifest: manifest.yaml
pointer (a file this out-of-place format never ships) is dropped — each package
carries only claims that are true of it.--format allnow emits three trees.
v0.3.0
0.3.0 — Native pre-tool-use for Copilot CLI and VS Code
agent-hooksenforcement surface:chock syncnow writes.github/hooks/chock.json,
the native pre-tool-use hook read by Copilot CLI and VS Code agent mode. Both honour
exit 2 as deny (witnessed blocking on both). The hook resolves its interpreter at run time
— skipping the Windows Storepython3alias stub that made hooks error — and finds the
repo root withgit rev-parse, so the committed file is portable with no baked path. One
adapter now parses all three payload shapes (Claude, Cursor, Copilot/VS Code). Coverage is
creditedenforcedfor copilot/vscode only when the file is verifiably installed. Guards
are bash-oriented, so on Windows PowerShell they catch bash-syntax commands but not
PowerShell-native destructive syntax until a PowerShell guard ships (documented caveat).
v0.2.0
0.2.0 — First release with an external contribution
MINOR: new features and adapters; compiled output for existing policies is unchanged
(golden-suite verified), but new surfaces exist.
- Antigravity CLI adapter — contributed by @alexsmolya, the project's first external
contribution:.agents/rules/chock.mdworkspace rule, ambient/git-hook/CI surfaces
(deliberately not pre-tool-use: no installer exists, so no claim is made). - Claude-format plugin emitter:
chock plugin build --format claude|all --out-dir
renders each policy into Claude Code's plugin layout (read natively by Claude Code,
Copilot CLI, VS Code and Grok Build), with the fail posture stated verbatim in every
emitted description and per-format subtrees so no package has to lie for another
client. Stale-output reconciliation, duplicate-id refusal. chock marketplace build: derives the marketplace index, a content-addressed
chock-market.lock(sha256 per published plugin directory), and a generated
PLUGINS.mdcatalog page from the built packages — never hand-listed, drift-checked.- Hook interpreter honesty: the emitted hook command stays a single
python3
invocation -- a review of the proposedpython3 || pythonfallback proved a chain
can erase a deny verdict (a deny exit followed by a missing-interpreter exit reads
as an error, and the first leg consumes stdin), so it was rejected with
measurements. Instead every emitted description now states the per-client fail
posture: fail-open clients allow silently withoutpython3and a usable bash;
fail-closed clients (VS Code) refuse matched commands; Windows needs the
Microsoft Storepython3alias disabled or Python installed. - Supply chain: the Marketplace action no longer interpolates workflow inputs
into shell (two HIGH template-injection alerts, fixed by env indirection); GitHub
Releases are created by the runner's ownghCLI instead of a third-party action;
the semgrep scanner installs hash-pinned via compiled requirements; Dependabot
gets a 7-day cooldown. - CI pressure testing: zizmor, actionlint, ShellCheck, and Semgrep (with custom
rules encoding this project's own incidents) run as required checks; all three
public repos are at zero open code-scanning alerts. - Fix:
chock removerefuses when a policy's manifest cannot be read — an
unreadable manifest previously read as "not mandatory" and allowed deletion. - Fix:
frontier_ingestno longer prints and exits at import time; frontier
validation shares oneSTANDARDS_DIRwith ingestion. - Tests: 755 (from 736); statement coverage 83%; new suites for the plugin
emitter, marketplace,chock remove, and the frontier validation modes.
v0.1.1
0.1.1 — Hardening and governance PATCH
Compiled output is byte-identical to 0.1.0 (golden-suite enforced); everything here is
validation, supply chain, documentation, and tests.
- Fix: policy-id validation now uses
fullmatch— an id with a trailing newline
was accepted by Python's$-before-newline matching. Found by the new
property-based suite. - Supply chain: every GitHub Action pinned to a commit SHA; least-privilege
permissions:on all workflows; pip installs hash-pinned via compiled requirements;
release artifacts now carry build provenance attestations; weekly coverage-guided
fuzzing (atheris) of the id and selection parsers. - Governance docs: GOVERNANCE.md (decision-making, roles, access continuity) and a
public roadmap index; SECURITY.md gains advisory URL and response timelines. - Tests: property-based suite for id validation and agent selection; unit suites
for the lifecycle umbrellas and frontier ingestion (statement coverage 78% → 81%). - Marketplace: the GitHub Action is listed as "Chock Governance Check" with branding.
v0.1.0
0.1.0 — First public release
Everything below is the launch surface; 0.0.1a0 was a name-claiming pre-release, so this
is the first version with real contents.
- Policies as code: versioned policy manifests committed to the repo, compiled by
chock syncto every enforcement surface each agent supports. - Enforcement surfaces: pre-tool-use guards (Claude Code and Cursor), git hooks,
a CI gate (chock sync --ci+ commit-range mode), and ambient rules for
instruction-file agents. - Coverage honesty: per-agent, per-policy claims at three levels —
enforced,
enforced-at-commit,advisory— raised only when the installed mechanism is
witnessed for that agent. - Arm-on-clone: cloned repos re-arm through an ambient rule plus a consented
SessionStart hook; git never clones hooks and Chock does not fight that boundary. - Catalog adoption:
chock add <id>installs hash-pinned policies from any
catalog, public or private; every published policy ships with replayed evals. - Compliance frameworks built in: OWASP Agentic Security Top-10, MITRE ATLAS,
NIST AI RMF, EU AI Act — manifests claim framework coverage,chock checkreports it. - Versioning contract: PATCH releases never change compiled output (enforced by a
golden-file suite); MINOR releases may.