Skip to content

chore(models): refresh stale model defaults (NodeAgent) - #15

Merged
HomenShum merged 13 commits into
mainfrom
claude/model-refresh-nodeagent
Oct 16, 2026
Merged

HomenShum merged 13 commits into
mainfrom
claude/model-refresh-nodeagent

Conversation

@HomenShum

@HomenShum HomenShum commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Summary

Refreshes stale model defaults in the live provider smoke and fixes the request shapes the new ids require.

Runtime sites (9: migrate 4, freeze 5, defer 0)

Line numbers in the two tables below are SPEC/inventory coordinates on origin/main (SPEC-v3 §A.2.3), so a reviewer can match them to the plan. Where the code now sits at head f7963e2: frozen chain scripts/nodeagent-live-provider-smoke.ts:68-71 (nex-agi/nex-n2-pro deleted), defaults :212 (openai) / :214 (anthropic) / :216 (gemini), env-chain resolver selectModelCandidates :202-210, openAiCompatibleChat :400.

Site Today Disposition Target / reason
scripts/nodeagent-live-provider-smoke.ts:34 z-ai/glm-5.2 freeze active on OpenRouter, no vendor-named successor; chain order is a cost decision -> Part B v2
:35 moonshotai/kimi-k2.7-code freeze same
:36 cohere/north-mini-code:free freeze same
:37 nvidia/nemotron-3-ultra-550b-a55b freeze same
:38 nex-agi/nex-n2-pro migrate (delete) absent from OpenRouter catalog 2026-10-10; also removed from .env.example:29 and README.md:172-176
:177 gpt-5.5 migrate gpt-6.1-sol
:179 claude-3-5-haiku-latest migrate claude-haiku-5-5 (retired 2026-02-19)
:181 gemini-2.0-flash migrate gemini-3.8-flash (shut down 2026-06-01)
nodekit.yaml:57 none freeze conformance mapping, no model

E / R sites (5: migrate 1, freeze 3, defer 1)

Site Class Disposition Reason
smoke.ts:173 env-chain resolver E freeze literals dispositioned above; order NODEAGENT_OPENROUTER_MODEL_PRIORITY ?? NODEAGENT_OPENROUTER_MODEL ?? const unchanged
smoke.ts:248 openAiCompatibleChat E migrate request shape fixed once here for OpenRouter and OpenAI
src/features/node-agent/providers/piAiAdapter.ts:34 E freeze provider + model are caller options
src/features/node-agent/protocol/model.ts:60 R freeze optional pass-through, no caller sets them
package.json:100 pi-ai pin R defer untouched; bump is a human change when a live line is wired

Class N (doc 4, example 2, other 2, test-assertion 1): docs loop = README.md default-priority sentence and .env.example chain only; no other doc/evidence file names a moved id (evidence trees are hash-bound, untouched).

Breaking-parameter fixes

  • temperature: 0 removed from OpenAI-compatible, Anthropic and Gemini bodies (400 on Haiku 5.5, removed on GPT-6, deprecated on Gemini 3.6+).
  • 16-token caps -> 256 (SMOKE_MAX_TOKENS) at all three sites (thinking counts toward the cap).
  • OpenAI branch: max_completion_tokens + reasoning_effort: "low", no temperature, no tools. OpenRouter branch keeps max_tokens, no temperature.
  • Anthropic reply text now read by content block type === "text"; a stop_reason: "refusal" response now throws provider_refusal before content is read (migration guide Haiku 5.5 checklist, [BLOCKS]).

Test proof

tests/liveProviderSmokeRequestShape.test.ts (20 cases: 6 request-shape incl. an Anthropic stop_reason: "refusal" regression, 14 receipt; the request-shape cases also assert the SPEC §1.3 forbidden keys absent: Gemini thinkingConfig.thinkingBudget/thinking_budget/candidateCount/candidate_count, OpenAI logprobs/top_logprobs. Each assertion observed to fail against a mutant that adds the key to the builder, mutant reverted) drives the script's own callProvider / selectModelCandidates / probeLlm / gitIdentity / receiptIdentity with a fake fetch. The git-identity cases run against a throwaway temp git repo, so the suite passes on a dirty or untracked working tree (verified with an untracked file in the checkout).

  • Fail-before evidence, re-measured at head f7963e2 in an isolated worktree: all 14 per-site mutants are killed by tests/liveProviderSmokeRequestShape.test.ts. Mutants: each of the three literals reverted (gpt-5.5, claude-3-5-haiku-latest, gemini-2.0-flash); nex-agi/nex-n2-pro re-added; temperature: 0 re-added to the Anthropic, OpenAI-compatible and Gemini bodies; cap set back to 16; OpenAI max_tokens instead of max_completion_tokens; tools added; thinking: {type: "disabled"}; an assistant prefill; text no longer filtered by block type; refusal check removed. Swapping in origin/main's whole script gives 20 of 20 failing, mostly because origin/main has no exports.

  • Round-5 fixes, each observed to fail without its fix: (a) gitDirty case: the probe was *.tmp, ignored by .gitignore:44, so git never saw it and the case passed only on an already-dirty tree. The case now runs against an isolated temp git repo (makeRepo(), probe file probe.txt, no dependence on the working tree), asserting a clean tree, then that docs/eval output is ignored, then that an untracked root file gives gitDirty: true from both the repo root and docs/. With the :(top) anchors replaced by . the case fails with expected [ true, false ] to deeply equal [ true, true ]. (b) A successful reply costing 0.11 against maxUsd 0.10 now sets stoppedBy: "maxUsd"; (c) the receipt command quotes whitespace args. Against the previous head's script (3044810), (b) and (c) fail (2 failed | 13 passed).

  • Round-6 fixes: (a) budget.stoppedBy now compares the known (non-null) spend to maxUsd even when another row reported no cost; a retry after an HTTP 503 followed by a 0.11 reply stops the run (spentUsd stays null, stoppedBy: "maxUsd"; the test fails when the old spentUsd !== null guard is restored). (b) gitIdentity(cwd) replaces the git calls inside receiptIdentity; the gitDirty case uses a temp repo, so npm test / npm run check no longer depend on the state of the working tree. (c) main() captures testedCommit, gitDirty, constantSha256 before the first paid dispatch, so a non-git directory fails before any spend and a checkout change mid-run cannot misattribute the run. (d) The receipt command is POSIX shell-quoted (;, empty and ' arguments replay). (e) A missing provider key is detected before a request is counted: requests: 0, no row.

  • Round-7 fixes: (a) gitIdentity passes --untracked-files=all; the test sets status.showUntrackedFiles=no in the fixture and still expects gitDirty: true (fails without the flag). (b) The gitIdentity test now asserts gitDirty === false from the repo root and from docs/ after docs/eval/receipt.json is written and before the root probe (fails with a cwd-relative :(exclude)docs/eval), and asserts constantSha256 equals the sha256 of the committed blob. (c) The non-git test is retitled gitIdentity throws outside a git checkout; the call-before-dispatch ordering in main() is not covered by a test and is not claimed to be.

Check output (npm run prepush, the repo's declared check)

Branch rebased onto origin/main a918e85 (0 behind, 12 ahead). Re-run 2026-10-15 on a clean tree at head f7963e2 (git status clean before the run; no provider keys in the environment). npm run prepush exit 0: 12 test files, 137/137 tests, live smoke SKIP, build ok, 0 vulnerabilities. The request-shape file alone (npx vitest run tests/liveProviderSmokeRequestShape.test.ts): 20/20. The log is local to the author's machine and not part of the PR, so the output below is the evidence (counts quoted for earlier heads no longer apply): Re-run again 2026-10-16 at the same head f7963e2 (clean tree, provider keys unset; one earlier attempt under machine load hit 2 timeout failures in the cancellation tests and passed 137/137 on re-run): npm run prepush exit 0, 12 files, 137/137, live smoke SKIP, 0 vulnerabilities; request-shape file 20/20; the four docs/eval/*.json files restored.

nodeagent live provider smoke: SKIP no provider key configured
...
 Test Files  12 passed (12)
      Tests  137 passed (137)
...
found 0 vulnerabilities
exit=0

prepush rewrites four docs/eval/*.json smoke outputs; those were restored (not committed). No paid provider calls were made.

Notes

  • D2 scope: settled by D2a (SPEC-v3.md:6). D2 (SPEC-v3.md:5) chooses the target only for OpenRouter-routed roles that this refresh moves under A.0 rule 1; D2a states that frozen paid OpenRouter routes with no vendor-named successor, such as z-ai/glm-5.2, stay frozen. So the frozen paid chain (z-ai/glm-5.2 first, at scripts/nodeagent-live-provider-smoke.ts:68, mirrored in .env.example:29 and README.md:172-174) is unchanged and only the dead nex-agi/nex-n2-pro entry is deleted. The sibling PRs apply the same rule (NodeRoom#261 and NodeSlide#203 keep z-ai/glm-5.2; NodeBenchAI#662 and parity-studio#101 keep kimi-k2.6). No decision is pending here; a broader "every OpenRouter role goes :free" reading would be a follow-up PR per D2a.

  • .env.example:29 is uncommented, so anyone who copied it keeps the old list including nex-agi/nex-n2-pro; they should re-copy or remove that entry.

  • needs-live-eval (block, not a note): merge waits for the three native keyed receipts below, taken at f7963e2 or a later commit (rule 3: testedCommit must be that commit or a descendant). The bare npm run nodeagent:live-provider:smoke is NOT sufficient: selectProvider picks the first keyed provider (openrouter, openai, anthropic, gemini), so on a machine with OPENROUTER_API_KEY it only tests the frozen chain, and the npm script hard-codes one --json-out. Required runs (all three before the label is removed; run each separately, attach each output):

    • npx tsx scripts/nodeagent-live-provider-smoke.ts --provider openai --model gpt-6.1-sol --json-out docs/eval/nodeagent-live-provider-smoke-openai.json (gpt-6.1-sol)
    • npx tsx scripts/nodeagent-live-provider-smoke.ts --provider anthropic --model claude-haiku-5-5 --json-out docs/eval/nodeagent-live-provider-smoke-anthropic.json (claude-haiku-5-5)
    • npx tsx scripts/nodeagent-live-provider-smoke.ts --provider gemini --model gemini-3.8-flash --json-out docs/eval/nodeagent-live-provider-smoke-gemini.json (gemini-3.8-flash)

    OpenRouter role (the nex-agi/nex-n2-pro deletion and the frozen chain): live-unverified (no key, Homen 2026-10-16). Per decision D2 (SPEC-v3.md:5) no working OpenRouter key exists (the local one returns 401 "User not found"), the role carries this marking, and merge is allowed with it; the OpenRouter run is not a merge condition. Public-list evidence instead, fetched without a key at 2026-10-16T10:00:05Z (GET https://openrouter.ai/api/v1/models, 465 rows, snapshot _scratch/or_models_2026-10-16.json in the model-defaults workspace, not in this repo): nex-agi/nex-n2-pro is absent; z-ai/glm-5.2, moonshotai/kimi-k2.7-code, cohere/north-mini-code:free and nvidia/nemotron-3-ultra-550b-a55b are all listed with no expiration_date, so the frozen chain stays as is. Optional, only when a working key exists: npx tsx scripts/nodeagent-live-provider-smoke.ts --provider openrouter --json-out docs/eval/nodeagent-live-provider-smoke-openrouter.json.

    --model is pinned on the three direct-provider runs because loadEnvFiles loads NODEAGENT_LIVE_MODEL and NODEAGENT_<PROVIDER>_MODEL from .env.local and selectModelCandidates honours them, so a stale override there would silently test another model (the receipt would be rejected under rule 3, but the paid run is wasted). The optional OpenRouter run is unpinned (no --model), and selectModelCandidates (scripts/nodeagent-live-provider-smoke.ts:205) checks NODEAGENT_LIVE_MODEL first, then NODEAGENT_OPENROUTER_MODEL_PRIORITY, then NODEAGENT_OPENROUTER_MODEL; any of the three replaces the frozen chain, and loadEnvFiles does not override variables already in the process env. Before that run (optional, see above), unset all three in the shell (unset NODEAGENT_LIVE_MODEL NODEAGENT_OPENROUTER_MODEL_PRIORITY NODEAGENT_OPENROUTER_MODEL) and remove them from .env.local and .env; after the run, check that the receipt's candidateIds equals the four-entry frozen chain (z-ai/glm-5.2, moonshotai/kimi-k2.7-code, cohere/north-mini-code:free, nvidia/nemotron-3-ultra-550b-a55b), otherwise the receipt is rejected under rule 3 and the run is wasted. Risk the keyed receipt may surface: Haiku 5.5 (adaptive thinking, medium effort by default) and gemini-3.8-flash (default thinking) count thinking tokens toward the spec's 256-token cap, so a reply could end in max_tokens with no text and the smoke would fail closed (expected NODEAGENT_LIVE_OK); the migration guide's lever then is effort low or a larger cap.

    Estimated cost: a few cents total for the three required runs (one ~30-token reply each). The optional OpenRouter run adds up to 4 attempts. Not run here (no paid calls).

  • Receipt schema (§A.0 rule 3) — fixed in this PR. The smoke report now carries command (POSIX shell-quoted, so semicolons, empty and spaced arguments replay), candidateIds, echoedModels, rows[{requestedModel, resolvedModel, echoedModel, usage, costUsd, fallbackUsed}], testedCommit (git rev-parse HEAD), gitDirty (top-anchored pathspecs and an explicit --untracked-files=all, so it is the same from any working directory and independent of the user's status.showUntrackedFiles; ignores docs/eval, the evidence directory), constantSha256 (this script as committed at testedCommit, read once from a single git rev-parse HEAD; recompute with git show <testedCommit>:scripts/nodeagent-live-provider-smoke.ts | sha256sum), budget{maxUsd, estimateUsd, spentUsd|null, requests, stoppedBy} and environment. echoedModel is the response model (Anthropic/OpenAI/OpenRouter) or modelVersion (Gemini); fallbackUsed is true when the OpenRouter chain moves past index 0; a budget stop (including a reply whose reported cost exceeds maxUsd, even when an earlier attempt reported no cost) sets ok: false. The git identity is read before the first dispatch. No model site, precedence or frozen site changed. Runtime behaviour does change in the smoke: the OpenRouter chain stops when committed spend (the reported cost, or the $0.01 estimate only where a row reports none) plus one more $0.01 estimate would exceed maxUsd $0.10; the cap is in dollars, not attempts, so cheap failed replies that report a small cost can run more than 10 attempts, and a budget stop fails the run (ok: false, exit 1). Fake-fetch tests assert a differing echoed model is recorded. Limits: costUsd is only filled where the provider reports it (OpenRouter usage.cost), otherwise null, and then budget.spentUsd is null (unknown), never 0. Before each dispatch the smoke requires committed spend (reported cost, or the $0.01 estimate for an unreported row) plus one more estimate to stay within maxUsd, so the cap holds for direct providers too. estimateUsd is a flat $0.01 per request, not a price table: it bounds the built-in and frozen ids (gpt-6.1-sol at 256 output tokens is about $0.0026), but an operator-supplied NODEAGENT_OPENROUTER_MODEL_PRIORITY of pricier ids can overshoot maxUsd by up to one request; such a run ends stoppedBy: "maxUsd", ok: false, so it is flagged, not silent. A refused Anthropic row records echoedModel and usage before the run fails. Merge waits for the three native keyed runs (not run here, no paid calls; OpenRouter is live-unverified per D2); a receipt with a fallback row, gitDirty, or stoppedBy is rejected and re-run.

  • Resolved by D1 (Homen 2026-10-16): --model / NODEAGENT_LIVE_MODEL / NODEAGENT_*_MODEL stay pass-through; every built-in default is a §1.2 id or a known frozen chain id.

  • Round-8 fixes (b2d3fd3): smoke budget wording no longer claims a hard bound; receipt command records npx tsx ... (replays verbatim); the git-spawning tests have a 30 s timeout (assertions unchanged); the not-a-repo test asserts /not a git repository/i.

  • Round-10 fix (429ba6c): gitIdentity read git rev-parse HEAD and then hashed git show HEAD:<script> in a separate call, so a checkout between the two would give a receipt naming commit A with commit B's hash. It now reads HEAD once and hashes <testedCommit>:<script>. A request-shape test moves HEAD between the two calls (via a pass-through node:child_process hook) and asserts the hash is the captured commit's blob; reverting the fix to HEAD: fails it. The PR-body changes in this round: --model on the keyed commands, the stale-override and thinking-token notes, and the mixed-list sentence. In the verifying prepush run, the first attempt had one 5000 ms timeout in the untouched tests/nodeAgentChatAdapter.test.ts (a load flake, 136/137); the immediate re-run was 137/137, exit 0.

  • Round-11 fixes (f7963e2, after rebase onto a918e85): the request-shape test now asserts the SPEC §1.3 forbidden keys absent (defect: a mutant adding thinkingConfig: { thinkingBudget: 0 }, candidateCount: 1 to the Gemini generationConfig passed 20/20; it now fails, as does a logprobs: true mutant on the OpenAI body). The keyed receipts must be taken at head f7963e2 or later so testedCommit is an ancestor of the PR head (rule 3); a receipt taken at the pre-rebase 8b12bea is not.

  • Round-9 fixes (2a0faa8): the end-of-request budget check now counts a row with no reported cost at the $0.01 estimate, the same accounting as the pre-dispatch reservation. Before, a 503 with no cost followed by a $0.095 reply (estimate total $0.105 vs maxUsd $0.10) ended ok: true, stoppedBy: null; now it ends stoppedBy: "maxUsd" while spentUsd stays null (a row is unknown). The new fake-fetch case fails against the previous script and passes now.

Spec: model-defaults SPEC Part A §A.2 (NodeAgent)

🤖 Generated with Claude Code

@HomenShum

Copy link
Copy Markdown
Owner Author

Live-eval attempt on f8d6f9a6b251a8c055dbe8a65db547bfaf53cffb (branch claude/model-refresh-nodeagent, clean tree): not run, no receipt produced.

Reason: no provider key was available on the machine that ran this. OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY and OPENROUTER_API_KEY are unset in the process, user and machine environments, and the repo has no .env or .env.local (only .env.example). Spend: $0.00, 0 requests.

Result: passed = false. The changed roles (gpt-6.1-sol, claude-haiku-5-5, gemini-3.8-flash) are unverified live. The merge block stays: this PR still needs a receipt from a keyed machine. The needs-live-eval label does not exist in this repo, so the block is stated here and in the PR body only.

To produce the receipt (budget cap $1.5, one call per role), run once per role with the matching key set, e.g.
npx tsx scripts/nodeagent-live-provider-smoke.ts --provider openai --json-out docs/eval/nodeagent-live-provider-smoke.json
and likewise --provider anthropic and --provider gemini. Note the script writes one provider per report and does not record echoedModel/usage/cost, so the per-role reports need combining into the spec section A.0 rule 3 receipt shape.

@HomenShum
HomenShum force-pushed the claude/model-refresh-nodeagent branch from f8d6f9a to 5a8ab49 Compare October 14, 2026 18:37
HomenShum and others added 12 commits October 15, 2026 16:39
Live provider smoke defaults move off retired/shut-down ids and the
request shapes are fixed for the new targets (SPEC Part A §A.2 NodeAgent).

- gpt-5.5 -> gpt-6.1-sol, claude-3-5-haiku-latest -> claude-haiku-5-5,
  gemini-2.0-flash -> gemini-3.8-flash
- delete nex-agi/nex-n2-pro (absent from OpenRouter catalog 2026-10-10)
  from the priority list, .env.example and README
- drop temperature (400 on Haiku 5.5, removed on GPT-6, deprecated on
  Gemini 3.6+); 16-token caps -> 256; OpenAI branch sends
  max_completion_tokens + reasoning_effort low; Anthropic text read by type
- add request-shape test (fake fetch) for all four providers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…read

- clear NODEAGENT_*_MODEL overrides in beforeEach so a host-exported
  override no longer fails the default-resolution assertions
- give the non-text fixture block a text field and assert it is excluded,
  so reverting the type filter in the Anthropic parser now fails the test

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ression test

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ider smoke

The smoke report recorded only the requested model, so none of the four
keyed runs could produce a receipt review would accept. Add the rule 3
fields; no model site, precedence or request shape changes.

- builders keep the response `model` (Gemini `modelVersion`) and usage;
  OpenRouter `usage.cost` is recorded as costUsd, null elsewhere
- rows[{requestedModel, resolvedModel, echoedModel, usage, costUsd,
  fallbackUsed}], candidateIds, echoedModels, command, environment
- testedCommit (git rev-parse HEAD), gitDirty (ignores docs/eval),
  constantSha256 (this file at HEAD), budget with maxUsd stop
- fake-fetch tests: echoed model differs from requested and is recorded;
  fallbackUsed set when the OpenRouter chain moves past index 0

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…efusal row metadata

spentUsd is null when any dispatched row has no reported cost (direct OpenAI,
Anthropic, Gemini); the maxUsd guard reserves the per-request estimate before
dispatch. gitDirty uses top-anchored pathspecs so it no longer depends on the
caller's cwd. A refused Anthropic row now records echoedModel and usage.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…replies; quote receipt command

The gitDirty probe was named *.tmp, which .gitignore:44 ignores, so git status
never saw it and the test only passed on an already-dirty tree. The probe is
now gitdirty-probe.txt, asserted not ignored, with a clean-tree precondition.
A successful reply costing more than maxUsd now sets stoppedBy=maxUsd. The
receipt command quotes whitespace arguments so it can be replayed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…command, request accounting

An unreported-cost row no longer hides an over-budget reply: the known spend is
compared to maxUsd even when spentUsd is null (retry after a 503, then a $0.11
reply, now sets stoppedBy). testedCommit, gitDirty and constantSha256 are
captured by gitIdentity() before the first dispatch, so a non-git directory
fails before any spend and a mid-run checkout change cannot misattribute the
run. The receipt command is POSIX shell-quoted (semicolons, empty and quote
characters replay). The credential is checked before a request is counted, so a
missing key records requests:0 and no row. The gitDirty test now runs against an
isolated temp git repo and no longer depends on the working tree.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…s catch the regressions they name

gitIdentity() now passes --untracked-files=all, so a user's
status.showUntrackedFiles=no can no longer make an untracked file report
gitDirty:false (SPEC-v3 A.0 rule 3 provenance). The gitIdentity test sets that
config in the fixture and still expects gitDirty:true. It also asserts the
docs/eval receipt leaves the tree clean from both the repo root and docs/
before any root probe file exists (catches a cwd-relative exclude), and
constantSha256 equals the sha256 of the committed blob rather than only
matching 64 hex characters. The non-git test title no longer claims main()
ordering it does not exercise.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… replayable npx command; git tests get a time budget and assert the git error

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… at the estimate

The post-request check summed only reported costs, so a 503 with no cost followed by a
0.095 reply (estimate total 0.105 > maxUsd 0.10) ended ok:true, stoppedBy:null. It now
uses the same accounting as the pre-dispatch reservation. spentUsd stays null when any row
is unknown. Adds the 503-then-0.095 fake-fetch case.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…at that sha

constantSha256 used `git show HEAD:...` after a separate `git rev-parse HEAD`, so a checkout between the two calls produced a receipt naming commit A with commit B's hash. Hash `<testedCommit>:<script>` instead; a test moves HEAD between the two calls and asserts the hash belongs to the captured sha.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…nking_budget, candidate_count, logprobs)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@HomenShum
HomenShum force-pushed the claude/model-refresh-nodeagent branch from 8b12bea to f7963e2 Compare October 15, 2026 23:42
… gemini-3.8-flash

Receipt-only commit (SPEC-v3 A.0 rule 3 form a). testedCommit f7963e2,
clean tree, one request per role. OpenRouter chain recorded as live-unverified (no key, SPEC D2).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@HomenShum HomenShum removed the needs-live-eval merge blocked until keyed receipt attached label Oct 16, 2026
@HomenShum

Copy link
Copy Markdown
Owner Author

Live eval receipt: PASS for every changed non-OpenRouter role. Receipt-only commit 66360e3 on top of testedCommit f7963e2 (clean tree; nothing outside docs/eval changed after it; constantSha256 74d9f21a... matches git show f7963e2:scripts/nodeagent-live-provider-smoke.ts).

role requested = resolved echoedModel fallbackUsed result
anthropic claude-haiku-5-5 claude-haiku-5-5 false NODEAGENT_LIVE_OK, 52 in / 17 out
openai gpt-6.1-sol gpt-6.1-sol false NODEAGENT_LIVE_OK, 32 in / 9 out
gemini gemini-3.8-flash gemini-3.8-flash false NODEAGENT_LIVE_OK, 11 in / 89 out (83 thinking)

Echoed ids are the exact section 1.2 ids (no dated snapshot). Spend: 3 requests, no retries; direct providers report no cost, estimated well under $0.01 from token usage (cap $1.5; the script's own cap is $0.10, stoppedBy null).

OpenRouter chain: not called (SPEC D2, no working key). Recorded as live-unverified (no key, Homen 2026-10-16) in docs/eval/nodeagent-live-provider-smoke-openrouter.json with public-list check (fetched 2026-10-16T20:27:34Z, 467 rows): all four frozen chain ids listed, none with an expiration_date. This file is a record, not a run.

Command per role: npx tsx scripts/nodeagent-live-provider-smoke.ts --provider <openai|anthropic|gemini> --json-out docs/eval/nodeagent-live-provider-smoke-<provider>.json. needs-live-eval label removed. Open for Homen: the section C rule 10 vs rule 4 note in the PR body is unchanged.

@HomenShum
HomenShum merged commit a010f0e into main Oct 16, 2026
3 checks passed
@HomenShum
HomenShum deleted the claude/model-refresh-nodeagent branch October 16, 2026 20:30
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