Skip to content

fix(cogos-harness): restore usage watermark writer + fix anomaly-kinds truncation - #24

Open
chazmaniandinkle wants to merge 2 commits into
mainfrom
fix/cogos-harness-usage-watermark
Open

fix(cogos-harness): restore usage watermark writer + fix anomaly-kinds truncation#24
chazmaniandinkle wants to merge 2 commits into
mainfrom
fix/cogos-harness-usage-watermark

Conversation

@chazmaniandinkle

Copy link
Copy Markdown
Contributor

Root cause

The cogos-harness plugin migration (#16/#18, landed 2026-08-03) rewrote
user-scope-proprioception.py for portability (CLAUDE_PLUGIN_DATA /
CLAUDE_PLUGIN_ROOT, the session-heartbeat POST). That rewrite dropped the
plan-usage segment and its observatory watermark write -- they only ever
existed in the pre-plugin dotfiles copy
(~/.claude/hooks/user-scope-proprioception.py), which has been unregistered
(no hook wires to it) since the migration. Net effect: the operator's
$COGOS_WORKSPACE/.cog/state/watermarks/claude-usage.json watermark froze at
the migration date and the kernel-vitals probe has been flagging
stale:claude-usage ever since (stale_after=172800s in
kernel-vitals-probe.py's _watermarks()).

What this PR does

Commit 1 ports _official_usage, _session_pct_from_cache,
_weekly_pcts_from_cache, _usage_fields, _usage_seg,
_write_usage_watermark (plus the _read_json_cache_fresh helper and usage
constants) from the orphaned dotfiles copy, verbatim except for the
_DATA_DIR/CLAUDE_PLUGIN_DATA split: the usage caches
(~/.claude/cache/{blocks,weekly,rate_limits}.json) are host-local, not
plugin-scoped, so they stay under Path.home() unconditionally rather than
moving under the plugin's data dir. Wires the segment into the second
proprioception line and the watermark write into the per-turn call path,
matching the pre-migration behavior.

Known limitation, preserved intentionally: the existing
cog-workspace-cwd early-skip is unchanged, so the watermark still will not
refresh from a session whose cwd is inside the cog workspace -- that surface
already gets richer proprioception from the workspace's own
foveated-context.py hook and was out of scope for this port.

Commit 2 fixes an unrelated display bug found while verifying the vitals
line during this work: kernel-vitals-probe.py's _format_line() computed
",".join(anomaly_kinds)[:24], which truncates the joined string, not the
item list -- "degraded,over_budget,quarantined" rendered as
"...degraded,over_budget,qua", a visibly cut-off word. Reproduced live
against the operator's actual .kernel-vitals.json cache content before the
fix. New _join_truncated() stops before any item that would blow the
character budget, so the segment always ends on a whole kind name.

Testing

  • python3 -m py_compile on both edited files.
  • Exercised _usage_fields / _usage_seg / _write_usage_watermark against
    a scratch rate_limits.json / cache dir (redirected off-host, not the
    operator's real cache) through all three paths: official-source,
    estimate-fallback (official absent + no ccusage caches -> empty segment,
    watermark still written with nulls), and the >=80% official-alarm escalation.
    All three produced the expected fields, segment string, and watermark JSON.
  • Exercised _format_line / _join_truncated directly against the exact
    anomaly_kinds list from the operator's live cache
    (["degraded", "over_budget", "quarantined"]); before the fix this renders
    ⚠4anom(degraded,over_budget,qua), after it renders
    ⚠4anom(degraded,over_budget) -- no partial word.

Deployment note

The operator's currently-installed plugin runs from a pinned cache
(~/.claude/plugins/cache/plugins/cogos-harness/0.2.0, gitCommitSha
dabfb36), separate from the marketplace registry clone. Neither is touched
by this PR -- both are deploy artifacts. The fix ships when the plugin is
next updated after this merges. Deployment itself is the operator's call,
not part of this PR.

…prioception

The plugin migration (#18, dabfb36) dropped the plan-usage segment and its
observatory watermark write when user-scope-proprioception.py was rewritten
for portability -- they only ever shipped in the pre-plugin dotfiles copy
(~/.claude/hooks/user-scope-proprioception.py, unregistered since the
migration). Result: $COGOS_WORKSPACE/.cog/state/watermarks/claude-usage.json
stopped advancing and the kernel-vitals probe has been flagging
stale:claude-usage ever since.

Ports _official_usage / _session_pct_from_cache / _weekly_pcts_from_cache /
_usage_fields / _usage_seg / _write_usage_watermark verbatim from the
dotfiles copy (git-clean at 8aa11a6), adapted only to read $HOME/.claude/cache
paths unconditionally (that cache is host-local, not plugin-scoped, so it
does not move under CLAUDE_PLUGIN_DATA the way this hook's other state
does). Wires the segment into the second proprioception line and writes the
watermark once per UserPromptSubmit turn, matching the pre-migration
behavior exactly.

Known limitation (unchanged, preserved intentionally): the existing
cog-workspace-cwd early-skip still applies, so the watermark will not
refresh from a session whose cwd is inside the cog workspace -- that
surface already gets richer proprioception from the workspace's own
foveated-context hook and was out of scope for this port.

Exercised against a scratch cache (official-source, estimate-fallback, and
>=80% alarm paths) with the watermark target redirected off-host; all three
produced the expected fields/segment/watermark JSON.
… mid-word

','.join(kinds)[:24] truncated the JOINED string, not the item list, so
'degraded,over_budget,quarantined' rendered as
'...degraded,over_budget,qua' -- a visibly broken word in the vitals
line. Add _join_truncated() to stop before any item that would blow the
budget, so the segment always ends on a whole kind name (or is empty).

Reproduced against the operator's live .kernel-vitals.json cache content
before the fix (same anomaly_kinds list); confirmed the same input renders
cleanly after.
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.

1 participant