Add /graph G2: resumable budget, GraphUpdated status chip, PTY + turn-level coverage
BudgetLimited is now a resumable state: a budget trip demotes in-flight
nodes to Ready (a resource stop, not a verdict — no forever-Running node is
ever persisted) and '/graph resume --budget <tokens>' re-arms the graph with
fresh headroom (new budget = spent-so-far + extra). The tripped node's
partial burn is charged into tokens_spent_nodes at BOTH cascade sites before
the demotion clears current_node, so the top-up arithmetic never runs on an
under-counted ledger. Any input starting with 'resume' resolves to a resume
(case-insensitive; malformed top-ups surface the usage hint) and setup_graph
refuses to replace any non-Complete graph — a typo can no longer silently
destroy a resumable graph. An explicit --budget on a merely-paused graph is
rejected loudly instead of silently discarded; all trip-time messages now
advertise the top-up.
The pager gains a graph status chip: a new GraphUpdated wire variant
(extensions/notification.rs, old pagers degrade via #[serde(other)]) is
emitted from the single persist_graph_state chokepoint — every transition is
both a checkpoint and a badge tick — with a 'cleared' sentinel on /graph
clear and a one-shot re-emit after session restore (the replayed updates log
otherwise shows the pre-shutdown Active state that from_snapshot just
demoted in memory). TUI side: GraphDisplayState, session-notification arm,
and a goal-idiom chip with node progress, clamped current-node title, and
budget-aware spend. Pre-session command availability now advertises /graph
from the flags (it was fail-closed to the in-session path only, so the
welcome-screen slash menu never showed it).
Coverage: GraphUpdated wire round-trip + minimal-payload + unknown-tag
tests; PTY scenarios graph_slash_presession{,_disabled}.yaml (both run
green against the real pager binary); handle_prompt-level e2e for terminal
slash outcomes (/graph status|resume|pause, /goal refusals while the graph
owns the engine); budget top-up e2e driving a BudgetLimited diamond back to
Complete. Not shimmed: pre-G2 persisted snapshots with budget-Failed nodes
(the KIGI_GRAPH flag has never shipped enabled, so none exist).
kigi-shell 4927 and kigi-tui 6610 lib tests green; workspace clippy clean.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
name: graph-slash-presession
|
||||
description: >
|
||||
With the graph feature flag on (`KIGI_GRAPH=1`, plus `KIGI_GOAL=1` — the
|
||||
graph gate requires the goal harness), `/graph` must appear in the
|
||||
slash-command menu on the welcome screen *before* the first user turn
|
||||
creates a session. Typing `/graph` pre-session must surface the command
|
||||
and its description in the dropdown.
|
||||
terminal:
|
||||
rows: 40
|
||||
cols: 100
|
||||
environment:
|
||||
env:
|
||||
- key: KIGI_GOAL
|
||||
value: "1"
|
||||
- key: KIGI_GRAPH
|
||||
value: "1"
|
||||
mock:
|
||||
response: "unused — this scenario never submits a prompt."
|
||||
steps:
|
||||
- action: wait_for_text
|
||||
text: Quit
|
||||
timeout_ms: 20000
|
||||
- action: assert_not_contains
|
||||
text: panicked
|
||||
# Sanity: nothing has been submitted yet, so no session exists.
|
||||
- action: assert_not_contains
|
||||
text: dependency graph
|
||||
- action: focus_prompt
|
||||
- action: type_text
|
||||
text: "/graph"
|
||||
- action: wait
|
||||
millis: 300
|
||||
# The dropdown row carries the builtin's description, which only renders
|
||||
# when /graph is actually advertised pre-session.
|
||||
- action: assert_contains
|
||||
text: dependency graph
|
||||
- action: assert_running
|
||||
- action: screenshot
|
||||
name: graph-in-slash-menu-presession
|
||||
note: "/graph advertised in the slash menu on the welcome screen (KIGI_GRAPH=1), before any prompt."
|
||||
@@ -0,0 +1,45 @@
|
||||
name: graph-slash-presession-disabled
|
||||
description: >
|
||||
Fail-closed counterpart: with `KIGI_GRAPH=0` (goal harness still on),
|
||||
`/graph` must NOT appear in the pre-session slash menu, while the menu
|
||||
itself keeps working for other commands.
|
||||
terminal:
|
||||
rows: 40
|
||||
cols: 100
|
||||
environment:
|
||||
env:
|
||||
- key: KIGI_GOAL
|
||||
value: "1"
|
||||
- key: KIGI_GRAPH
|
||||
value: "0"
|
||||
mock:
|
||||
response: "unused — this scenario never submits a prompt."
|
||||
steps:
|
||||
- action: wait_for_text
|
||||
text: Quit
|
||||
timeout_ms: 20000
|
||||
- action: assert_not_contains
|
||||
text: panicked
|
||||
- action: focus_prompt
|
||||
- action: type_text
|
||||
text: "/graph"
|
||||
- action: wait
|
||||
millis: 300
|
||||
- action: assert_not_contains
|
||||
text: dependency graph
|
||||
- action: assert_running
|
||||
- action: screenshot
|
||||
name: graph-absent-from-slash-menu
|
||||
note: "/graph hidden with KIGI_GRAPH=0 (fail-closed gate)."
|
||||
# The menu itself still works: clear "/graph" (6 chars) and try /compact.
|
||||
- action: keys
|
||||
keys: "<BS><BS><BS><BS><BS><BS>"
|
||||
- action: type_text
|
||||
text: "/compact"
|
||||
- action: wait
|
||||
millis: 300
|
||||
- action: assert_contains
|
||||
text: Compact conversation history
|
||||
- action: screenshot
|
||||
name: slash-menu-still-works
|
||||
note: "Slash menu functional; only /graph is gated off."
|
||||
Reference in New Issue
Block a user