Summary
/session-flow:keep-going tells the model to compare a stated reset time against the
current time, but ships no mechanism to do it. The check is pure arithmetic over a
timestamp, and the model is unreliable at exactly that — so the skill's most consequential
branch depends on the operation least likely to be performed correctly.
Observed in a real session, 2026-07-25. Six subagent lanes died with
You've hit your session limit · resets 2:30am (America/New_York). The skill was invoked
at 10:25 ET — the limit had been over for eight hours. I read the failure reason,
classified every lane as dead, wrote a recovery report, and declared the session settled
without ever comparing 2:30am to the clock. The operator had to point out the limit was
long expired. Six lanes stayed dead that could have been restarted immediately.
The skill's own text is not at fault — it states the rule plainly under "After a usage
limit lifts — GO, don't summarize":
when step 2 inspects a worker or subagent that is itself limited, compare the current
time against the reset its limit message states, to decide whether that worker can
proceed now
That is correct guidance. It was simply not followed, and nothing in the skill made not
following it visible.
Why this is a skill gap and not only operator error
The primary cause was my error. The gap is that the skill makes a deterministic check
into a judgment call.
Writing the check as a script surfaced three bugs that unaided reasoning had glossed over:
ZoneInfo("America/New_York") raises on Windows CPython — no bundled tz database.
Every real message carries a zone in that form, so a naive implementation fails on the
only input shape that occurs.
- "Most recent occurrence at or before now" is wrong. At 02:00 with a 2:30am reset it
resolves to yesterday 2:30am and reports CLEAR — a still-active limit read as over.
- Tomorrow's occurrence is easy to miss entirely. At 22:00 with a 2:00am reset, the
answer is four hours ahead, not twenty hours behind.
A bare clock time names two instants. Picking one by intuition is a coin flip, and both
failure directions are real: reading a passed reset as pending strands live work; reading
a pending reset as passed re-fires straight into the limit.
What is and is not available
Verified on Claude Code 2.1.219, Windows:
claude --help exposes no usage, limit, quota, or rate flag.
- No
limit/reset/quota environment variable is set.
- Grepping
~/.claude/*.json for resets|rate_?limit|rateLimit returns nothing.
So the skill's claim is accurate — reset time is available only in the message text and the
interactive /usage view. The retrieval cannot be scripted. The comparison can.
Proposed fix
Ship a small checker with the skill and cite it at the decision point, replacing "compare
the current time" with a command to run. Reference implementation, tested against seven
cases including all three bugs above:
$ limit-reset-check.py "You've hit your session limit · resets 2:30am (America/New_York)"
CLEAR: reset passed 7h55m ago. reset 2026-07-25 02:30 | now 2026-07-25 10:25
$ echo $?
0
Exit 0 = reset passed, resume. 1 = still blocked, hand back per the skill's
still-blocked branch. 2 = no reset parsed — treat as blocked and verify by hand, never
as clear.
Resolution is fail-closed against the 5-hour rolling window: a bare time landing within
5h ahead is read as the pending reset; anything further ahead is read as already passed.
Local implementation at ~/.claude/scripts/limit-reset-check.py if useful as a starting
point; it needs a decision on where a skill-shipped script belongs and how it is invoked
on a machine without the tz database.
Secondary observation, lower confidence
Reported here rather than filed separately, since it shares a root cause with the above and
I have one session's evidence rather than a pattern.
Across this session, five subagents went idle without delivering their reports — they
wrote findings as plain text instead of calling SendMessage, so nothing arrived. Each
needed an explicit follow-up request to resend. In one case a full adversarial review was
nearly lost.
Both this and the reset gap are the same shape: a step stated as prose guidance that
depends on the model choosing to do it, with no mechanism and no signal when it is skipped.
Whether that belongs in this skill, a subagent-brief template, or neither is a judgment for
whoever owns the loop-lane contract.
Related
No linked issue.
- Skill:
session-flow 0.15.0, skills/keep-going
- Section: "After a usage limit lifts — GO, don't summarize"
Summary
/session-flow:keep-goingtells the model to compare a stated reset time against thecurrent time, but ships no mechanism to do it. The check is pure arithmetic over a
timestamp, and the model is unreliable at exactly that — so the skill's most consequential
branch depends on the operation least likely to be performed correctly.
Observed in a real session, 2026-07-25. Six subagent lanes died with
You've hit your session limit · resets 2:30am (America/New_York). The skill was invokedat 10:25 ET — the limit had been over for eight hours. I read the failure reason,
classified every lane as dead, wrote a recovery report, and declared the session settled
without ever comparing
2:30amto the clock. The operator had to point out the limit waslong expired. Six lanes stayed dead that could have been restarted immediately.
The skill's own text is not at fault — it states the rule plainly under "After a usage
limit lifts — GO, don't summarize":
That is correct guidance. It was simply not followed, and nothing in the skill made not
following it visible.
Why this is a skill gap and not only operator error
The primary cause was my error. The gap is that the skill makes a deterministic check
into a judgment call.
Writing the check as a script surfaced three bugs that unaided reasoning had glossed over:
ZoneInfo("America/New_York")raises on Windows CPython — no bundled tz database.Every real message carries a zone in that form, so a naive implementation fails on the
only input shape that occurs.
resolves to yesterday 2:30am and reports CLEAR — a still-active limit read as over.
answer is four hours ahead, not twenty hours behind.
A bare clock time names two instants. Picking one by intuition is a coin flip, and both
failure directions are real: reading a passed reset as pending strands live work; reading
a pending reset as passed re-fires straight into the limit.
What is and is not available
Verified on Claude Code 2.1.219, Windows:
claude --helpexposes no usage, limit, quota, or rate flag.limit/reset/quotaenvironment variable is set.~/.claude/*.jsonforresets|rate_?limit|rateLimitreturns nothing.So the skill's claim is accurate — reset time is available only in the message text and the
interactive
/usageview. The retrieval cannot be scripted. The comparison can.Proposed fix
Ship a small checker with the skill and cite it at the decision point, replacing "compare
the current time" with a command to run. Reference implementation, tested against seven
cases including all three bugs above:
Exit
0= reset passed, resume.1= still blocked, hand back per the skill'sstill-blocked branch.
2= no reset parsed — treat as blocked and verify by hand, neveras clear.
Resolution is fail-closed against the 5-hour rolling window: a bare time landing within
5h ahead is read as the pending reset; anything further ahead is read as already passed.
Local implementation at
~/.claude/scripts/limit-reset-check.pyif useful as a startingpoint; it needs a decision on where a skill-shipped script belongs and how it is invoked
on a machine without the tz database.
Secondary observation, lower confidence
Reported here rather than filed separately, since it shares a root cause with the above and
I have one session's evidence rather than a pattern.
Across this session, five subagents went idle without delivering their reports — they
wrote findings as plain text instead of calling
SendMessage, so nothing arrived. Eachneeded an explicit follow-up request to resend. In one case a full adversarial review was
nearly lost.
Both this and the reset gap are the same shape: a step stated as prose guidance that
depends on the model choosing to do it, with no mechanism and no signal when it is skipped.
Whether that belongs in this skill, a subagent-brief template, or neither is a judgment for
whoever owns the loop-lane contract.
Related
No linked issue.
session-flow0.15.0,skills/keep-going