Fix main CI: rewind and Skills strings, token count harness, deep research contract, zoo 2026.10.5 scan baseline (#13701)

* Studio i18n: move the Italian rewind filesNotRestored string into rewind

#13676 added it under settings.data.library, so the overlay parity check
in Frontend CI fails with an overlay key missing from en.

* Tests: lift arrow-function consts like functions in the node harness resolver

#13687 added const skillsForTools = () => ..., which reads the zustand
Skills switch store. The resolver treated it as an eagerly evaluated const
and dropped it because the store cannot be lifted, so the token count
parity harness failed with ReferenceError: skillsForTools is not defined.
An arrow or function expression reads its references only when called.
The parity harness also gets a stand-in Skills switch store.

* Baseline the unsloth-zoo 2026.10.5 findings after review

Five pinned zoo sites moved digest in 2026.10.5. Four have the same matched
code; speculative.py adds two mx.eval calls (MLX array evaluation). The rest
of each file's 2026.10.4 to 2026.10.5 diff adds no network, exec or
process code.

* Studio i18n: translate skills.turnOff in every overlay

#13687 added the Skills switch's Turn off skills label in en only, so the
strict overlay check in Frontend CI fails with it missing from all 13.

* Tests: follow the keyed + menu in the deep research contract

#13679 builds the chat + menu from a keyed list, so the one-shot gate is now
deepResearch: researchAvailable ? ( ... ) : null.

* Tests: shorten the deep research contract comment
This commit is contained in:
Daniel Han 2026-10-14 03:20:30 -07:00 • committed by GitHub
parent 3822d7046e
commit eb49b6f8b8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 90 additions and 4 deletions

View file

@ -2562,6 +2562,51 @@
"evidence": "Obfusc: L338: exec(compile(cached_bytes, cache_file, \"exec\"), module.__dict__)\nExec: L338: exec(compile(cached_bytes, cache_file, \"exec\"), module.__dict__)",
"evidence_hash": "ef22a4fe0d8ec7e2b0e4afc6e6a3d997cd94c981bf59790562217d4f9dd70732",
"file_sha256": "24bcbf0d36a0850fde3f5cddf303c31e24d93394ff0f6d71494370d41533e50e"
},
{
"package": "unsloth-zoo",
"file": "unsloth_zoo/vllm_utils.py",
"check": "Advanced obfuscation (marshal/compile/zlib) + exec/eval",
"severity": "HIGH",
"evidence": "Obfusc: L4472: lora_types.append(getattr(__import__(module_path, fromlist = [class_name]), class_name))\nExec: L1357: cross_attn_layer = eval(f'vllm_internals.{name}') | L1402: layernorm = eval(vllm_name).state_dict()[\"weight\"] | L1924: parent = eval(f\"new_model.{parent_path}\") if parent_path else new_model | L1930: exec(f\"new_model.{layer_name_br} = layer\") | L2001: exec(f\"new_model.{layer_name_br}.weight = None\") | L2002: exec(f\"new_model.{layer_name_br}.weight = weight_param\") | L2004: exec(f\"new_model.{layer_name_br}.bias = None\") | L2005: exec(f\"new_model.{layer_name_br}.bias = bias\") | L2011: exec(f\"new_model.{layer_name} = layer\") | L2043: new_model.eval() | L4279: exec(f\"module.to({dtype})\") | L4302: exec(f\"module.to({dtype})\") | L5961: model.eval() | L6001: new_model.eval()",
"evidence_hash": "4928e730b84a3fa71dcc50cfe185c77c2028be09ad908706710ab864786b4659",
"file_sha256": "88134b230d81ec499927d5355b90a32315cf94cb282021f462251ee44578fcd3"
},
{
"package": "unsloth-zoo",
"file": "unsloth_zoo/mlx/decision.py",
"check": "Advanced obfuscation (marshal/compile/zlib) + exec/eval",
"severity": "HIGH",
"evidence": "Obfusc: L382: with av.open(io.BytesIO(base64.b64decode(url.partition(\",\")[2], validate = True))) as container: sha256:946796d261fb90a0f7ad5f482b39026735f161d8d6877aa38112583f98acf957\nExec: L248: mx.eval(out) | L283: model.eval() | L284: mx.eval(model.parameters()) | L799: model.eval() | L800: mx.eval(model.parameters()) | L831: mx.eval(decoder.parameters()) | L1023: self.model.eval() | L1032: mx.eval(self.model.parameters()) | L1090: mx.eval(head, [entry.state for entry in cache]) | L1489: head.eval() | L1490: mx.eval(head.parameters()) | L1589: mx.eval(self.head.parameters()) | L1590: self.head.eval() | L2230: mx.eval(x) | L2242: mx.eval(loss, grads, cotangent) | L2250: mx.eval(stage_grads, cotangent) | L2340: mx.eval(model.parameters()) | L2381: mx.eval(self.parameters()) | L2407: mx.eval(logits) | L2547: mx.eval(total, grads) | L2574: network.eval() | L2651: model.eval()",
"evidence_hash": "e247443dfea5b48389857add89110a17e97c5226b7b8cd3c6bce68309d6e2c9d",
"file_sha256": "d83445bf7066c573bc8fa568a9fbafee4d5bf8a0aa3eaf6cac6bfdeeb40f95df"
},
{
"package": "unsloth-zoo",
"file": "unsloth_zoo/mlx/loader.py",
"check": "Advanced obfuscation (marshal/compile/zlib) + exec/eval",
"severity": "HIGH",
"evidence": "Obfusc: L5297: _mod = __import__(module_name, fromlist=[\"_\"])\nExec: L163: mx.eval(model.parameters()) | L197: mx.eval([v for k, v in tree_flatten(casted) if is_mlx_norm_parameter_path(k)]) | L1491: mx.eval(model.parameters()) | L1492: mx.eval(mx.distributed.all_sum(mx.array(1.0), stream=mx.cpu)) | L1559: mx.eval(model.parameters()) | L1562: mx.eval(mx.distributed.all_sum(mx.array(1.0), stream=mx.cpu)) | L2991: mx.eval(altup.correct(predictions, activated)) | L3463: model.eval() | L3540: mx.eval(baseline, perturbed) | L4945: model.eval() | L5702: mx.eval(model.parameters()) | L5818: mx.eval(module.weight) | L8423: mx.eval(model.parameters()) | L8440: mx.eval(target.parameters()) | L9440: lambda: mx.eval(model.parameters()), | L9504: lambda: mx.eval(model.parameters()), | L9667: mx.eval(model.parameters())",
"evidence_hash": "d1c32d6d0a0f4625af70ef11ce765a893c07f48e54c21fb8ff5ef43381daf18e",
"file_sha256": "171e445ef608e624f86b538b0fac15628d9f35338c8424f79988b24354009aec"
},
{
"package": "unsloth-zoo",
"file": "unsloth_zoo/mlx/speculative.py",
"check": "Advanced obfuscation (marshal/compile/zlib) + exec/eval",
"severity": "HIGH",
"evidence": "Obfusc: L835: module = __import__(f\"mlx_vlm.models.{family}.language\", fromlist = [\"LanguageModel\"])\nExec: L1044: mx.eval(drafts) | L1068: mx.eval([array for pair in drawn for array in pair if array is not None] + ([] if drafts is None else [drafts])) | L1343: mx.eval(parts[-1]) | L1345: mx.eval(self._scan) | L1838: mx.eval(model.parameters())",
"evidence_hash": "64b95579c569b39eddc493ac6b808258094d9b1d62154c55ae9c224c80577e45",
"file_sha256": "29edc582762bcde4f88e36af0f04a0c652c6e0c1c0e3a06f3d354d211d7ae51c"
},
{
"package": "unsloth-zoo",
"file": "unsloth_zoo/temporary_patches/moe_utils.py",
"check": "Advanced obfuscation (marshal/compile/zlib) + exec/eval",
"severity": "HIGH",
"evidence": "Obfusc: L338: exec(compile(cached_bytes, cache_file, \"exec\"), module.__dict__)\nExec: L338: exec(compile(cached_bytes, cache_file, \"exec\"), module.__dict__)",
"evidence_hash": "ef22a4fe0d8ec7e2b0e4afc6e6a3d997cd94c981bf59790562217d4f9dd70732",
"file_sha256": "86f4fe7b9a8e5973951eaa5ce70e2c0b4823c1e6bf9e54487f8be41c6fa2ee2d"
}
]
}

View file

@ -3984,6 +3984,7 @@ export const ar = {
discard: "تجاهل",
mentions: "المهارات",
manage: "إدارة المهارات",
turnOff: "إيقاف المهارات",
bulkActions: "إجراءات المهارات",
enableAll: "تفعيل الكل",
disableAll: "تعطيل الكل",

View file

@ -4057,6 +4057,7 @@ export const de = {
discard: "Verwerfen",
mentions: "Fähigkeiten",
manage: "Fähigkeiten verwalten",
turnOff: "Fähigkeiten ausschalten",
bulkActions: "Fähigkeiten-Aktionen",
enableAll: "Alle aktivieren",
disableAll: "Alle deaktivieren",

View file

@ -4056,6 +4056,7 @@ export const es = {
discard: "Descartar",
mentions: "Habilidades",
manage: "Gestionar habilidades",
turnOff: "Desactivar habilidades",
bulkActions: "Acciones de habilidades",
enableAll: "Activar todas",
disableAll: "Desactivar todas",

View file

@ -4068,6 +4068,7 @@ export const fr = {
discard: "Abandonner",
mentions: "Compétences",
manage: "Gérer les compétences",
turnOff: "Désactiver les compétences",
bulkActions: "Actions sur les compétences",
enableAll: "Tout activer",
disableAll: "Tout désactiver",

View file

@ -4098,6 +4098,7 @@ export const he = {
discard: "ביטול שינויים",
mentions: "מיומנויות",
manage: "ניהול מיומנויות",
turnOff: "כיבוי מיומנויות",
bulkActions: "פעולות מיומנויות",
enableAll: "הפעל הכול",
disableAll: "השבת הכול",

View file

@ -3993,6 +3993,7 @@ export const hi = {
discard: "छोड़ें",
mentions: "कौशल",
manage: "कौशल प्रबंधित करें",
turnOff: "कौशल बंद करें",
bulkActions: "कौशल क्रियाएँ",
enableAll: "सभी चालू करें",
disableAll: "सभी बंद करें",

View file

@ -2782,7 +2782,6 @@ export const it = {
working: "Elaborazione...",
loadFailed: "Impossibile caricare gli elementi archiviati",
loadMoreFailed: "Impossibile caricare altri elementi archiviati",
filesNotRestored: "{count} file modificati non possono essere ripristinati e restano come sono.",
restoreFailed: "Impossibile ripristinare gli elementi selezionati",
deleteFailed: "Impossibile eliminare gli elementi selezionati",
projectsFailed: "Impossibile caricare i progetti archiviati",
@ -3155,6 +3154,7 @@ export const it = {
restoredMany: "{count} file ripristinati",
nothingRestored: "Nessun file da ripristinare",
skippedCount: "{count} saltati",
filesNotRestored: "{count} file modificati non possono essere ripristinati e restano come sono.",
restoreFailed: "Impossibile ripristinare i file",
undo: "Annulla",
undone: "Ripristino dei file annullato",
@ -4058,6 +4058,7 @@ export const it = {
discard: "Scarta",
mentions: "Competenze",
manage: "Gestisci competenze",
turnOff: "Disattiva competenze",
bulkActions: "Azioni sulle competenze",
enableAll: "Attiva tutte",
disableAll: "Disattiva tutte",

View file

@ -3932,6 +3932,7 @@ export const ja = {
discard: "破棄",
mentions: "スキル",
manage: "スキルを管理",
turnOff: "スキルをオフにする",
bulkActions: "スキルの操作",
enableAll: "すべて有効にする",
disableAll: "すべて無効にする",

View file

@ -3975,6 +3975,7 @@ export const ko = {
discard: "버리기",
mentions: "스킬",
manage: "스킬 관리",
turnOff: "스킬 끄기",
bulkActions: "스킬 작업",
enableAll: "모두 사용",
disableAll: "모두 사용 안 함",

View file

@ -4016,6 +4016,7 @@ export const ptBR = {
discard: "Descartar",
mentions: "Habilidades",
manage: "Gerenciar habilidades",
turnOff: "Desativar habilidades",
bulkActions: "Ações de habilidades",
enableAll: "Ativar todas",
disableAll: "Desativar todas",

View file

@ -4012,6 +4012,7 @@ export const ru = {
discard: "Отменить",
mentions: "Навыки",
manage: "Управлять навыками",
turnOff: "Отключить навыки",
bulkActions: "Действия с навыками",
enableAll: "Включить все",
disableAll: "Отключить все",

View file

@ -4233,6 +4233,7 @@ export const sv = {
discard: "Ignorera",
mentions: "Färdigheter",
manage: "Hantera färdigheter",
turnOff: "Stäng av färdigheter",
bulkActions: "Färdighetsåtgärder",
enableAll: "Aktivera alla",
disableAll: "Inaktivera alla",

View file

@ -3889,6 +3889,7 @@ export const zhCN = {
discard: "放弃",
mentions: "技能",
manage: "管理技能",
turnOff: "关闭技能",
bulkActions: "技能操作",
enableAll: "全部启用",
disableAll: "全部停用",

View file

@ -45,6 +45,11 @@ _REEXPORT_RE = re.compile(
# Initialisers a `const` may carry and still be safe to lift: literals and callables.
# Anything else (a store built by `create(...)`, a client instantiated at import time) is
# module setup rather than a helper, so it is refused instead of executed in the harness.
# A `const` bound to a function expression runs nothing until it is called, like a `function`.
_FUNCTION_DECL_RE = re.compile(
r"^(?:export\s+)?(?:const|let|var)\s+[A-Za-z_$][\w$]*\s*=\s*"
r"(?:async\s+function\b|function\b|(?:async\s*)?(?:\([^()]*\)|[A-Za-z_$][\w$]*)\s*=>)"
)
_SAFE_INIT_RE = re.compile(
r"^(?:/|[\"'`]|\d|\[|\{|!|new\s+(?:Set|Map|RegExp|Date)\b"
r"|async\s+function\b|function\b|async\s*\(|\(|[A-Za-z_$][\w$]*\s*(?:=>|;))"
@ -516,8 +521,11 @@ def resolve_dependencies(
# A name this module really does resolve, so failing to follow it matters.
wanted.add(reference)
pull(reference, origin)
kind = home.kind(name) or "const"
if _FUNCTION_DECL_RE.match(text.lstrip()):
kind = "function"
pulled[name] = (
home.kind(name) or "const",
kind,
f"// sliced from {home.path.name}\n" + re.sub(r"^export\s+", "", text, count = 1),
wanted,
)
@ -531,7 +539,8 @@ def resolve_dependencies(
# A declaration evaluated at import time cannot be left half-resolved: `const A = [B]` with `B` refused crashes the
# whole harness on load, which is worse than the lazy ReferenceError it replaced. Drop those to a fixed point
# instead. Functions and types are lazy or erased, so an unfollowed reference in one costs nothing until it is
# called. A fixture the harness defines does not rescue one either: the fixtures sit BELOW this block, so reading
# called, and so is a `const` bound to an arrow or function expression. A fixture the harness defines does not
# rescue one either: the fixtures sit BELOW this block, so reading
# one from here is a TDZ error rather than a resolution.
eager = {"const", "let", "var", "class"}
while True:

View file

@ -347,7 +347,8 @@ def test_research_is_one_shot_per_thread_without_disabling_normal_chat() -> None
assert "runtime.setDeepResearchEnabled(false)" in adapter
assert "effectiveDeepResearchEnabled" in thread
assert "researchAvailable={!researchUsed}" in thread
assert "{researchAvailable ? (" in thread
# #13679: the + menu is a keyed list.
assert "deepResearch: researchAvailable ? (" in thread
assert "setToolsEnabled" in thread
assert "Web search" in thread

View file

@ -134,6 +134,21 @@ def test_a_pulled_const_that_needs_a_fixture_is_dropped_not_emitted(tmp_path):
assert "const HEADERS" not in resolved.replace("const used = HEADERS;", "")
def test_a_pulled_arrow_const_is_kept_like_a_function(tmp_path):
"""An arrow const reads its references only when called, so one it cannot follow is fine."""
module = tmp_path / "src" / "m.ts"
module.parent.mkdir(parents = True)
module.write_text(
'import { store } from "./store";\n'
"const pick = () =>\n store.getState().on === false ? [] : [1];\n"
"export function count() {\n return pick().length;\n}\n"
)
(module.parent / "store.ts").write_text("export const store = create(() => ({ on: null }));\n")
resolved = resolve_dependencies("const used = count();\n", (module,), root = tmp_path / "src")
assert "const pick = () =>" in resolved
assert "create(" not in resolved
def test_a_destructured_fixture_is_not_declared_twice(tmp_path):
"""``const { only, ...rest } = ...`` is a binding a declaration regex does not see."""
module = tmp_path / "src" / "m.ts"

View file

@ -123,6 +123,9 @@ const state: any = {
const useChatRuntimeStore: any = { getState: () => state };
const useBrowserAgentStore: any = { getState: () => state.browserAgent };
// The composer's Skills switch (#13687), unset as on a fresh install: skillsForTools() then
// offers the skill snapshot, the same list the request reads.
const useSkillsSwitchStore: any = { getState: () => ({ on: null }) };
// Browser use off: the count must match a turn that offers no browser tools.
function browserAgentToolsForTurn(): string[] {