Skip to content

feat(autonudge): wall-clock runtime budget for monitoring loops - #2116

Merged
iamwhatever merged 1 commit into
kirodotdev:mainfrom
rubencu:feat/autonudge-runtime-budget
Aug 8, 2026
Merged

iamwhatever merged 1 commit into
kirodotdev:mainfrom
rubencu:feat/autonudge-runtime-budget

Conversation

@rubencu

@rubencu rubencu commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

What

Adds an opt-in wall-clock runtime budget (max_runtime_secs, 0 = unlimited, capped at 7 days) to AutoNudge monitoring loops, alongside the existing max_cycles cap.

Why

A cycle cap alone cannot bound cost: a loop with slow turns or a long idle gap can run for days within its cycle budget. A wall-clock budget gives unattended loops a hard TIME bound ("babysit this for at most 2 hours") regardless of turn duration or idle gap.

How

  • Restart-proof by construction: measured from the persisted created_ts (not arm time), so a gateway restart re-arms the loop without resetting its clock. A store entry with no created_ts never trips (no anchor — guessing one could kill a healthy loop on its first post-upgrade cycle).
  • Enforcement in _timer via a shared runtime_budget_exceeded predicate, checked after the cycle cap (both exhausted → the cap wins) and before the fire, so a spent budget never buys one more unattended turn.
  • Terminal treatment matches the cap: deactivate (inspectable/restartable, not removed) + expired event; _notify_nudge_expired words the user notification per bound using the same predicate — a budget-stopped loop is never mistaken for a manual Stop or a cap-out.
  • Plumbed through every write surface with the same validation as max_cycles:
    • both authz chokepoints (audited in SEL metadata; non-integral input → 400)
    • POST/PATCH /api/autonudge (up-front int coercion)
    • monitor_start/monitor_update MCP tools (MONITOR_*_SCHEMA bounds 0–604800)
    • the session-directive applier, which also refuses a monitor_update whose new budget is at/below the loop's elapsed age (would deactivate without another fire), mirroring its cycle-cap guard
  • WS autonudge_state broadcasts include the new field (additive, backwards-compatible).
  • Spec doc (learn-cron-dashboard.md) updated in the same commit per AGENTS.md.

Tested

  • test_autonudge.py: 80 passed (7 new: predicate contract incl. boundary/no-anchor, spent-budget deactivation+expired+no-extra-fire, unspent fires normally, 0 = unlimited, persistence round-trip of budget AND clock anchor, update semantics/clamping)
  • test_autonudge_stop_auth.py: new MCP pass-through tests + applier spent-budget guard test; existing payload assertion updated for the new field
  • Full sweep over touched surfaces: test_autonudge_dashboard_fire, test_autonudge_remove_offload_425, test_validation, test_session_directive, test_slack_gateway, test_workflows_nudge_wiring (fake svc double extended), spec_builder/tests/test_routes, test_mcp_core*, test_dashboard_chat* — all green (~1,450 tests)
  • flake8 clean on all touched files

Not in scope

Token budgets (needs turn-level accounting) and a Goal-popover UI field for the budget — both follow-ups. The REST/MCP/WS surfaces already expose the field for the UI to adopt.

Why this fits Kiro Crew

TENETS.md #1 puts safety first: "every action is gated, auditable, and reversible." An unattended loop that re-injects turns is the highest-leverage action the system takes without a human present, and today its only bound is a cycle count — which the codebase itself documents as insufficient (_MONITOR_DEFAULT_MAX_CYCLES exists because "observed loop stores show that is unreliable: real babysit loops ran to 24/24 and 20/20 cycles"). A wall-clock bound completes the containment story for the dimension users are actually billed in: time. It changes nothing for anyone who doesn't set it (0 = unlimited, default).

@rubencu
rubencu requested a review from a team August 7, 2026 22:25
@github-actions github-actions Bot added fork Pull request from a fork (external contributor) readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running and removed readiness: action required A blocking check or review needs attention labels Aug 7, 2026
@github-actions

github-actions Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

GPT 5.6 Review (fork) — ✅ no blocking findings

Reviewed be6d0b40011297bf65b2ed5a0d5a10b74be54e8f via the fork AI-review pipeline; updated in place on each push.

Review details

No findings.
[GPT-REVIEWED] be6d0b4

@github-actions

github-actions Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Opus 5 Review (fork) — ✅ no blocking findings

Reviewed be6d0b40011297bf65b2ed5a0d5a10b74be54e8f via the fork AI-review pipeline; updated in place on each push.

Review details

No blocking findings.

FINDING — src/kiro_crew/autonudge_authz.py:62 — added comment carries review-round narration, (GPT review on #2116: REST accepted 604801 unchanged), which AGENTS.md forbids in comments (no PR/CR numbers or review markers); same pattern at src/kiro_crew/dashboard/session_directive_apply.py:227 ((GPT review on #2116: a budget raise must never resume a loop the user paused)) → Fix: drop the parentheticals, keeping the behavioral rationale ("…which do not pass through those schemas." / "…cannot distinguish a pause from an expiry.").

[OPUS-REVIEWED] be6d0b4

@github-actions

github-actions Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Design Review (Fable 5, fork) — ✅ PASS

Advisory design-level review of be6d0b40011297bf65b2ed5a0d5a10b74be54e8f via the fork AI-review pipeline — updated in place on each push; does not block merge.

Design-Verdict: PASS

Sound, restart-proof time bound with symmetric revival semantics; stopped_reason correctly closes the pause-vs-expiry ambiguity wall-clock anchoring would otherwise create.

[DESIGN-REVIEWED] be6d0b4

@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running and removed readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention labels Aug 7, 2026
@rubencu
rubencu force-pushed the feat/autonudge-runtime-budget branch from b95d363 to 170125b Compare August 7, 2026 23:05
@rubencu
rubencu requested a review from a team August 7, 2026 23:05
@rubencu
rubencu force-pushed the feat/autonudge-runtime-budget branch from 170125b to e9a4639 Compare August 7, 2026 23:08
@github-actions github-actions Bot added readiness: checking Automated validation is still running and removed readiness: action required A blocking check or review needs attention labels Aug 7, 2026
@rubencu
rubencu force-pushed the feat/autonudge-runtime-budget branch from e9a4639 to 3c4c355 Compare August 7, 2026 23:45
@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running and removed readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention labels Aug 7, 2026
@github-actions github-actions Bot added the readiness: action required A blocking check or review needs attention label Aug 8, 2026
@rubencu
rubencu force-pushed the feat/autonudge-runtime-budget branch from 3c4c355 to f8f93fe Compare August 8, 2026 00:05
@github-actions github-actions Bot added readiness: checking Automated validation is still running and removed readiness: action required A blocking check or review needs attention labels Aug 8, 2026
@rubencu
rubencu force-pushed the feat/autonudge-runtime-budget branch from f8f93fe to 9a9b22f Compare August 8, 2026 00:30
@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running and removed readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention labels Aug 8, 2026
@rubencu
rubencu force-pushed the feat/autonudge-runtime-budget branch from 9a9b22f to 498a115 Compare August 8, 2026 01:02
@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention and removed readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running labels Aug 8, 2026
…itoring loops

A cycle cap alone cannot bound COST: a loop with slow turns or a long idle
gap can run for days within its cycle budget. This adds an opt-in second
terminal bound - max_runtime_secs (0 = unlimited, schema-capped at 7 days) -
measured from the persisted created_ts so a gateway restart re-arms the loop
without resetting its clock.

- NudgeLoop/add/update carry the budget; _timer enforces it via the shared
  runtime_budget_exceeded predicate, checked after the cycle cap and before
  the fire so a spent budget never buys one more unattended turn
- Terminal treatment matches the cap: deactivate + 'expired' event; the
  notifier words the notification per bound with the same predicate
- Budget-stopped loops are revivable via monitor_update (raise the budget
  above elapsed), and the paused-loop denial names the bound that stopped it
- Plumbed through both authz chokepoints (audited; non-integral or
  overflowing input is 400, incl. 1e309 -> inf), POST/PATCH /api/autonudge,
  monitor_start/monitor_update MCP tools (MONITOR_*_SCHEMA bounds 0-604800),
  and the directive applier's spent-budget guard
@rubencu
rubencu force-pushed the feat/autonudge-runtime-budget branch from 498a115 to be6d0b4 Compare August 8, 2026 03:36
@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: passed Eligible automated validation passed for the current revision and removed readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running labels Aug 8, 2026
@iamwhatever
iamwhatever merged commit 9245c68 into kirodotdev:main Aug 8, 2026
49 checks passed
@github-actions github-actions Bot removed the readiness: passed Eligible automated validation passed for the current revision label Aug 8, 2026
@rubencu
rubencu deleted the feat/autonudge-runtime-budget branch August 8, 2026 10:51
encomjp pushed a commit to encomjp/kirocrew-customapi that referenced this pull request Aug 22, 2026
…itoring loops (kirodotdev#2116)

A cycle cap alone cannot bound COST: a loop with slow turns or a long idle
gap can run for days within its cycle budget. This adds an opt-in second
terminal bound - max_runtime_secs (0 = unlimited, schema-capped at 7 days) -
measured from the persisted created_ts so a gateway restart re-arms the loop
without resetting its clock.

- NudgeLoop/add/update carry the budget; _timer enforces it via the shared
  runtime_budget_exceeded predicate, checked after the cycle cap and before
  the fire so a spent budget never buys one more unattended turn
- Terminal treatment matches the cap: deactivate + 'expired' event; the
  notifier words the notification per bound with the same predicate
- Budget-stopped loops are revivable via monitor_update (raise the budget
  above elapsed), and the paused-loop denial names the bound that stopped it
- Plumbed through both authz chokepoints (audited; non-integral or
  overflowing input is 400, incl. 1e309 -> inf), POST/PATCH /api/autonudge,
  monitor_start/monitor_update MCP tools (MONITOR_*_SCHEMA bounds 0-604800),
  and the directive applier's spent-budget guard
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fork Pull request from a fork (external contributor)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants