The gap
Phase 1 (#29, shipped 0.16.0) gave the Claude Code hook three things when the gateway cannot see a call: the hardline floor, the new ask-level destructive floor, and a local ledger that flushes on connect. The gateway ships the same floor (gatewaystack-connect#1097, live) and the ingest endpoint (#1115, live).
Every other harness still allows those calls with a warning and records nothing. Per the harness-coverage doctrine, a capability that exists for one harness is owed to all of them.
Survey (2026-09-08)
Five different shapes, which is why this needs a design decision rather than eleven hand-ports:
| Plugin |
Governance entry point |
Language |
| claude-code |
bin/govern.mjs + bin/decide.mjs |
mjs — has phase 1 |
| codex |
bin/govern.mjs (455 lines, v0.6.6, no decide.mjs) |
mjs |
| antigravity, grok-build, muse-code |
hook.mjs |
mjs |
| dsh |
index.js |
js |
| fx |
lib/bridge.js |
js |
| opencode |
src/index.ts |
ts |
| openclaw |
src/govern.ts |
ts |
| pi, prime-agent |
index.ts |
ts |
| hermes |
src/acp_hermes/__init__.py |
python |
Nine of these are JS/TS and could share a module. Hermes needs a Python port of the same rules. None of the eleven has a generator; every copy is manual today, which is how install.sh ended up shipping a pre-floor engine for a full release cycle (acp-install#33).
The decision this needs
Option A — a published shared module. Extract decide.mjs (classifier + both floors) and the ledger into @agenticcontrolplane/decide, depend on it from the nine JS/TS plugins, port once to Python for Hermes. Fixes drift permanently and makes the next floor a version bump. Costs: a publish pipeline per plugin, and the plugins stop being single-file drop-ins, which is a property several of them were designed around (govern.mjs says so in its header).
Option B — one generator, per-harness params. Keep single-file plugins, generate them from one source (the doctrine's stated preference). No runtime dependency, but a build step in eleven repos.
Option C — floors only, ledger later. Port just the two floors now (small, pure, no I/O) and leave the ledger to the harnesses that have a config directory. Cheapest correct step; leaves the on-ramp story Claude-only.
Recommendation: C now, A or B as the follow-up. The floors are the safety half and they are pure functions with a fixture suite that already exists; the ledger needs a per-harness home for ~/.acp equivalents and is worth doing once the flush data from #29 says the on-ramp matters.
Acceptance (whichever option)
Related: #29 (phase 1), acp-install#33 (installer sync), gatewaystack-connect#1097 (gateway floor), #4 (stale embedded govern.mjs fallback, still v0.5.0 — separate).
The gap
Phase 1 (#29, shipped 0.16.0) gave the Claude Code hook three things when the gateway cannot see a call: the hardline floor, the new ask-level destructive floor, and a local ledger that flushes on connect. The gateway ships the same floor (gatewaystack-connect#1097, live) and the ingest endpoint (#1115, live).
Every other harness still allows those calls with a warning and records nothing. Per the harness-coverage doctrine, a capability that exists for one harness is owed to all of them.
Survey (2026-09-08)
Five different shapes, which is why this needs a design decision rather than eleven hand-ports:
bin/govern.mjs+bin/decide.mjsbin/govern.mjs(455 lines, v0.6.6, no decide.mjs)hook.mjsindex.jslib/bridge.jssrc/index.tssrc/govern.tsindex.tssrc/acp_hermes/__init__.pyNine of these are JS/TS and could share a module. Hermes needs a Python port of the same rules. None of the eleven has a generator; every copy is manual today, which is how
install.shended up shipping a pre-floor engine for a full release cycle (acp-install#33).The decision this needs
Option A — a published shared module. Extract
decide.mjs(classifier + both floors) and the ledger into@agenticcontrolplane/decide, depend on it from the nine JS/TS plugins, port once to Python for Hermes. Fixes drift permanently and makes the next floor a version bump. Costs: a publish pipeline per plugin, and the plugins stop being single-file drop-ins, which is a property several of them were designed around (govern.mjssays so in its header).Option B — one generator, per-harness params. Keep single-file plugins, generate them from one source (the doctrine's stated preference). No runtime dependency, but a build step in eleven repos.
Option C — floors only, ledger later. Port just the two floors now (small, pure, no I/O) and leave the ledger to the harnesses that have a config directory. Cheapest correct step; leaves the on-ramp story Claude-only.
Recommendation: C now, A or B as the follow-up. The floors are the safety half and they are pure functions with a fixture suite that already exists; the ledger needs a per-harness home for
~/.acpequivalents and is worth doing once the flush data from #29 says the on-ramp matters.Acceptance (whichever option)
--force-with-lease,rm -rf ./build).govern.mjsof the same shape, and the one with a live external user.Related: #29 (phase 1), acp-install#33 (installer sync), gatewaystack-connect#1097 (gateway floor), #4 (stale embedded govern.mjs fallback, still v0.5.0 — separate).