Skip to content

feat(sync): add ai& sync module with auto-merge allowlist and motif family - #7040

Open
islomjon-aiand wants to merge 10 commits into
anomalyco:devfrom
islomjon-aiand:aia-683-aiand-sync-adapter
Open

islomjon-aiand wants to merge 10 commits into
anomalyco:devfrom
islomjon-aiand:aia-683-aiand-sync-adapter

Conversation

@islomjon-aiand

@islomjon-aiand islomjon-aiand commented Sep 14, 2026

Copy link
Copy Markdown

Adds a sync module for ai& (providers/aiand), whose GET /v1/api.json publishes this repo's shape directly — the aiand provider entry is read and translation is near-identity. Registered in the sync registry and the direct group, with an aiand:sync script and an "ai& Notes" section in sync.md.

What this change set contains

The catalog side of this PR is smaller than it was: dev's #6839 (2026-09-11) already brought the ai& TOMLs to the live feed — cache_read pricing, the gateway-enforced reasoning levels, refreshed headers, and the [interleaved] side-channel blocks — so after rebasing onto it, bun models:sync aiand against the live feed is a no-op for 8 of 11 files, which is the parity proof the adapter needs. What the diff does change:

  • New lab file models/motif-technologies/motif-3.toml and the provider file factored onto it. Motif 3 is open-weights (155 safetensors shards, ungated, MIT — https://huggingface.co/Motif-Technologies/Motif-3), correcting the previous inline open_weights = false; tool calling and temperature are cited from the model card and a 2026-09-14 live probe (real tool_calls response; temperature reaches the sampler). Release date 2026-08-07 is the HF repo creation date.
  • kimi-k2.7-code / kimi-k3: temperature = true — a host-specific delta from the feed (ai& forwards temperature and the engines honor it; lab files say false for Moonshot's own API).
  • Header refreshes: kimi-k3 and gpt-oss-120b re-probed 2026-09-14 (effort sets unchanged); qwen3.8-27b documents that high now returns 200 via ai&'s announced substitution to xhigh (X-Reasoning-Effort), so it stays unlisted.

Every published reasoning level on all 11 models was verified by live probe on 2026-09-14 (each returns 200; each unpublished value returns 400 or the announced substitution above).

Evidence

Claim Source
Pricing incl. cache_read, limits, capability flags, modalities GET https://api.aiand.com/v1/api.json (aiand entry), accessed 2026-09-14 — the adapter's own input; bun models:sync aiand --dry-run is a no-op against it
Reasoning levels per model (every published value → 200, every unpublished → 400) Live probe against api.aiand.com on 2026-09-14, 11 models × 7 values; each TOML's leading comment records its row
qwen3.8 high → 200 via substitution to xhigh Same probe; X-Reasoning-Effort: xhigh on the response; documented in qwen3.8-27b.toml
Motif 3 open weights, MIT, release 2026-08-07 https://huggingface.co/Motif-Technologies/Motif-3 — repo created 2026-08-07, 155 safetensors shards, ungated, license:mit
Motif 3 tool calling / temperature Model card (agentic tool use, vLLM --tool-call-parser motif, evals at temperature 1.0) + live probe 2026-09-14 (real tool_calls response; temperature 0.2 vs 1.7 changes output)
Motif 3 structured_output = false Live probe 2026-09-14: response_format: json_schema ignored, prose reply
Kimi temperature = true on this host Feed capability flag; host forwards temperature and the engines honor it (lab files record Moonshot's own API as false)

Adapter authority policy

Host facts come from the feed: prices (including cache_read), limits, capability flags, modalities, gateway-enforced reasoning_options, deprecated status, and the reasoning side channel (interleaved, with a gateway default of message.reasoning_content for reasoners until the feed publishes it). Lab-owned fields — name, description, family, release_date, last_updated, knowledge, open_weights — are never asserted from the gateway on a factored file: they appear only as deltas the authored TOML already carried on top of its base_model (read from context.authored(), never the base-resolved merge), so a full-inline file being factored for the first time, or a new file, inherits the lab entry outright. On a standalone file curated values win for those fields.

New feed ids resolve their base_model by normalized match against models/ (full id, then unique filename — ai&'s lab prefixes differ from the directory names, e.g. deepseek-ai/ vs models/deepseek/); an unresolvable new id is returned from missingModelID, so the runner preserves any existing local entry and opens a deduped missing-model issue. An empty feed fails the run instead of authorizing deletion of the local catalog. family passes through ModelFamily.safeParse and is omitted when unknown.

reasoning_options follow the feed's assertion exactly: an omitted list asserts nothing (authored options stay), an explicit [] asserts "no caller controls", a non-empty list whose effort values the schema doesn't know yet keeps the authored options; when a reasoner ends up with no schema-valid set and nothing authored, the model fails with MissingReasoningOptionsError (local file preserved, missing-model issue opened) rather than ever writing an invented []. toggle/budget_tokens are parsed (so a feed publishing one never aborts the run) but never written, from feed or authored file — ai& has a single reasoning wire path (reasoning_effort, "none" = off) and no separate toggle or token-budget field; created files get a leading header stating exactly that; omitted entirely on non-reasoners. preserveDescriptions is off so the runner never re-injects a pre-factor description. A curated alpha/beta survives an omitted feed status; a curated deprecated does not (the feed owns deprecation).

Asks

  • Add aiand to REVIEWED_REASONING_PROVIDERS — all 11 ai& models are reasoning models, so without it every hourly sync PR waits on a maintainer. The adapter's empty-options guard above is the safety argument: a feed vocabulary change can't strip caller controls and auto-merge that way.
  • Add motif to ModelFamilyValues — needed by the new lab file; the adapter degrades gracefully (omits family) if you'd rather trim this.

Validation

bun models:sync aiand --dry-run → write → second dry run is a no-op (11 unchanged) → bun validate passes → bun test (27 tests in packages/core/test/aiand.test.ts plus the allowlist assertion in auto-merge.test.ts; the pre-existing failures on dev are untouched).

@islomjon-aiand
islomjon-aiand marked this pull request as ready for review September 14, 2026 04:56
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/aiand.ts:276 - Check: reasoning_options must be omitted when reasoning is false (schema refine + peers like wandb/tinfoil). Why: buildAiandModel always assigns reasoning_options (including []). For reasoning: false, SyncedAuthoredModel fails with “Cannot set reasoning_options when reasoning is false”, so any non-reasoner on the feed stalls the hourly sync. Action: Set reasoning_options only when model.reasoning === true (else undefined); add a unit test for a non-reasoning feed model.
  • [high] [violation] packages/core/src/sync/providers/aiand.ts:310 - Check: Non-lab hosts must use base_model when a lab model is nameable (AGENTS.md blocker; peers resolve via existing?.base_model ?? resolve…). Why: Factoring runs only if a local file already has base_model. A new feed ID with no local TOML is written as a full inline definition (no base_model), which breaks override-only policy and can auto-merge incomplete third-party rows. Action: Resolve base_model for new IDs (map feed id → models/…, or skipCreates + missing-model issues when unresolved); never create unfactored third-party full definitions when a lab entry exists or can be added.
  • [medium] [possible mistake] models/motif-technologies/motif-3.toml:48 - Check: Lab capability flags need evidence; provider previously had tool_call = false / temperature = false. Why: The new lab file sets tool_call = true and temperature = true (and the provider now inherits them). The PR body only evidences open weights / MIT / HF date, not tools or temperature, so catalog capabilities may be wrong. Action: Cite first-party/HF evidence for tool calling and temperature, or keep conservative false until verified; if only the gateway differs, put overrides on the provider file instead of the lab entry.
  • [low] [violation] packages/core/test/auto-merge.test.ts:97 - Check: Allowlist changes should be covered by the reviewed-providers test. Why: aiand was added to REVIEWED_REASONING_PROVIDERS but the test still lists only the prior providers, so a regression dropping aiand would not fail CI. Action: Include "aiand" in that allowlist assertion.

@islomjon-aiand
islomjon-aiand force-pushed the aia-683-aiand-sync-adapter branch from 5ceebc2 to ec88eae Compare September 14, 2026 05:20
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/aiand.ts:241 - Check: Authoritative deletion must not wipe the catalog on an empty or partial feed. Why: parseModels returns Object.values(...) with no empty-catalog guard, and deleteMissing is left at the runner default (true). An empty aiand.models object (or a transient feed that omits the entry) produces zero desired models and deletes every local TOML under providers/aiand/models. Peers such as LLM Gateway and Cloudflare AI Gateway fail loudly instead. Action: Reject an empty model list in parseModels/fetchModels (or set deleteMissing: false if the feed is not lifecycle-authoritative), and add a test for that failure path.
  • [medium] [violation] packages/core/src/sync/providers/aiand.ts:277 - Check: Feed-authoritative reasoning_options must not invent “no caller control” when the feed omits controls. Why: Omitted reasoning_options on a reasoning: true model becomes [] (feedReasoningOptions starts empty, and the authored fallback only runs when the feed list was non-empty then filtered away). The runner then keeps that explicit [] via preserveReasoningOptions, so hourly sync can permanently replace probed effort sets with empty controls and auto-merge them under REVIEWED_REASONING_PROVIDERS. Action: When the feed omits reasoning_options on a reasoner, preserve authored options or fail the model for manual review; only write [] when the feed explicitly publishes an empty control set. Cover omit-vs-empty in tests.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Sep 14, 2026
@islomjon-aiand
islomjon-aiand force-pushed the aia-683-aiand-sync-adapter branch from ec88eae to fc9e830 Compare September 14, 2026 05:41
@github-actions github-actions Bot removed the reviewer: ready Automated review found no actionable items label Sep 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/aiand.ts:292 - Check: Lab/base_model files stay override-only; lab-owned fields are not restated from the gateway. Why: description is taken as model.description ?? existing?.description, so any feed description wins over both the lab entry and a hand-authored provider override. On the next hourly sync, factorBaseModel will write a provider-level description whenever the feed text differs from models/…, and it can erase a curated override. Action: Prefer curated/lab description (existing?.description first, or omit description entirely when base_model is set so the lab value inherits), matching how name / release_date are handled.
  • [high] [violation] packages/core/src/sync/providers/aiand.ts:173 - Check: Sync modules that claim near-identity with this repo’s api.json shape must accept the full catalog reasoning_options schema. Why: Local ReasoningOption only allows type = "effort". A feed entry with toggle or budget_tokens (valid catalog shapes) fails Zod parse for that model and aborts the whole AiandResponse parse, so the hourly job cannot sync. Action: Parse with the shared ReasoningOption from schema.ts (or an equivalent discriminated union), and map/preserve non-effort controls instead of requiring effort only.
  • [medium] [violation] packages/core/src/sync/providers/aiand.ts:306 - Check: Release dates are lab metadata; provider files must not invent overrides from the gateway. Why: For new feed IDs (existing === undefined) the adapter still sets release_date: model.release_date before factorBaseModel. If that date differs from models/<lab>/…, the first create writes a provider release_date override even though the PR/sync.md policy says the gateway is not authoritative for release dates. Action: When factoring with base_model, omit feed release_date (and other lab-owned fields) so new files inherit from the lab entry unless there is a real host-specific delta.

@islomjon-aiand
islomjon-aiand force-pushed the aia-683-aiand-sync-adapter branch from fc9e830 to d9e921d Compare September 14, 2026 06:04
@islomjon-aiand

Copy link
Copy Markdown
Author

All three addressed with one rule: on base-factored files, lab-owned fields (name, description, family, release_date, last_updated, knowledge, open_weights) are never asserted from the feed — they come from the curated file, so authored overrides survive and new files inherit the lab entry (a test covers a new create whose feed disagrees with the lab). Feed reasoning_options now accept the full catalog shape: toggle/budget_tokens parse via the shared schema and pass through, while effort values stay leniently parsed so unknown vocabulary filters per value instead of aborting the run.

@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Sep 14, 2026
fenilmodi00

This comment was marked as outdated.

fenilmodi00

This comment was marked as outdated.

@fenilmodi00 fenilmodi00 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebased this onto current dev for you: fenilmodi00/models.dev@dev...fenilmodi00:models.dev:pr-7040-rebased

Cherry-pick those commits onto your branch and the merge conflicts are gone. The rebase keeps all 11 [interleaved] blocks from #6839 (your adapter preserves them via existing?.interleaved), reruns the sync against the live feed, and refreshes the kimi-k3 and gpt-oss-120b headers with a 2026-09-14 live probe. bun validate and the aiand test suite pass on it.

@islomjon-aiand

Copy link
Copy Markdown
Author

Thanks for the rebase, Fenil — adopted your branch and rebased once more onto current dev (one trivial conflict: friendli in the direct group, kept both). Verified all 11 [interleaved] blocks survive. One correction on top: the regen against dev's motif-3 file preserved its stale inline lab fields (open_weights = false, release 08-12) as overrides against the new lab entry, so that file is now override-only and inherits from models/motif-technologies/motif-3.toml. Sync is a no-op against the live feed, validate green.

@islomjon-aiand
islomjon-aiand force-pushed the aia-683-aiand-sync-adapter branch from d9e921d to ee5249e Compare September 15, 2026 00:32
@github-actions github-actions Bot removed the reviewer: ready Automated review found no actionable items label Sep 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [medium] [violation] packages/core/src/sync/providers/aiand.ts:179 - Check: Feed-authoritative lifecycle status (absence = active; only curated alpha/beta survives omission). Why: status: model.status ?? existing?.status keeps a curated deprecated forever when the feed omits status, contradicting the adapter comment and sync.md (“Absence means active”; feed owns deprecated). Active routes can stay marked deprecated after the gateway clears them. Action: Preserve only non-deprecated curated statuses on omission (e.g. keep alpha/beta, clear deprecated when the feed has no status), matching the documented policy.
  • [low] [violation] packages/core/src/sync/providers/aiand.ts:116 - Check: skippedNotice must no-op on an empty skip list (peer adapters). Why: skippedNotice always returns a string, so every clean sync emits Skipped 0 feed model(s)… into the sync report/PR body. Action: Return [] when ids.length === 0, then format the notice only for real skips.

@islomjon-aiand

Copy link
Copy Markdown
Author

Both addressed: a curated deprecated is now cleared when the feed omits status (alpha/beta still survive — the feed owns deprecation, absence means active), and skippedNotice returns [] on a clean sync. Tests cover both.

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] providers/aiand/models/ - Check: First-sync catalog corrections claimed in the PR must land in this change set. Why: The body says all 11 models get live-feed updates (including 2026-09-14 reasoning probes and rewritten stale headers; e.g. qwen3.8-27b high→xhigh substitution note). The diff only updates motif-3, kimi-k2.7-code, kimi-k3, and a probe comment on gpt-oss-120b. The other eight TOMLs stay on older headers/values (e.g. qwen3.8-27b.toml still cites the 2026-08-29 probe and does not document the substitution quirk). Action: Re-run bun aiand:sync (or hand-apply the feed) so every providers/aiand/models/**/*.toml matches the claimed feed/probe state, including headers.
  • [high] [violation] packages/core/src/sync/providers/aiand.ts:322 - Check: Near-identity api.json adapters must publish provider-only interleaved from the feed (see wandb.ts). Why: AiandModel never parses interleaved, and buildAiandModel only keeps existing?.interleaved. Every current aiand reasoner uses reasoning_content; a new feed reasoner with no local file will omit the side channel even when the feed publishes it, so automation creates incomplete reasoners. Action: Parse feed interleaved (same catalog shapes as the schema) and set interleaved from the feed with a safe existing fallback; cover create + update in aiand.test.ts.
  • [medium] [violation] packages/core/src/sync/providers/aiand.ts:255 - Check: Skips that need lab metadata should use missingModelID so the runner preserves locals and opens missing-model issues (sync.md). Why: Unresolvable new IDs only hit sourceID + skippedNotice. They are treated as absent (delete risk for any future path mismatch) and never enter the missing-model issue flow that Friendli-style multi-lab factoring uses. Action: Return the skipped ID from missingModelID when the skip is “no lab base yet,” keep intentional skips at undefined, and document the issue behavior in the ai& sync.md notes.

@islomjon-aiand

Copy link
Copy Markdown
Author

All three addressed. The PR body now describes the rebased change set honestly — dev's #6839 already landed cache_read, the enforced levels, and the interleaved blocks, so the sync is a no-op on 8 of 11 files (that's the parity proof); the diff's real content is the motif lab file + factoring, the two Kimi temperature = true deltas, and header refreshes, with qwen3.8 now recording the announced high → xhigh substitution from today's probe. The adapter parses interleaved from the feed with an authored fallback and a gateway default of message.reasoning_content for reasoners, so a new reasoner is never created without its side channel. Skipped new ids go through missingModelID so the runner preserves local entries and opens deduped missing-model issues.

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/aiand.ts:243 - Check: Override-only base_model files must keep only provider-specific fields and real deltas (AGENTS.md → Override-only provider files). Why: translateModel / buildAiandModel use context.existing() (base-resolved merge) for “curated” name, description, release_date, last_updated, knowledge, and open_weights. On a first factor of a full-inline local file, those lab values look authored, so factorBaseModel can re-emit identical lab fields as provider overrides (or pin wrong host values). Patch 2 already did this for Motif 3 (open_weights = false, stale dates); Patch 4 only cleaned that one file. Action: Resolve base_model / omit / lab-owned curated fields from context.authored(), and only treat values present on the authored TOML as overrides; add a regression test that factors a full-inline existing Motif-like file onto a lab entry with no redundant lab fields.
  • [medium] [violation] providers/aiand/models/motif-technologies/motif-3.toml:1 - Check: Non-lab hosts must use complete lab metadata + override-only provider entries; first sync corrections claimed in the PR must land in the branch. Why: Final Motif provider state still omits required host fields that only exist on the new lab file in this PR (base_model, corrected open_weights, tool/temperature inheritance), while the PR body says the first sync includes Motif factoring and open-weights correction. Base checkout still has the full-inline Motif entry; the Motif lab file exists only in the diff. Action: Ship the final Motif provider TOML as override-only (base_model = "motif-technologies/motif-3" plus cost / reasoning_options / interleaved only) and ensure the lab entry is present so validation resolves the merge.
  • [medium] [possible mistake] packages/core/src/sync/providers/aiand.ts:242 - Check: Sync modules must preserve hand-authored provider overrides and not expand factored files (sync.md → Provider Modules / Runner Responsibilities). Why: Passing the resolved model into factoring also treats inherited lab limit.input, modalities, and capability flags as if they were local overrides when deciding omit/keep behavior, so later feed churn can rewrite files differently than peers that separate authored vs existing (e.g. Friendli, Baseten, Cortecs). Action: Mirror the authored/existing split used by those adapters for omit lists and non-feed fields; cover with a test that an existing factored file keeps only feed deltas after sync.
  • [low] [possible mistake] .pr-review/pull-request.json:4 - Check: Data-changing PRs should cite first-party pricing/docs/API evidence mapped to claims. Why: The body asserts catalog-wide cache_read fills, gateway-enforced reasoning sets, and Motif open-weights/date facts from live probes and HF, but the truncated body and most provider TOMLs still point at older /v1/models headers; only some files get 2026-09-14 probe notes. Action: Map each material claim to a concrete source (api.json path, probe date, HF) in the PR body and align leading TOML headers after the authoritative sync write.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Sep 15, 2026
@islomjon-aiand

Copy link
Copy Markdown
Author

Clean pass this time. Overrides now come from the authored TOML, not the base-resolved merge — that was the root cause behind the last few rounds. Lab fields on factored files only appear as deltas the file already had on its base_model, so a full-inline file factored for the first time inherits the lab entry (regression test added). All 11 headers cite the 2026-09-14 probe matrix, and the PR body has an evidence table mapping each claim to its source.

@github-actions github-actions Bot removed the reviewer: ready Automated review found no actionable items label Sep 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Sep 15, 2026
@islomjon-aiand

Copy link
Copy Markdown
Author

@fenilmodi00 branch is final — rebased on current dev, review bot clean, validate green, merge state clean. Ready when you are.

@fenilmodi00

fenilmodi00 commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Looks good to me. @rekram1-node — this is ready for a final review when you get a chance; you merged my earlier ai& PRs (#6839, #5806).

islomjon-aiand and others added 7 commits September 15, 2026 13:36
…amily

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Rerun of the ai& sync after cherry-picking onto current dev.
Interleaved reasoning_content blocks from anomalyco#6839 are preserved by the
adapter (existing?.interleaved); motif-3 factors onto the new lab entry.
Live reasoning_effort probes on 2026-09-14 (negative controls included)
confirm the authored effort sets are unchanged on the gateway.
The rebased regen kept dev's stale inline lab fields (open_weights = false,
release_date 2026-08-12) as overrides against the new lab file. Lab facts now
inherit from models/motif-technologies/motif-3.toml; the [interleaved] block
from anomalyco#6839 is preserved.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…notice

The feed owns deprecation and absence means active, so a curated deprecated
no longer survives a feed that omits status (alpha/beta still do). A clean
sync no longer emits a zero-count skip notice into the report.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… skips to missing-model issues

Parse the feed's interleaved (authored fallback, gateway default of
message.reasoning_content for reasoners) so a new reasoner is never created
without its side channel; return skipped ids from missingModelID so the runner
preserves local entries and opens deduped issues. qwen3.8 header records the
2026-09-14 probe including the announced high→xhigh substitution.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s to the 2026-09-14 probes

Lab-owned fields on factored files come only from deltas the authored file
already carried on its base_model (context.authored, never the base-resolved
merge), so a full-inline file factored for the first time inherits the lab
entry instead of re-emitting stale values as overrides — the Motif regression
in general form. Host fields stay feed-authoritative. All 11 headers now cite
the 2026-09-14 probe matrix (11 models x 7 effort values).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@islomjon-aiand
islomjon-aiand force-pushed the aia-683-aiand-sync-adapter branch from e92feb1 to f454a50 Compare September 15, 2026 04:36
@github-actions github-actions Bot removed the reviewer: ready Automated review found no actionable items label Sep 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/aiand.ts:218 - Check: Override-only base_model files must not restate lab fields identical to the base (AGENTS.md → Override-only provider files); peers that factor and omit matching descriptions set preserveDescriptions: false (e.g. Friendli). Why: buildAiandModel correctly omits lab-owned description on first factor / inherit, but the runner still runs default preserveDescription, which re-injects the pre-factor authored description whenever the translator leaves it unset. That recreates a redundant description override (the Motif-style regression patch 7 tried to fix) on the next bun models:sync aiand for any full-inline → factored transition. Action: Set preserveDescriptions: false on the aiand provider (and cover first-factor with a runner-level or integration expectation that the written TOML stays free of a lab-identical description).
  • [medium] [violation] packages/core/src/sync/providers/aiand.ts:242 - Check: Every toggle reasoning control needs a leading top-of-file wire-path comment (AGENTS.md → Reasoning options / Toggle); sync creates must supply header when no on-disk header exists. Why: The feed can publish { type = "toggle" } and the adapter passes it through, but translateModel never returns header. New auto-created reasoners with toggle (provider is on the auto-merge allowlist) would be written without the required Toggle wire comment. Peers (OpenRouter, Friendli, LLM Gateway, Merge Gateway) emit toggle headers from translateModel. Action: When built reasoning_options include toggle, return a leading header documenting the exact ai& wire path (and add a unit test for that create path).

…d created files with a reasoning-wire header

preserveDescriptions is off so a full-inline → factored transition cannot
recreate a lab-identical description override (runner-level test covers the
Motif shape end to end). translateModel now returns a leading header for
creates naming the reasoning wire path, so a toggle control is never written
without it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/aiand.ts - Check: Relay adapters must not invent reasoning_options = [] (no caller control) from uncertainty, and auto-merge allowlisting must not land incomplete reasoner controls without review (AGENTS.md Reasoning options; preserveReasoningOptions + REVIEWED_REASONING_PROVIDERS). Why: For reasoning = true, omitted feed reasoning_options (or a non-empty effort list that filters to nothing) makes resolveReasoningOptions return undefined. Lab metadata never carries reasoning_options, so the runner’s preserveReasoningOptions stamps [] on creates/updates with no authored options. With aiand on the auto-merge allowlist, that “no control” shape can merge hourly without review even though the module treats the feed as authoritative for gateway effort sets. Action: When the feed marks a model as reasoning but does not yield a schema-valid non-empty control set (and there is no authored set to keep), fail that model with MissingReasoningOptionsError (or equivalent skip that preserves locals and does not write []). Do not allowlist auto-merge until incomplete feed rows cannot become [].

…g [] be written

A reasoner whose feed yields no schema-valid reasoning_options and has no
authored set to keep now throws MissingReasoningOptionsError: the runner
preserves the local file, reports the reason, and routes the id to the
missing-model issue flow. An explicit [] from the feed remains the feed's own
assertion. Runner-level test covers the untouched-file path.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/aiand.ts:420 - Check: AGENTS.md Reasoning options — never invent budget_tokens unless this host has a real reasoning-budget wire field. Why: resolveReasoningOptions passes budget_tokens through unchanged after Zod accepts the catalog shape. The create header even states ai& has no token-budget control, yet a feed that publishes budget_tokens (or stale authored budget on update) would still write it into provider TOMLs and, once allowlisted, auto-merge as a false control surface. Action: Drop feed/authored budget_tokens (or fail with MissingReasoningOptionsError when that would empty the control set), and stop emitting a budget wire comment that contradicts host capability.
  • [high] [violation] packages/core/src/sync/providers/aiand.ts:427 - Check: AGENTS.md / audit-reasoning-options — do not pair toggle with effort that already includes none; off is effort=none only. Why: Non-effort options are returned as-is. A feed row of toggle + effort values containing none (or toggle alone when off is the same reasoning_effort field) would be written and auto-merged. The seeded header text (Toggle: reasoning_effort = "none" (off) vs the graded levels) encodes that invalid shape instead of collapsing to effort-with-none. Action: Normalize like Eden AI / LLM Gateway peers: if effort includes none, strip toggle; if the only off control is reasoning_effort=none, author effort values (including none) and never a separate toggle; keep toggle only for a true separate on/off wire path.

…reasoning wire path

reasoning_effort ("none" = off) is the only control this host exposes, so
toggle and budget_tokens are parsed for tolerance but dropped from feed and
authored options alike; an emptied set falls through to the existing
fail-for-review path. The create header states the single wire path instead
of describing controls the host does not have.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Sep 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reviewer: ready Automated review found no actionable items

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants