Remove the redundant JSON-RPC initialize fallback from the consolidated MCP health-check batch. A routed 404 already proves the endpoint is reachable, and the real authenticated MCP call remains authoritative. Avoiding the fallback also prevents a stalled GET plus stalled POST from consuming twice the configured hook timeout.
Prevent stale /tmp/harness-cost cache files from affecting Sonnet 5, dated,
near-miss, and cache-rate pricing tests by using Date.now() in each session ID.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The mcp-health-check preflight probes HTTP MCP servers with a bare GET.
Some Streamable HTTP servers route only POST /mcp and answer a bare GET
with 404 (Paper Desktop 0.5.3 is one). The probe scored that as down and
blocked every tool call for the server indefinitely, since the 30s
backoff just re-probes and re-fails.
A routed HTTP response of any status proves the endpoint is reachable,
which is all this preflight claims to check -- 400/401/403/405/406 are
already treated this way for the same reason. Add 404 to the set and let
the real MCP client validate the endpoint.
Adds a regression test that stands up a POST-only server (404 on GET,
200 on POST /mcp); it fails on the current code and passes with the fix.
The preflight probe in mcp-health-check only ever sent a bare GET to the
server URL. Some Streamable HTTP MCP servers route POST exclusively and
answer any GET with 404 — api.telnyx.com/v2/mcp is one — so the probe
failed permanently against a perfectly healthy server.
404 is not in HEALTHY_HTTP_CODES, so every probe failed, the backoff
compounded to the 10-minute ceiling, and the hook blocked every tool call
for that server before it left the machine while `claude mcp list` still
reported it Connected.
Replay a failed GET as a real JSON-RPC initialize POST and accept that as
proof of life. Whitelisting 404 was the alternative, but it would mask
genuine outages on every other server.
Adds a regression test with a POST-only server that 404s all GETs and
validates the initialize body; it fails without this change.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
cost-estimate.js carries its own copy of the stale Opus/Haiku/Sonnet rate
table already reported in #2574, but grepping every .js/.json/.md file
outside node_modules turns up zero callers besides its own test. It was
added in 940135e alongside the statusline observability hooks and never
wired into any of them.
The maintainer's comment on #2656 named two acceptable outcomes: remove
the unused duplicate, or share one rate source with the live tracker.
cost-tracker.js's own fix (#2574) has not landed yet, so sharing its
table now would import numbers that are still wrong. Removing the dead
file is the smaller, immediately-correct step.
Fixes#2656
Artifacts written by `evolve --generate` are inert: Claude Code (and every
spec-compliant Agent Skills client) injects only `name` + `description` at
startup and will not load an artifact missing them.
Today the generator writes:
- skills: `# {name}` with no frontmatter block at all
- commands: `# {cmd_name}` with no frontmatter block at all
- agents: `model`/`tools` only, no `name`, no `description`
So the whole evolve pipeline terminates in files that can never load. I hit
this on a real install: 12 generated artifacts across two projects, none of
which Claude Code had ever seen.
This adds a `_evolved_description()` helper and emits proper frontmatter for
all three artifact kinds. The description is sanitised for the two things that
break loaders: `: ` in an unquoted scalar (rejected by strict YAML parsers)
and `<`/`>` (system-prompt injection risk).
Adds two tests to tests/scripts/instinct-cli-evolve-generate.test.js. Both
fail against current main and pass with this change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>