Skip to content

Feat/self verifying turns#262

Merged
cukas merged 8 commits into
mainfrom
feat/self-verifying-turns
Jul 16, 2026
Merged

Feat/self verifying turns#262
cukas merged 8 commits into
mainfrom
feat/self-verifying-turns

Conversation

@cukas

@cukas cukas commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

No description provided.

One resolvePermissionDecision pipeline (hard-deny -> deny rules -> task
lease -> allow sources -> boundary asks -> mode policy) now backs the
native/API preflight, the XML and eager tool paths, the companion
buildOnApproval gate, the MCP side-channel watcher, and the delegated
agent callback. The three divergent per-gate permissionMode reads are
retired; notably the smart-mode blanket auto-approve for delegated
agents is replaced by an auto-edit floor clamp (file edits run free,
Bash mutations still prompt), and an Always rule now suppresses the
lease prompt instead of double-gating. New agonPermissionMode config
key (ask|auto-edit|auto) migrates from the legacy permissionMode
(auto->auto, smart->auto-edit, ask/deny-all->ask); deny-all stays a
hard-deny override checked first. Leaseless delegated pushes and other
external side effects still ask even in auto mode. The approval prompt
fallback without a dispatch surface now denies instead of approving.

34-case golden decision table in tests/unit/permission-resolver.test.ts.

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
Shift+Tab now cycles ask -> auto-edit -> auto (Claude Code parity);
Ctrl+A and /auto stay as the direct AUTO toggle, mapped onto the same
mode enum (auto <-> auto-edit) through one applyPermissionMode writer
so cesarAutoMode, agonPermissionMode, the lease, and the footer never
disagree. The footer's AUTO slot becomes an always-visible permission
segment: 'AUTO' when autonomous, otherwise the mode label with a
shift+tab hint — restoring the approval-posture visibility the status
bar rewrite dropped. New /mode command (bare cycles, /mode <mode> sets,
/mode status explains).

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
The permission prompt grows to Yes / Yes-for-this-session / Always /
No / Never. Always persists a validated scoped rule (two-token Bash
scope like Bash(git push:*), exact resolved path for file tools) into
permissions.allow — never a bare base token; when no safe rule can be
synthesized (bare verbs, compounds, substitution, rendered previews)
the Always/Never choices simply don't appear. Never persists a deny
rule. Yes-for-session stores the rule in a session-scoped store so one
answer drains coalesced sibling prompts across a multi-engine run; the
queue drain now also honors persisted and session rules, not just
allowedCommands. /permissions lists persisted + session rules, the
legacy allowedCommands compat list, and the active mode, and gains
add allow|deny <rule> / remove <rule> subcommands.

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
Full-roster review (4/6 engines) confirmed two blockers, both fixed:
legacy bare allow sources (allowedCommands base tokens, tool-level
toolPermissions allow, session base tokens) could cover a dangerous
lease boundary — they now rank BELOW the boundary ask, and only
scoped permission rules (the deliberate Always artifact) remain strong
enough to auto-approve a push. And fileTargetInsideWorkspace treated an
empty cwd as universal containment, so delegated agent runs floor-
clamped to auto-edit could silently approve edits anywhere on disk;
empty-cwd now passes only relative non-escaping paths, the delegated
callback passes the real workspace root (team worktrees live under
.agon/agent-worktrees inside it), and auto mode without a lease fences
file mutations to the workspace itself.

Also from the review: subcommand synthesis skips key=value option
tokens (git -c user.name=x push -> Bash(git push:*)), persisting a rule
evicts it from the opposite bucket so Always-after-Never actually wins,
the remaining inline approval-string checks use
isApprovedPermissionResponse, ask-mode prompts carry the resolver
reason, and dead rule-engine imports are dropped. Refuted (no change):
'auto_off' in boundaryReasons is reachable via the lease reason
carry-through; parsePermissionRule strips ':*' so synthesized rules
validate (covered by tests).

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
When Cesar claims done after write-work (legacy done-claim or the agentic
'verifying' state), the harness now executes the discovered gate directly
whenever the unified permission resolver already allows the command (mode
auto, or an Always/session rule; resolver 'ask' falls back to the prompt
nudge). Green runs verify the claim deterministically; red runs feed the
real exit code and output tail back as a [SYSTEM] continuation so the
engine fixes actual failures. Results route through recordToolUse so all
existing verify bookkeeping flips uniformly. Runs are capped per turn
(cesarGateAutoRunLimit, default 3) and each re-run requires fresh
mutations. New tunables: cesarGateAutoRun, cesarGateAutoRunLimit,
cesarGateTimeoutSec, cesarGateOutputTailChars. The verify nudge round-trip
is extracted into a shared _injectSystemContinuation helper reused by the
gate-failure feedback path.

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
… turns

Full-roster review (6/6 engines) findings, each verified against source:
(1) codex — agentic fail → fix → re-run never re-triggered because
verificationFailed routes evaluateAgenticTaskState to 'running', never
back to 'verifying'; gateAutoRunTriggered (new pure fn, unit-tested) now
also fires on the settled verification_failed_fix_required state.
(2) kimi/claude — a done-claim after a red harness run ended the turn
looking done; the turn now ends with an explicit RED-gate warning and a
[HARNESS] note in the transcript. (3) codex/minimax — the read-only
classifier strips redirections, so 'npm test > file' resolved allow under
an ask posture; redirecting gates are now refused outside mode auto
(> /dev/null and fd-dups stay allowed). (4) minimax — engine-error state
is reset at the top of _injectSystemContinuation so a stale error cannot
short-circuit a healthy round-trip. (5) zai — the harness success note is
[HARNESS]-tagged so verification is not misattributed to the engine, and
the README documents the read-only-gate posture semantics.

Refuted (no change): lifecycle-hook/exec-tree expansion — the gate command
comes from the repo's own package.json/fitness line and the engine could
already run the identical command under the identical posture; silent
tool-loop catch — pre-existing pattern kept for parity.

⚔️ Forged by [Agon](https://github.com/KERNlang/agon)

Co-Authored-By: agon (KERN) <292465531+KERN-Agon@users.noreply.github.com>
# Conflicts:
#	packages/cli/src/generated/cesar/brain.ts
#	packages/cli/src/generated/signals/intent.ts
#	packages/cli/src/kern/signals/intent.kern
#	packages/core/src/generated/models/types.ts
# Conflicts:
#	packages/cli/src/generated/cesar/brain.ts
#	packages/core/src/generated/models/types.ts
#	packages/core/src/kern/models/types.kern
@cukas
cukas merged commit e480430 into main Jul 16, 2026
1 check passed
@cukas
cukas deleted the feat/self-verifying-turns branch July 16, 2026 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants