Skip to content

feat(afk): prompt and subagent routers are off unless opted in - #37

Merged
0x7067 merged 2 commits into
0x7067:mainfrom
griffinwork40:afk-routers-default-off
Oct 5, 2026
Merged

0x7067 merged 2 commits into
0x7067:mainfrom
griffinwork40:afk-routers-default-off

Conversation

@griffinwork40

@griffinwork40 griffinwork40 commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Problem

On AFK the two router hooks cost a Jev call each time they run, and neither has ever been measured there:

  • subagent-router.ts makes one Jev call per agent spawn. AFK drops a PreToolUse hook's additionalContext unless the hook blocks (Non-blocking PreToolUse additionalContext from plugin hooks is dropped (but counted in the trace) griffinwork40/agent-afk#2778, dispatcher.pre-dispatch-gates.ts:527-541 in agent-afk 5.286.1). This hook never blocks, so its tier recommendation and brief check reach neither the agent nor the user.
  • prompt-router.ts makes one Jev call per REPL prompt and writes no log row on AFK, so stats.py cannot score it. Its hints (chat: "No file reads, no commands"; lookup: "one targeted search… then stop") can also push an AFK agent to answer "what does X do?" from memory instead of reading the source.

Today an AFK user can only turn off one of these by editing the installed hooks.json. AFK has no per-hook switch (griffinwork40/agent-afk#2816), and afk marketplace update checks out with --force, so the edit is silently reverted on the next update.

Change

  • adapters/afk/.claude-plugin/plugin.json declares userConfig.promptRouter and userConfig.subagentRouter, both boolean with default: false. They mirror the root plugin's fields of the same names.
  • enabled(field, whenUnset = true) in adapters/afk/src/shared/config.ts. An unset option returns whenUnset, and set values behave as before. The root Claude Code hooks call it with one argument, so unset still means on for them.
  • Both AFK routers read stdin, then return before any Jev call unless enabled("<option>", false) is true. They stay registered in hooks.json, so turning one on is a config change, not a manifest edit.
  • README: the hook table marks both as off by default, and a new Optional routers setup section explains how to turn them on.
  • CHANGELOG [Unreleased] bullet. No version bump: three other open PRs (fix(afk): bound stop-sweep loadRules inside shared 4.5s budget #34, docs(afk): refresh README against agent-afk 5.286.1 source #35, feat(afk): judge patch_apply edits in the rule hook #36) touch the same files, and a bump in each would conflict.

Rule checks, the Stop sweep, and the SessionStart digest are unchanged.

Verification

  • New adapters/afk/test/router-opt-in.test.ts, which spawns each router against a local fake Jev server:
    • option unset: zero requests, no output
    • option false: zero requests, no output
    • option true: the router calls Jev
    • enabled() unit test: unset is on with one argument and off with whenUnset = false; "true" and "0" behave as before
  • Mutation check: run against the routers from upstream/main, the four unset/false tests fail. They pass with this change.
  • node --experimental-strip-types --test adapters/afk/test/*.test.ts: 13 pass, 0 fail
  • npm run test:pi: 65 pass, 0 fail
  • tsc --noEmit (root and adapters/afk): clean
  • oxlint: 0 warnings, 0 errors
  • check_no_comments.py and check_no_stubs.py: ok

Notes


Summary by cubic

The AFK prompt router and subagent router now ship off by default and exit before calling Jev unless their userConfig option is set to true, because each costs a Jev call per prompt or spawn and neither is measured on AFK.

  • Adds promptRouter and subagentRouter options to the AFK plugin manifest with default: false; both hooks stay registered so enabling one is a config change, not a manifest edit.
  • enabled() now takes the value to use when an option is unset, keeping Claude Code hooks on by default.
  • Documents the pluginHookEnv/afk.env workaround for agent-afk versions that don't export userConfig options, and adds tests that verify zero Jev requests when the option is unset or false.

Written for commit 35a5c69. Summary will update on new commits.

Review in cubic

On AFK both routers cost one Jev call per prompt or per spawn, and
neither is measured there: AFK drops a non-blocking PreToolUse
additionalContext (griffinwork40/agent-afk#2778), so the subagent
router's advice never arrives, and the AFK prompt router writes no
log row. Its generic chat/lookup/fix hints can also steer an agent
away from reading source before it explains.

Both hooks stay registered and exit before calling Jev unless their
userConfig option is true. The adapter manifest declares
promptRouter and subagentRouter with default false, and enabled()
takes the value to use when an option is unset, so the Claude Code
hooks keep treating unset as on.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 7 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="adapters/afk/.claude-plugin/plugin.json">

<violation number="1" location="adapters/afk/.claude-plugin/plugin.json:5">
P3: This behavior change (routers off by default) ships with the version still at 0.6.2 in `.claude-plugin/plugin.json` and `package.json`, contrary to the AGENTS.md invariant that behavior changes bump the version. The changelog entry under `## [Unreleased]` is present; just confirm the bump lands before release rather than relying on memory — release notes and `afk marketplace` release tags follow this version.</violation>
</file>

<file name="adapters/afk/README.md">

<violation number="1" location="adapters/afk/README.md:91">
P2: The documented opt-in depends on `pluginHookEnv` in `afk.config.json`, which `agent-afk-handoff.md` in this repo describes as an unimplemented proposal, and which current agent-afk docs do not list (plugin hooks receive only `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PROJECT_DIR`). If it is not supported in agent-afk 5.286.1, this workaround is a no-op: `pluginOption()` reads `process.env` only, and AFK's hook env allowlist never carries `CLAUDE_PLUGIN_OPTION_*`, so the routers stay silently off. Verify the key exists in the installed agent-afk before documenting it as the enablement path, or state that no supported opt-in exists on AFK yet.</violation>

<violation number="2" location="adapters/afk/README.md:96">
P2: The workaround only forwards `CLAUDE_PLUGIN_OPTION_PROMPTROUTER`, so users opting into `subagentRouter` still receive no option variable and keep that router disabled. Allowlist both variables, or label this explicitly as a prompt-router-only example.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread adapters/afk/README.md
```json
{
"pluginHookEnv": {
"claude-jev-afk": ["CLAUDE_PLUGIN_OPTION_PROMPTROUTER"]

@cubic-dev-ai cubic-dev-ai Bot Oct 3, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The workaround only forwards CLAUDE_PLUGIN_OPTION_PROMPTROUTER, so users opting into subagentRouter still receive no option variable and keep that router disabled. Allowlist both variables, or label this explicitly as a prompt-router-only example.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At adapters/afk/README.md, line 96:

<comment>The workaround only forwards `CLAUDE_PLUGIN_OPTION_PROMPTROUTER`, so users opting into `subagentRouter` still receive no option variable and keep that router disabled. Allowlist both variables, or label this explicitly as a prompt-router-only example.</comment>

<file context>
@@ -78,8 +78,29 @@ The hooks look for `$AFK_HOME/config/afk.env`, or `~/.afk/config/afk.env` when `
+```json
+{
+  "pluginHookEnv": {
+    "claude-jev-afk": ["CLAUDE_PLUGIN_OPTION_PROMPTROUTER"]
+  }
+}
</file context>
Suggested change
"claude-jev-afk": ["CLAUDE_PLUGIN_OPTION_PROMPTROUTER"]
"claude-jev-afk": ["CLAUDE_PLUGIN_OPTION_PROMPTROUTER", "CLAUDE_PLUGIN_OPTION_SUBAGENTROUTER"]
Fix with cubic

Comment thread adapters/afk/README.md

They are off on AFK because each costs one Jev call per prompt or per spawn. AFK drops the subagent router's advice ([griffinwork40/agent-afk#2778](https://github.com/griffinwork40/agent-afk/issues/2778)), and the prompt router's hint does not go to the log, so neither is measured on AFK. The Claude Code plugin keeps both on by default.

AFK reads the option as `CLAUDE_PLUGIN_OPTION_PROMPTROUTER` or `CLAUDE_PLUGIN_OPTION_SUBAGENTROUTER`. agent-afk 5.286.1 does not export `userConfig` options to hooks ([#2373](https://github.com/griffinwork40/agent-afk/issues/2373); [#2732](https://github.com/griffinwork40/agent-afk/pull/2732) adds `afk plugin config <plugin> <key> <value>`). Until then, forward the variable with `pluginHookEnv` in `~/.afk/config/afk.config.json` and set it in `~/.afk/config/afk.env`:

@cubic-dev-ai cubic-dev-ai Bot Oct 3, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The documented opt-in depends on pluginHookEnv in afk.config.json, which agent-afk-handoff.md in this repo describes as an unimplemented proposal, and which current agent-afk docs do not list (plugin hooks receive only CLAUDE_PLUGIN_ROOT and CLAUDE_PROJECT_DIR). If it is not supported in agent-afk 5.286.1, this workaround is a no-op: pluginOption() reads process.env only, and AFK's hook env allowlist never carries CLAUDE_PLUGIN_OPTION_*, so the routers stay silently off. Verify the key exists in the installed agent-afk before documenting it as the enablement path, or state that no supported opt-in exists on AFK yet.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At adapters/afk/README.md, line 91:

<comment>The documented opt-in depends on `pluginHookEnv` in `afk.config.json`, which `agent-afk-handoff.md` in this repo describes as an unimplemented proposal, and which current agent-afk docs do not list (plugin hooks receive only `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PROJECT_DIR`). If it is not supported in agent-afk 5.286.1, this workaround is a no-op: `pluginOption()` reads `process.env` only, and AFK's hook env allowlist never carries `CLAUDE_PLUGIN_OPTION_*`, so the routers stay silently off. Verify the key exists in the installed agent-afk before documenting it as the enablement path, or state that no supported opt-in exists on AFK yet.</comment>

<file context>
@@ -78,8 +78,29 @@ The hooks look for `$AFK_HOME/config/afk.env`, or `~/.afk/config/afk.env` when `
+
+They are off on AFK because each costs one Jev call per prompt or per spawn. AFK drops the subagent router's advice ([griffinwork40/agent-afk#2778](https://github.com/griffinwork40/agent-afk/issues/2778)), and the prompt router's hint does not go to the log, so neither is measured on AFK. The Claude Code plugin keeps both on by default.
+
+AFK reads the option as `CLAUDE_PLUGIN_OPTION_PROMPTROUTER` or `CLAUDE_PLUGIN_OPTION_SUBAGENTROUTER`. agent-afk 5.286.1 does not export `userConfig` options to hooks ([#2373](https://github.com/griffinwork40/agent-afk/issues/2373); [#2732](https://github.com/griffinwork40/agent-afk/pull/2732) adds `afk plugin config <plugin> <key> <value>`). Until then, forward the variable with `pluginHookEnv` in `~/.afk/config/afk.config.json` and set it in `~/.afk/config/afk.env`:
+
+```json
</file context>
Fix with cubic

"description": "Jev judgment hooks for AFK — automatic rule enforcement, prompt routing, and turn-level compliance. Hooks are fences the agent cannot skip; MCP tools are lenses the agent chooses to use.",
"version": "0.6.2"
"version": "0.6.2",
"userConfig": {

@cubic-dev-ai cubic-dev-ai Bot Oct 3, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This behavior change (routers off by default) ships with the version still at 0.6.2 in .claude-plugin/plugin.json and package.json, contrary to the AGENTS.md invariant that behavior changes bump the version. The changelog entry under ## [Unreleased] is present; just confirm the bump lands before release rather than relying on memory — release notes and afk marketplace release tags follow this version.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At adapters/afk/.claude-plugin/plugin.json, line 5:

<comment>This behavior change (routers off by default) ships with the version still at 0.6.2 in `.claude-plugin/plugin.json` and `package.json`, contrary to the AGENTS.md invariant that behavior changes bump the version. The changelog entry under `## [Unreleased]` is present; just confirm the bump lands before release rather than relying on memory — release notes and `afk marketplace` release tags follow this version.</comment>

<file context>
@@ -1,5 +1,19 @@
   "description": "Jev judgment hooks for AFK — automatic rule enforcement, prompt routing, and turn-level compliance. Hooks are fences the agent cannot skip; MCP tools are lenses the agent chooses to use.",
-  "version": "0.6.2"
+  "version": "0.6.2",
+  "userConfig": {
+    "promptRouter": {
+      "type": "boolean",
</file context>
Fix with cubic

Combine hook-table rows (routers off-unless-opted-in + patch_apply on rules.ts). Keep both [Unreleased] CHANGELOG bullets.
@0x7067
0x7067 merged commit 021ce65 into 0x7067:main Oct 5, 2026
2 checks passed
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