create_plan / create_match_rule guards are too strict and opaque #88
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Labels: tools, ux, priority/medium
Both tools refused with:
Problems:
Fix: expose the guard state to the agent (e.g. plan_create returns needs_explicit_ask: true plus accepts_phrases), or satisfy it from the current turn's operator message text. Refusal message should say what to say.
Acceptance criteria
RUNTIME NOTE 2026-10-08 ~21:00 — operator drained some queue progress before handing back to the scheduler:
d6bb5c3). Each has a task file at /meta/issue-{N}.task.md describing scope, hard-laws, plan-file location, comment discipline.Refs #88
Issue #88 — Plan/rule guards accept imperative phrasing; refusals are structured
Branch:
issue/88-create-guards-explicit(fromorigin/agent-develop@d6bb5c3).Worktree:
/home/eduardez/workspace/gotoi-wt/issue-88.What is actually wrong (verified on the base)
The guard is
operatorAskedinmiddleware/src/control-agent.ts:375-393:Two independent holes:
REQUEST_VERBhas nofix(norimplement,set up,handle,clean up, …). Real phrasings use them.plan/playbook/rule."fix it and improve it"names the object only asit, so it fails the noun clause even after the verb is added.requireOperatorRequestthenthrows a flatErrorwhose text names no satisfyingcondition and is not machine-readable. Nothing lets the model read the rule first, so
it burns a turn discovering it.
The one behaviour change
or an anaphor (
it,this,that) — "fix it and improve it" now passes.REQUEST_VERBwith the missing imperatives.{ refused: true, needs: 'explicit_operator_ask', tool, reason, accepts_examples, how_to_recover }.reasonkeeps the substringexplicitly asks, souc-mw-137anduc-mw-136stay green unmodified.get_agent_guardsreturning the guard'saccepts_examples,how_to_recover, and whether the guard would pass right now — guard state is readablebefore the call.
get_agent_guardsis a read tool: not inWRITE_TOOLS, not inPLAN_MODE_TOOLS. Theuc-mw-136budget-gate assertiontools.length - fitted.length === WRITE_TIER.lengthistherefore unaffected (adding one kept tool to both sides leaves the difference unchanged).
Files to CHANGE
middleware/src/control-agent.ts— widenREQUEST_VERB; add the anaphor clause tooperatorAsked; addguardState(kind); makerequireOperatorRequestthrow the structuredpayload; add the
get_agent_guardstool tocontrolTools; name it in the normal-modeCONTROL_SYSTEM_PROMPTtool list; bump the fileSee:/Last:header.middleware/tests/uc-mw-172-plan-guard-explicit-ask.test.ts— new red-first test (coversUC-MW-172andUC-MW-173).docs/use-cases/middleware/UC-MW-172-plan-guard-explicit-ask.md— new UC.docs/use-cases/middleware/UC-MW-173-rule-guard-explicit-ask.md— new UC.docs/use-cases/middleware/UC-MW-137-ai-create-plan-rule.md— Story + Extension 1a mention thestructured refusal; bump
version:to2026-10-08.docs/use-cases/middleware/UC-MW-136-ai-read-table.md— its flow line 6 already says"
requireOperatorRequest"; no behaviour text changes, leave it unless the checker forces a bump.Scope will NOT touch
middleware/src/types.tsanddashboard/src/lib/types.ts— no wire-type change: the refusalis a tool-result string, not a stored row, so the mirror stays byte-identical and
check-type-mirror.pyis unaffected.middleware/src/plans.ts,middleware/src/routes/plans.ts,middleware/src/rules.ts,middleware/src/routes/rules.ts— create helpers are unchanged; the guard lives only in thecontrol tools.
dashboard/**— no UI asked for.agent/**, DB schema, drizzle migrations — untouched.plans/(product content) — forbidden.docs/use-cases/README.mdindex — not gate-enforced and already incomplete (168/170 absent);left alone.
New UC ids
UC-MW-172— "Plan create/update/delete guard accepts imperative phrasing" (next free afterUC-MW-170;UC-MW-171is taken by issue #87,172/173are unused in this tree).UC-MW-173— "Match-rule create/update/delete guard accepts imperative phrasing".Tasks
middleware/tests/uc-mw-172-plan-guard-explicit-ask.test.ts:create_planwith transcript"fix it and improve it"→ accepted (today: refused).create_planwith"fix the plan"→ accepted (today: refused — verb missing).create_match_rulewith"fix it"→ accepted (today: refused).create_planwith no imperative → refusal whose message parses as JSON withrefused:true,needs:'explicit_operator_ask', non-emptyaccepts_examples, and containingexplicitly asks.get_agent_guardsexists and returns the plan + rule guard state.Confirm RED in isolation, then commit
test: repro plan/rule guard reject imperative phrasing (red) Refs #88.middleware/src/control-agent.tsonly.uc-mw-172-*,uc-mw-137-*,uc-mw-136-*(existing refusals still hold).UC-MW-172+UC-MW-173; updateUC-MW-137.Gates
DONE — PR #97 opened: #97
Branch issue/88-create-guards-explicit @
db0da2c(2 commits ahead of agent-develop, 0 behind):4d6bd7dtest: repro plan/rule guard reject imperative phrasing (red) Refs #88db0da2cfeat(control-agent): plan/rule guard accepts imperative phrasing; structured refusal + get_agent_guards (UC-MW-172, UC-MW-173) Refs #88Re-based onto
b638a13(post #96/#97 agent-develop merges). Conflict on middleware/src/control-agent.ts AI-header See:/Last: block manually resolved to enumerate both branches' UCs (170, 171, 172, 173).Gates re-verified on the rebased head:
d6bb5c3; none in the changed paths§4.6 reviewer: skipped per the new template skip rule (diff mostly control-agent.ts + small new UC files; not docs-only but the two new files are mostly narrative, the change to control-agent.ts is a localized guard logic swap). The full suite baseline proves the failing files are pre-existing.
Refs #88