- Release-pipeline fix-up on top of
.26.1.pre_release_check.py's "Channel experience dirs" mandatory check failed in CI on the.26.1tag becauseexperience/is.gitignored on purpose (runtime artifact, not committed). The check is still useful as a local pre-tag developer-sanity guard, so this release auto-skips it underCI=true/GITHUB_ACTIONS=trueinstead of demoting the check. Mandatory-check list and the existing test contract are unchanged.
- P0 / P1 security + reliability rollup (10 PRs). Closes the
reports/autosearch-p0-fix-plan.mdpunch-list:- npm wrapper no longer fakes success on missing binary. ENOENT /
EACCES / EPERM during the post-install spawn now exits non-zero with
a fix hint;
scripts/install.shpersists~/.local/binto a real shell profile (zsh/bash; fish/csh skip with a warning instead of writing bash syntax to.bashrc); install passes--no-initso barenpx autosearch-aino longer auto-runs init. (#427) - Cloud transcription stops leaking local paths. OpenAI / Groq
transcribe modules route
sourceandaudio_paththrough a newredact_path_for_output()(basenames for local files, redacted-URL form for URL inputs); failure-pathextrafields are redacted before merge; Windows drive-letter paths detected correctly. (#428) - bcut transcribe redacts signed URLs. All log call sites and
structured output's
source/reasonnow walkredact_url/redact;LOGGER.exceptionswapped for redactedLOGGER.warningso tracebacks no longer echo the signed URL; empty or non-stringsourceis guarded before redaction. (#429) - Per-channel timeout + cooldown in delegate.
run_subtaskacceptsper_channel_timeout(env overrideAUTOSEARCH_PER_CHANNEL_TIMEOUT_SECONDS); timeout is mapped totransient_error, recorded against executable channel methods so cooldown actually triggers, and tracked with the real elapsed latency.asyncio.CancelledErrorpropagates and exception types are narrowed instead ofnoqa-suppressed. (#430) - Atomic write to
~/.config/ai-secrets.env. Newsecrets_store.write_secret(...)does fcntl-locked read-modify-write withfsync+os.replace, preserving comments, ordering, and unknown lines.fcntlimport is now optional so the module imports on Windows; newline / control-character keys + values are rejected. CLIconfigure --replaceand the cookie-write path both route through the helper. (#431) - e2b reports redact scenario error text.
summary.md,results.json, and the comprehensive transcript writer all walkredact()before disk. (#432) scripts/e2b/run_validation.py --outputno longer rmtree's arbitrary directories. Default behaviour creates arun-<timestamp>subdir;--clean-outputis required to delete and only inside the repo'sreports/root, with both sides.resolve()d to defeat symlink escape. E2B test stubs register proper__path__so nested submodule imports work. (#433)- Legacy
research()MCP path redacts exception text. Same sanitisation as the new pipeline. (#434) - CLI top-level error redact.
_exit_query_failure()redacts before stderr /--jsonenvelope. (#435) - kr36 channel switched to working JSON gateway endpoint. Old
endpoint returned 404; new code reads article fields from the nested
template payload, skips empty fallback values, and gracefully maps
upstream failures to
transient_errorwith an actionablefix_hint. Legacy HTML fallback now driven by an explicit feature flag instead of monkeypatch identity. (#436)
- npm wrapper no longer fakes success on missing binary. ENOENT /
EACCES / EPERM during the post-install spawn now exits non-zero with
a fix hint;
- Companion infra fixes shipped alongside the rollup.
.gitleaks.tomlgained allowlists for placeholder usernames +.localPOSIX paths used in the new install / wrapper tests; a regression inpapers/via_paper_search.pyper-source timeout (caused by the F006a exception narrowing) was repaired so the existing skip-slow-source test still passes.
- No more signed-URL secret leaks from fetch / video tools.
autosearch.core.redactgainsredact_url(url, *, strip_query=True); six MCP-visible tools (fetch-jina,fetch-crawl4ai,fetch-firecrawl,video-to-text-openai,video-to-text-groq,video-to-text-local) now sanitize URLs at every output boundary (return fields + log calls). Previously a user passinghttps://example.com/foo?access_token=SECRET&X-Amz-Signature=...would see the credential echoed back in the tool result and structured logs. A new integration suite (tests/tools/test_url_leak_prevention.py) parametrizes 6 leak scenarios and locks the contract. Closes P0-2 fromdocs/exec-plans/active/autosearch-0425-p0-scan-report.md. - Rolls up #406 (CN→EN cleanup residuals — workflow comment, e2b harness stdout, scenario docstring) and syncs
pyproject.tomlto2026.04.25.11(the bump in #406 missed this file, leavingtest_version_consistencyfailing on main).
autosearch query "..." --jsonis now parseable. The CLI was leaking structlog[info]lines onto stdout, so piping intojqfailed with "Extra data". Logs now route to stderr (matching the MCP path), and a fresh-install smoke test (tests/smoke/test_first_use_flow.py) locks the contract in: markdown brief + JSON envelope +--helpall pass without network or LLM keys, closing the P1-7 first-use loop from the production-critical-fix-plan-v2.- Public-repo hygiene rollup. Bumps in PRs #395–#403 were intentionally deferred per the "bump once after a merge batch" rule; this release ships them: install paths unified to npx / AI-agent / curl with
--yesremoved (#395); internal docs + runtime experience stripped from HEAD (#396); committer / husky / gitleaks tooling layer (#397);public_repo_hygiene.py+ tests + npm/CI entrypoints (#398); gitleaks split into public/private notes (#399); CLAUDE.md cleanup + stale validation/bench/plan docs removed (#400); 5 user-facing docs rewritten to drop internal voice (#401); "boss" wording removed from skill READMEs +public-repo-policy.mdadded (#402); history-exposure assessment + verification procedure (#403).
Hotfix on top of .25.8. PR #387 wired pre_release_check.py into
the release workflow as a blocking step, but the checklist bundles
dev-sanity checks (channel experience/patterns.jsonl bootstrap state,
Gate 12 bench results) that fail when those artifacts haven't been
generated for a given commit. .25.8 release blocked at this step
before any real release work happened.
Removed the workflow step. pre_release_check.py remains as a local
developer tool — run python scripts/validate/pre_release_check.py
before tagging. The checklist itself is fine; just shouldn't be a
release-pipeline gate without separating release-blocking from
dev-sanity tiers.
.25.9 ships the full .25.8 content (Gate 12 commit binding +
label-based open-PR gating from #387) plus this workflow unwire.
Ships PR #387 — the Gate 12 / pre-release-check / open-PR-label
work that was open while the .25.4–.25.7 release-pipeline
hotfixes landed.
scripts/bench/judge.py: Gate 12 stats now includecommit_sha,version,generated_at,test_configprovenance.scripts/validate/pre_release_check.py: requires Gate 12commit_sha == HEAD; supports--allow-stale-gate12override; open PR gate switched from "any open PR blocks" to "PR labeledrelease-blockerblocks"..github/workflows/release.yml: pre-release check is now a release-job step.
GitHub Release auto-creation hotfix on top of .25.6. The
.25.6 workflow successfully published to PyPI and npm using the
PyPA action, but the create-github-release job lacked
actions/checkout — gh release create failed with "fatal: not a
git repository" because the runner had no .git context. The GH
Release was created manually for .25.6. This release adds the
missing checkout step so future releases auto-create the GH Release
end-to-end.
.25.6 content (already on PyPI / npm):
- All
.25.3–.25.5rollup (twelve PRs from the production-critical sweep audit) - License metadata +
setuptools>=80/twine>=6.1/ PyPA action
Third (and hopefully final) release-pipeline hotfix. .25.4 and .25.5
both pinned twine>=6.1 but still failed at upload with the same
InvalidDistribution: unrecognized or malformed field 'license-file'
error — even though local twine check --strict passed on identical
wheels. Cause appears to be GitHub's ubuntu-latest runner shadowing
the user-installed twine with a system-installed older pkginfo on the
fallback path.
Switched the publish-pypi step to pypa/gh-action-pypi-publish@release/v1,
the official PyPA action. It manages the upload toolchain internally
and is the recommended path. No more manual twine version pinning.
Same content as .25.5 (which had .25.3 content + license metadata
hotfix + publish-pypi twine pin). Just the action change.
Second hotfix attempt for the .25.3/.25.4 PyPI publish failure.
.25.4 pinned twine>=6.1 in the build job but missed the
publish-pypi job which had its own separate pip install twine
without the pin — so the upload step grabbed older twine and rejected
metadata-2.4 license-file/license-expression fields. Both .25.3 and
.25.4 tags exist on GitHub but neither shipped to PyPI / npm /
GitHub Release.
This release pins twine>=6.1 in the publish-pypi job too. Same
content as .25.4 (which had all .25.3 content + license metadata
hotfix) — just the second half of the workflow fix.
The "release plumbing hotfix" release — 2026.04.25.3 was tagged and
the GitHub workflow ran, but twine upload rejected the wheel with
Invalid distribution metadata: unrecognized or malformed field 'license-file'. Older setuptools (75-77 range) wrote a metadata 2.4
field that older twine clients didn't accept. The PyPI / npm /
GitHub Release for .25.3 never actually shipped.
This release contains all .25.3 changes (the "production-critical
sweep" — see the .25.3 entry below for the full list of 21 features
from the 5-agent audit) plus the release-plumbing hotfix:
pyproject.toml: explicitlicense = "MIT"(PEP 639 SPDX) andlicense-files = ["LICENSE"].[build-system].requiresbumped tosetuptools>=80so build environments use a clean metadata-2.4 generator..github/workflows/release.yml: pin--upgrade build>=1.2,twine>=6.1,setuptools>=80in the build job. Twine 6.1+ knows about metadata 2.4 license-file fields.
Verified locally with python -m build + twine check dist/* after
the fix (both wheel and sdist PASS).
The "production-critical sweep" release — twelve PRs landing 21 features from a 5-agent audit. Two security P0s, one supply-chain P0, three secrets-hygiene P0s, plus channel reliability, release plumbing, docs alignment, report quality, and observability.
Security
scripts/install.sh --versionnow validates against a PEP 440 allowlist and runs install commands as argv arrays — the previousevalpath was a real command-injection vector via thecurl | bashinstall URL.- Bearer-token redaction now covers the full token character set
(
+/=._-~plus base64url and JWT). Earlier regex stopped at the first special char and leaked the tail of the token. secrets_store.inject_into_env()no longer overwrites a key the parent process / orchestrator set explicitly. Tracks file-injected keys and only refreshes those it already owns.ClaudeCodeProvidersubprocess gets a minimal allowlistedenv(PATH/HOME/SHELL/TERM/USER/LANG/LC_/TMPDIR plus ANTHROPIC_/CLAUDE_CODE_/XDG_) instead of inheriting the full parent environment with unrelated secrets likeTIKHUB_API_KEY.
Channel reliability
package_search/xueqiu/discourse_forumno longer return[]when upstream fails — typed errors propagate. Aggregated channels distinguish "all sources failed" from "partial failure".- All TikHub channels now raise
PermanentErroron item-level schema drift (zhihu/xiaohongshu/instagram/weibo/wechat_channels) instead of silently returning[]when items are present but every one fails to parse — caught field renames TikHub deploys without warning. tiebaBaidu safety-verification (captcha) page is now classified asTransientError, notChannelAuthError. Users no longer told to "fix your auth" for platform-side anti-scrape.xiaohongshu/SKILL.mdvia_signsrv.requiresnow matches the env nameautosearch login xhsactually writes (XHS_COOKIES). Login worked, runtime worked, but the requires gate referenced a legacy name nothing wrote.- TikHub hosted-proxy mode actually works end-to-end now.
PR #366 added the requires shim; this release adds the
corresponding
KNOWN_ENV_KEYSentries soprobe_environment()reports the proxy vars and the shim can fire.
MCP runtime
run_channelnow distinguishestransient_error,channel_unavailable, andchannel_error(was allchannel_error). Host agents can backoff vs. retry vs. give up with the right strategy.delegate_subtaskreturnsfailed_channel_detailsper failed channel (status / reason / fix_hint / unmet_requires) instead of squashing into a flat name list. Legacyfailed_channelsfield retained for compat.- Channel health cooldown distinguishes auth/permanent failures (long cooldown — waiting won't help) from transient/rate-limited (short cooldown — try again later).
- Experience layer no longer writes raw user query strings to
~/.autosearch/experience/.../patterns.jsonl. Replaced withquery_shape(length bucket, language detection) so summaries capture pattern info without leaking PII.
Report quality
consolidate_researchpreservespublished_atwhen rebuilding Evidence (was dropped, breaking time-sensitive reports). Heading renamed from "Top findings" to "Top evidence snippets" — these are raw excerpts, not synthesized findings.citation_indexcanonicalizes URLs before dedupe (strip utm_*, fbclid, gclid, fragment, trailing slash, arXiv version suffix). Same source no longer gets multiple citation numbers.
Release plumbing
.claude-plugin/marketplace.jsonmetadata.versionandplugins[0].versionare now synced bybump-version.shand validated bycheck_version_consistency.py. Official Claude plugin tag gates would have failed on the drift.release.ymlrequires PyPI publish success before npm publish — no more npm-only releases whenPYPI_API_TOKENis missing.npx autosearch-aiusers always have a matching Python package.release-gate.shnow verifies.venv/bin/autosearch --versionandpython -m autosearch.cli.main --versionmatchpyproject.tomlvia PEP 440 normalization. Catches stale editable-install console scripts that previously slipped past.
Docs
docs/install.mdClaude Code + Cursor config examples use the correctmcpServers.autosearchshape (was a top-level"autosearch"key that doesn't work).docs/mcp-clients.mdrequired-tools table matches_REQUIRED_MCP_TOOLS;delegate_subtasklisted as required;healthclarified as helper.run_channelschema dropped non-existentmethod_id, addedrationale.researchcorrectly documented as opt-in viaAUTOSEARCH_LEGACY_RESEARCH=1.
Testing
- Live coverage extended to seven free production-critical channels
(
package_search/openalex/crossref/dblp/reddit/google_news/discourse_forum). Addedflaky_livemarker for anti-scrape-prone channels (currentlytieba); nightly default excludes them so platform-side captcha doesn't gate CI.
The "sixth-pass channel-error" release — two more bugs from the
post-.25.1 audit round.
- TikHub hosted-proxy mode now actually works. PR #364 taught
TikhubClientto run in proxy mode (AUTOSEARCH_PROXY_URL+AUTOSEARCH_PROXY_TOKENinstead ofTIKHUB_API_KEY), but every TikHub channel'sSKILL.mdstill hardcodesrequires: [env:TIKHUB_API_KEY], so the MCP boundary's requires check returnedunmet_requires=["env:TIKHUB_API_KEY"]and every TikHub channel surfacedstatus=not_configuredfor proxy users.ChannelRegistry._resolve_requiresnow treatsenv:TIKHUB_API_KEYas satisfied when both proxy vars are present. TikHub-specific shim, documented inline; otherenv:tokens unaffected. - Schema drift no longer hides at intermediate dict levels. The
earlier audits closed the
invalid_payload_shapehole at the finalitems/cardslevel, but the navigation above it still usedpayload.get("data", {})with dict defaults. Whendatawas missing or the wrong type, the default{}silently fell through, the next.get()returned[], and the final shape check saw a valid (empty) list and skipped the raise — schema drift masqueraded as a legitimate empty result. Four channels (zhihu,xiaohongshu,instagram,weibo) now checkisinstance(d, Mapping)at every nesting level and raisePermanentErroron mismatch.
The "fifth-pass channel-error" release — three more audit rounds on top of v8/v9/v10 caught the last remaining paths where upstream failures masqueraded as "no results", plus a P0 MCP stdio bug that was silently corrupting JSON-RPC for every client.
- MCP stdio JSON-RPC was being polluted by structlog on stdout.
autosearch-mcprunstransport="stdio"(stdout = JSON-RPC channel), but structlog's defaultPrintLoggerFactorywrites log lines to stdout. AnyLOGGER.warning(...)inside a channel during arun_channelcall corrupted the stream — clients silently failed or dropped messages.autosearch/mcp/cli.pynow configures structlog toWriteLoggerFactory(file=sys.stderr)at the start ofmain(). The CLI entry point is unaffected — CLI users still see logs on stdout for their terminal. Regression smoke test spawns a realautosearch-mcpsubprocess, triggers a log-producing code path, and asserts every non-empty stdout line parses as valid JSON-RPC. - TikHub proxy-token misconfiguration surfaced as
no_results. WhenAUTOSEARCH_PROXY_URLwas set butAUTOSEARCH_PROXY_TOKENwas missing,TikhubClient()raisedValueErrorwhich every channel swallowed asreturn []. Theexcept ValueErrorsafety net was labeled "redundant" (because SKILL.md requires catches theTIKHUB_API_KEYcase) butPROXY_TOKENisn't in any requires list, so the net was the primary handler and silently ate a real auth failure. Now raisesChannelAuthErrorwhich surfaces asstatus="auth_failed"with a fix hint pointing atautosearch configure AUTOSEARCH_PROXY_TOKEN. - Eight more TikHub channels raise on schema drift instead of
returning
[]. Follow-up audits caught the channels missed by earlier passes —bilibili/zhihu/douyin/tiktok/kuaishou/instagram/weibo/wechat_channels(the unambiguousdata not a Mappingbranch). When TikHub changes payload shape on any of these, the MCP client now getsstatus="channel_error"with the drift reason instead of a fake empty result.wechat_channelskeeps a noted-ambiguous path (if not items: return []) because the recursivedocIDscanner can't distinguish schema drift from a legit zero-result search — a comment flags this for future revisit. - Docs/code drift cleaned up.
docs/mcp-clients.mdnow listsauth_failedandbudget_exhaustedin therun_channelstatus table (they've been emitted since v8 but the doc never caught up) and removes the fictionalretry_afterfield from the troubleshooting section —ChannelToolResponsehas never had that field. - Test-isolation fix.
tests/unit/test_e2b_orchestrator_imports.pyregistered loaded modules under bare stdlib names (sys.modules["secrets"]), hijacking stdlib for every later test. This silently broketests/channels/ddgs/test_api.pyin the full test run. Prefixed registration name to avoid the collision.
The "fourth-pass fallback" release — seven more paths that masqueraded upstream failures as "no results", surfaced by a follow-up audit of the v8 fixes.
- XHS 300011 account-flag raise was eaten by an outer
try/except Exception: pass. The v8 release addedraise ChannelAuthErrorfor the account-restricted case but the raise lived inside the health-checktryblock, so the typed error was swallowed and the channel still returned[]. Restructured the health check so the raise fires outside the swallow. Regression test added. ChannelAuthErrorno longer short-circuits the channel fallback chain. It inheritsPermanentError, so the registry'sexcept PermanentError: raisewas re-raising it immediately — the paid TikHub backup never got a chance to run when the primary method's cookie was bad. Added a dedicatedexcept ChannelAuthErrorbranch that records health-failure, stashes the error inlast_retryable, and continues to the next method. If every method exhausts,last_retryablestill surfaces so MCP reportsauth_failed.- TikHub payload-shape drift (Twitter, Xiaohongshu) now raises
PermanentError. Tworeturn []paths were masking schema changes at the provider as silent empty results. Now surfaces aschannel_errorso the user knows to file a bug. - v2ex / kr36 broad
except Exception: return []converted toraise_as_channel_error. HTTP 5xx, network errors, and schema drift were all collapsed into a single fake empty result. Now get classified intoTransientError/PermanentError/RateLimited/ChannelAuthErrorby the shared adapter. npx autosearch-ai --versionruns the version-skew check. The--versionshort-circuit was returning beforecheckVersionAlignment()could fire, so users filing bugs never saw the wrapper/CLI drift warning the v8 release added.scripts/validate/test_experience_e2e.pyuses a real bundled channel. The fakeCHANNEL = "test-experience-channel"caused_runtime_skill_dirto early-return;patterns.jsonlwas never written and the script was always red withFileNotFoundError. Now usesgithub(tempAUTOSEARCH_EXPERIENCE_DIRkeeps the real runtime clean).
The "third-pass diagnostic" release — six follow-up bugs the v8 audit caught that the previous batch missed.
- YouTube failures stop hiding as
no_results. A separateexcept httpx.HTTPStatusErrorbranch inyoutube/data_api_v3.pywas logging "auth_failed" but still returning[], so 401 / 403 / 429 / quota-exhausted looked identical to "no matching videos". Now propagates through the typed-error classifier — same pattern as every other channel. - xiaohongshu / bilibili / linkedin: inner
return []defeated the fallback chain. The registry's fallback chain is supposed to tryvia_tikhubwhen the primary method dies, but it treats[]as success and stops. Three channels had innerexcept: return []that swallowed real failures (signsrv outage, WBI salt fetch failure, Jina HTTP error). All converted to typed-error raises. XHS code 300011 ("account flagged") now raisesChannelAuthErrorwith the rightautosearch login xhsfix hint. - TikHub 401 →
auth_failed, 402 → newbudget_exhaustedstatus. A staleTIKHUB_API_KEY(HTTP 401) used to surface aschannel_errorbecause_error_for_statuslacked a 401 case. And 402 ("top up your wallet") was lumped intorate_limited, which prompted the agent to wait-and-retry instead of telling the user to refill. Distinct typed errorBudgetExhaustednow producesstatus="budget_exhausted". scripts/validate/run_validation.pyexcludes network markers. A tieba/twitter network blip would kill the whole release-validation run because the script ran plainpytest -x -q --ignore=tests/perfwith no marker filter. Fixed.scripts/validate/test_experience_e2e.pyuses the v2 runtime path. It used to patch_SKILLS_ROOT, but runtime experience writes resolve viaAUTOSEARCH_EXPERIENCE_DIR— so the test was reading from the wrong file. Fixed.- Release gate catches
uv.lockdrift. Newuv lockfile freshnessstep inscripts/release-gate.shrunsuv lock --check. Without this gate,uv.lockcould lag pyproject for days; anyuv runwould silently rewrite it and pollute the working tree. Fixed (and ranuv lockto sync to v8 → v9). npmwrapper warns on Python-CLI version skew. It used to accept any installedautosearchregardless of version. Now compares the wrapper'syear.month.dayprefix against the installed CLI and prints an upgrade hint when they diverge — so users with a stale Python install don't silently run an old CLI.
The "every channel stops lying about success" release — finishes the github
pilot from 2026.04.24.7 across all 30+ channel adapters.
- Channels propagate typed failures. Every channel (TikHub-shared and
direct-HTTP alike) now turns network errors / 401-403 / 429 / parse failures
into typed exceptions (
ChannelAuthError,RateLimited,TransientError,PermanentError) that the MCP boundary maps to distinctrun_channelstatuses. A YouTube key gone bad surfaces asauth_failed; a TikHub budget-exhausted surfaces asrate_limited; a network blip surfaces aschannel_error. Real empty results still come back asno_results. - arxiv specifically: an empty atom feed is now a quiet
[](legitimate "no matches").ArxivRateLimitErrorraisesRateLimitedand bozo / parse errors raisePermanentError, so retry logic + circuit breaker can react to the right thing. - Two new helpers in the public API:
autosearch.channels.base.raise_as_channel_error(exc)for direct-HTTP channels, andautosearch.lib.tikhub_client.to_channel_error(exc)for TikHub-routed ones. New channel implementations only need to call the right helper from their broad except block.
The "second-pass diagnostic" release — six follow-up bugs the v6 audit caught that the original fix-plan missed.
- Channels stop lying about success. A 401 / 403 / 429 / schema change used to come back from
run_channelasstatus="no_results", indistinguishable from "nothing matched your query". New typed exceptions (ChannelAuthError, plus the existingRateLimited) propagate from channel adapters to the MCP boundary, whererun_channelnow surfacesstatus="auth_failed"/"rate_limited"/"channel_error"distinctly. github channel piloted; remaining 30+ adapters migrate in follow-up PRs. (#353) autosearch configure --replace KEYactually reaches the running MCP. Previously the file was rewritten but the long-running process kept the staleos.environ[KEY]it had injected on first load, becauseinject_into_env()skipped any key already in env. Newforce=Truemode wipes file-injected values on every fingerprint-triggered runtime rebuild; user-explicitKEY=… autosearch …overrides still win. (#351)autosearch configureandautosearch loginhonourAUTOSEARCH_SECRETS_FILE. Both used to write to the hardcoded~/.config/ai-secrets.envwhile the runtime read fromsecrets_path()— containers, CI, and multi-user installs ended up writing to A and reading from B. Both call sites now usesecrets_path(). (#351)- Cookie writes don't ride bare in shell history.
autosearch login --stdinadded (pipe the cookie in);--from-stringkept for back-compat but emits a deprecation warning + recommends--stdin._write_cookie_to_secretsnowchmod(0o600)after write so cookies aren't world-readable on shared boxes. (#351) npx autosearch-aiworks on Windows. The wrapper used to hardcodebash -c "curl … | bash". It now picks an installer based onprocess.platform: pipx →py -3.12 -m pip --user→python -m pip --useron Windows; the existing curl path on macOS / Linux.--helpand--versionshort-circuit before the install probe so users can inspect without triggering a y/N prompt. (#352)scripts/validate/check_mcp_tools.pyand the perf test follow the v6 contract. Both still expected the deprecatedresearchtool in the default registration list (which v5 made opt-in). The validate script now asserts research is NOT in the default list AND reappears underAUTOSEARCH_LEGACY_RESEARCH=1; the perf test sets the env before constructing the server. (#350)
The "six bugs caught by the product diagnostic" release. All 6 items in
docs/exec-plans/active/autosearch-0424-product-diagnostic-fix-plan.md
are fixed; each landed as a separate minimal-change PR with regression tests.
- Long-running MCP processes pick up
autosearch configure NEW_KEYwithout restart. The sharedChannelRuntimenow computes a cheap fingerprint (secrets-file mtime + presence of 20 channel-relevant env keys) on everyget_channel_runtime()call. When the user adds a new key while Claude Code / Cursor is open, the runtime rebuilds and re-injects secrets into the env, sorun_channel("youtube")no longer disagrees withdoctorin the same process. (#348) autosearch doctorandautosearch init --check-channelsagree on the count. They used to report 37/40 vs 38/40 because they ran two independent availability pipelines; init now delegates todoctor.scan_channelsas the single source of truth. (#346)consolidate_researchno longer marks every item asunknown source.Evidence.to_context_dict()writes the channel name undersource; the compressor now reads eithersourceorsource_channel. Cross-channel grouping and citation tools work again. (#344)recent_signal_fusionactually ranks by date.Evidencecarries an optionalpublished_atfield;to_context_dict()emits it as ISO 8601;arxivchannel pilots the field by parsing the feed's<published>tag. Other channels can opt in incrementally. (#345)citation_*andloop_*MCP tools return structured errors on invalid IDs. Previously a badindex_id/state_idraised a FastMCPToolErrorand crashed the host agent's workflow. Now agents get{"ok": false, "reason": "invalid_index_id" | "invalid_state_id"}and can recover. (#347)- Smoke test asserts the v2 default tool list, not the deprecated
researchtool. v2026.04.24.5 hidresearchby default but the stdio smoke test still expected it; CI red on every push. Fixed. (#343)
The "trim, gate, and stop tempting LLMs" release.
- The deprecated
researchMCP tool no longer registers by default. Previously it shipped on every server start and only returned a deprecation response when called — but the attractive name still tempted host LLMs to pick it over the v2 trio. Default tool count drops from 24 → 23. SetAUTOSEARCH_LEGACY_RESEARCH=1to opt in if you really need it; the behavior in opt-in mode is unchanged. scripts/install.shnow supports--dry-run,--no-init, and--version. Enterprise users can preview every command before piping the script into bash, CI can run unattended without the interactiveautosearch init, and you can pin a specific release (--version 2026.04.24.5) instead of always taking latest. Default behavior is byte-identical when no flags are passed.- Windows CI now exercises the v2 runtime experience path. The
cross-platform.ymlworkflow's experience-layer step was still mutating_SKILLS_ROOT(v1 contract); it now setsAUTOSEARCH_EXPERIENCE_DIRand asserts writes against the real runtime path so a Windows-specific path-handling regression actually trips a check. - E2B test matrices stop importing modules that were removed in 2026.04.24.4.
matrix.yamlshipped-imports list dropped 5 deleted module names;matrix-extensions.yaml's F112 channel-failure-isolation phase removed (covered by unit tests againstChannelRuntime);roadmap_r1_r5_commits_existtask removed;tests/e2b/bench/single_channel_bench.pydeleted (132-line v1 bench whose import target no longer exists). Net -269 / +3 lines. - Two new package-content guards:
tests/unit/test_package_contents.pynow also fails the release if any channel ships a seed digest at the legacy<skill>/experience/experience.mdpath (the runtime loader only checks the top-level<skill>/experience.md, so subdir variants were silently dead). Caught and removedlinkedin/experience/experience.md+xueqiu/experience/experience.md1-byte placeholders that had been quietly riding in the wheel.
The "smaller wheel, honest docs" release.
- Wheel surface shrinks ~600 lines. The legacy v1 modules
autosearch/synthesis/(citation + outline + report-rendering helpers) and the emptyautosearch/server/shell are gone from the runtime package. Two new gates intests/unit/test_package_contents.py(test_legacy_v1_modules_not_in_source_tree,test_built_wheel_does_not_ship_legacy_v1_modules) prevent them from sneaking back in. No production caller depended on them; v2 host agents synthesize their own answers. - Docs no longer lie about the contract while leaving the product narrative untouched per owner directive:
README.md/README.zh.mddoctor sample updated from the staleAlways-on (21/21) / Env-gated (0/1) / Login (0/15)to the real tiers (27/27 / API-key 0/11 / Login 0/2).docs/install.mdchannel count39 → 40; the npx note now says it prompts before running install (matching the consent step added in2026.04.24.3).docs/mcp-clients.mdrewritten around the v2 tool-supplier toolkit (10 required tools listed,run_channelschema documented, verification script switched fromcall_tool("research", …)to atools/listcheck + free-channel smoke). The deprecatedresearchtool is no longer the documented happy path.
The "tighten the install path and the release gate" release. Closes the remaining million-user-readiness items where the v2 contract was correct in code but not enforced at the install / release boundary.
npm install -g autosearch-aino longer silently downloads and runs a remote install script. Thepostinstallhook is removed.npx autosearch-ai(the recommended one-line install) still works, but now prints the URL it's about to fetch and waits foryto confirm — pass--yes(or-y) for non-interactive automation. In a non-TTY environment without--yes, it refuses rather than installing silently.- Release gate now runs named contract checks even in
--quickmode.scripts/release-gate.shadds an explicit "contract gates" step that lists each plan §Gate A-G (plus the P0-5/6 invariants) by name. A regression in secrets visibility, MCP redaction, channel availability, runtime health persistence, rate-limit enforcement, or wheel content now produces a contract-named failure banner instead of blending into the 800-test default suite. Gate E (docs contract) deferred pending the narrative refresh. - E2B matrix contract test scans every
tests/e2b/*.yaml, not just the main matrix. Cleaned residual v1 expectations inmatrix-extensions.yaml:stdout_contains: "References"→ topic-surface check, "Use the research tool" prompt → list_skills + run_channel flow. - New
tests/unit/test_package_contents.pygate — fails the release if runtime dependencies pull inpytest/ruff/ etc., if the setuptools package-data glob would ship*.jsonl, if the cross-file version pins drift, or if a built wheel ships runtimepatterns.jsonl.
The "runtime actually does what doctor says" release. Fixes audit findings
against 2026.04.24.1 — configured keys now reach the actual channel call,
doctor stops reporting ghost methods as available, run_channel returns a
precise not_configured (with fix hint) instead of unknown_channel, MCP
responses don't leak secret-shaped strings, circuit-breaker / rate-limit state
persists across calls, and health() returns a useful snapshot.
autosearch configure KEY valueis now visible to the actual runtime. Previouslyconfigurewrote~/.config/ai-secrets.envbut channel methods (youtubedata_api_v3.py,tikhub_client.py) and LLM providers (openai / anthropic / gemini) still calledos.getenv()directly —doctorsaw the key and reportedok, butrun_channelran with no key and returned empty. Now the secrets file is injected intoos.environat MCP-server and CLI startup; explicit env overrides still win.autosearch doctorrejects channels whose impl file doesn't exist. Ten methods acrossbilibili / douyin / github / twitter / xiaohongshu / zhihuwere declared in SKILL.md without ever shipping their.pyfile — doctor still reported them ready. Those ghost methods were removed and doctor now countsimpl_missingas unmet so a half-scaffolded method can't reportok.run_channelfor a known-but-unconfigured channel returnsnot_configuredwithunmet_requires+fix_hint— notunknown_channel. Agents can now ask the user for the missing key instead of falling back to the wrong channel. New response fields:status(ok | no_results | not_configured | unknown_channel | channel_error | rate_limited),unmet_requires,fix_hint.- MCP error responses redact secrets. An upstream library or accidental traceback carrying
Bearer sk-...no longer leaks into thereasonfield ofrun_channel/run_clarify. Sharedautosearch.core.redact.redact()now guards every CLI/MCP boundary; runtime experience events (~/.autosearch/experience/.../patterns.jsonl) also redactquerybefore write. autosearch configureno longer requires the secret on the command line. Default flow prompts with hidden input (no leak to shell history orps). New flags:--stdin(automation),--replace(overwrite existing key). Secrets file is chmod'd to0600after write.- Circuit breaker + rate limits actually fire at runtime. Previously
ChannelHealthwas recreated on everyrun_channelcall so cooldown state evaporated. Now a process-lifetimeChannelRuntimeowns the sharedChannelHealthandRateLimiter. Declaredrate_limit: {per_min, per_hour}in SKILL.md is enforced per-(channel, method)via sliding-window counter; exceeded requests surface asstatus="rate_limited"withretry_afterguidance. - MCP
health()returns a structured snapshot instead of the literal string"ok"— version, tool count, required-v2-tool present/missing, channel counts by status, secrets-file presence (key NAMES only, never values), and the sharedChannelHealth.snapshot().
The "make a fresh install actually work" release. After running autosearch init,
the v2 contract is now honest end-to-end: configured keys take effect, the MCP
client really sees the tools, runtime writes don't pollute the installed
package, and one command tells you what's wrong.
autosearch doctorandautosearch mcp-checkare first-class CLI commands —doctortier-groups channels and tells you the exact one-liner to fix each blocked one;mcp-checkproves all 10 required v2 MCP tools are registered.--jsonemits machine-readable output. Unknown subcommands now error instead of silently routing to the deprecatedquerypath.autosearch configure KEY valueactually takes effect — runtime now reads~/.config/ai-secrets.env(the fileconfigurewrites to), so a freshdoctorrun reflects keys you just added without a shell restart. Process env still overrides the file.autosearch initwrites the right MCP config shape per client — Claude Code and Cursor getmcpServers.autosearch, Zed getscontext_servers.autosearch(and the writer respects Zed's JSONC so your existing font/theme settings survive).init --dry-runpreviews writes without touching files. Backs up corrupt JSON instead of silently overwriting.autosearch mcp-check --client claude|cursor|zed— verifies the named client's config file is shaped correctly, in addition to the server-side tool registry.autosearch diagnostics --redact— copy-pasteable JSON support bundle (version, install method, MCP config presence, tool count, doctor summary). Refuses to run without--redact; scrubs API keys, Bearer tokens, cookies, and secret values before printing.- Runtime writes leave the installed package alone — channel experience and compaction now write to
~/.autosearch/experience/(or$XDG_DATA_HOME/autosearch/experienceif set), never tosite-packages. Bundledexperience.mdfiles remain read-only seeds. - Discourse forum search added (linux.do channel) — bringing the channel count from 39 to 40.
- Channel routing + doctor tier/fix-hint now driven by
SKILL.mdmetadata —tier:andfix_hint:declared in a channel's frontmatter take precedence over inferred defaults; selectors and channels-table generator share the same source of truth. - Circuit breaker is wired into runtime —
_build_channelsnow attachesChannelHealth, so cooldown / failure-rate tracking actually fires andavailable()filters out cooled-down channels.PermanentErrorpropagates correctly (was unreachable due to exception ordering). - OpenAI provider honors
OPENAI_BASE_URL— point any OpenAI-compatible backend at the provider without code changes. - One-command release gate —
scripts/release-gate.shruns version consistency + lint/format + tests + CLI surface in one shot; release.yml uses it before publishing, and pyproject↔npm version mapping comes from a single shared helper. pytest/ruffmoved out of runtime dependencies — installed wheels no longer pull in dev tools. CI installs withpip install -e ".[dev]".
npx autosearch-aiis now the one-command installer — auto-installs and shows init screen on any machine
- New one-command installer:
curl -fsSL https://raw.githubusercontent.com/0xmariowu/Autosearch/main/scripts/install.sh | bash— handles uv/pipx/pip automatically and shows the init screen
- Fixed
npm install -g autosearch-aifailing on Macs where pip3 points to Xcode's Python 3.9 — now detects Python 3.12+ explicitly
npm install -g autosearch-ainow runs init automatically — no second step needed
- README rewritten in Agent-Reach style: pain points first, two install formats (Agent one-liner + npm)
- You can now install AutoSearch with
npm install -g autosearch-ai— no Python setup required - Docs site (docs.autosearch.dev) overhauled: new Quickstart, Channels, and Install pages
- README rewritten to reflect current feature set
autosearch initnow shows ASCII banner, auto-configures MCP for Claude Code / Cursor, and displays Integration Status + "You are all set!" — vibeusage-style install UX
- You can now run
autosearch initto get a tiered channel status report with fix hints for each unconfigured channel autosearch loginsupports 7 platforms: xhs / twitter / bilibili / weibo / douyin / zhihu / xueqiu — with--from-stringfor cookie paste- New channels: xueqiu (雪球 stock search) and linkedin (via Jina Reader, no auth)
- TikHub budget exhaustion now triggers graceful fallback instead of error
- Circuit breaker with failure categories: QUOTA_EXHAUSTED / AUTH_FAILURE / NETWORK_ERROR / PLATFORM_BLOCK — each with independent cooldown
run_channeloutput reduced ~60% in token count viaEvidence.to_context_dict(max_content_chars=500)
Channels — 37 total (+3 new, +4 fixed):
- You can now search Instagram and WeChat Channels (视频号) via TikHub
- Bilibili now uses direct WBI signing (free, no TikHub needed) with TikHub as fallback
- Twitter flat-timeline parsing fixed (was silently returning 0 results)
- XHS now uses two-step TikHub sign flow (
sign→search) — previous endpoints returned 400 - Douyin switched to the working POST search endpoint (16 results)
Search quality:
- EvidenceProcessor is now active in
run_channel: URL dedup → SimHash near-dedup → BM25 rerank. Previously written but never wired in. - New
consolidate_researchMCP tool: compresses multi-channel evidence lists to prevent context overflow in long research sessions
Search modes:
- New
list_modesMCP tool: discover 5 built-in search modes (academic / news / chinese_ugc / developer / product) run_clarifyauto-detects query intent and injects channel priority/skip from the matched mode- User-customizable via
~/.config/autosearch/custom_modes.json
Video transcription:
- New
video-to-text-bcutskill: Bilibili Bcut API (free, no key needed, word-level timestamps — more precise than Whisper)
Signing Worker (Cloudflare):
POST /sign/bilibili— WBI signing with KV-cached salt, cron refresh every 2hPOST /sign/xhs— TikHub sign + local X-s-common (saves per-call sign cost)- Rate-limit: 1000 requests/day per service token
- Self-hosted:
autosearch-signsrv.autosearch-dev.workers.dev
E2B test suite expanded:
- Phase 1: 59 scenarios, 96.3/100 🟢 (install diversity, channel quality, error handling, AVO evolution, report quality, Windows emulation)
- Phase 2: 126 scenarios, 84.3/100 🟢 (desktop GUI, search quality judge, channel reliability, stress, experience effectiveness, TikHub pathfinding, cross-platform)
Cleanup:
- Deleted HTTP server (
autosearch serve, 577 lines) — v2 is MCP-first, the endpoint was callingPipeline.run()→NotImplementedError TikhubClientretry logic deduplicated (get()/post()→ shared_execute(), −45 lines)- Cross-platform CI: Windows + macOS runners, Python 3.11 reverse-compat test
This is the first production release of AutoSearch v2 tool-supplier architecture.
Quality gates passed:
- Gate 12 bench: augmented vs bare win rate 51.67% (30 topics × 2 runs, OpenRouter)
- E2B comprehensive test: 91.5/100 🟢 READY (18/20 scenarios, 7 categories)
- Real channel searches: pubmed (10 results), dockerhub (10 results), hackernews, arxiv, ddgs ✅
- Full golden path: clarify → delegate_subtask → citation_index → OpenRouter report ✅
- AVO evolution cycle (Rule 22): all 12 tests pass ✅
- pytest suite: 750+ tests passing
What's new in v2 (vs legacy pipeline):
/autosearchnow uses v2 tool-supplier flow:run_clarify → select_channels → run_channel → synthesize- 21 MCP tools: run_clarify / run_channel / list_skills / list_channels / doctor / select_channels_tool / delegate_subtask / loop state / citation index / 5 workflow skills
- Experience layer: each channel accumulates
patterns.jsonl→ auto-compacts toexperience.md→ injected into next search - 35 channels including new: pubmed (free), dockerhub (free), searxng (local), tieba (Chinese UGC)
- Clarify wizard: 4-step
AskUserQuestionflow withquestion_optionsfor structured choices autosearch doctor/autosearch configureCLI tools
- Release quality test suite: G1 static checks (version consistency, SKILL.md format, experience dirs), G2 mock tests (arxiv/ddgs/hackernews/youtube/tieba + clarify wizard + experience injection), G3 smoke tests (doctor/list_channels/configure), G4 live integration (9 channels, nightly CI), G5 E2E flow (fast/clarify/deep/experience, all mock), G6 AVO evolution (12 tests covering full 6-step Rule 22 cycle), G7 pre-release checklist script.
ClarifyToolResponse+ClarifyResult+Clarifiernow carryquestion_options: list[str]for structuredAskUserQuestionUI.- 56 SKILL.md files: added
# Quality Barsection (CLAUDE.md rule 18). - All 34 channel experience dirs initialized with empty
patterns.jsonl. - New pytest marks:
live,e2e,avo.
- You can now run
autosearch doctor(via MCP) to scan all channel health — shows which channels are ready, missing API keys, or unavailable. - You can now run
autosearch configure KEY valueCLI to safely append API keys to~/.config/ai-secrets.envwith TTY confirmation. - New MCP workflow tools:
trace_harvest(extract winning query patterns),perspective_questioning(multi-viewpoint sub-questions),graph_search_plan(parallel DAG batching),recent_signal_fusion(recency filter),context_retention_policy(token-budget trim). - New channels:
pubmed(PubMed E-utilities, free),dockerhub(Docker Hub public search, free),searxng(local SearXNG meta-search, requiresSEARXNG_URL). - New tool skill:
fetch-firecrawl(URL → Markdown via Firecrawl API, requiresFIRECRAWL_API_KEY, degrades to warn when key missing).
autosearch queryCLI now exits immediately with a v2 deprecation notice directing you tolist_skills / run_clarify / run_channelMCP tools.pipeline.pyandsynthesis/report.pyphysically deleted — v2 tool-supplier is now the only research path.
- You can now use
/autosearchwith the v2 tool-supplier flow: run_clarify → channel selection → run_channel → runtime AI synthesizes. Legacy pipeline no longer invoked. - Per-skill experience layer: each channel now records search outcomes in
experience/patterns.jsonland surfaces a compactedexperience.mddigest before the next call — skills grow smarter over time. - New MCP tools:
select_channels_tool(group-first channel routing),delegate_subtask(parallel multi-channel search),loop_init/update/get_gaps/add_gap(reflective loop state),citation_create/add/export/merge(cross-channel citation deduplication).
fetch-jinaskill: Jina Reader URL-to-Markdown fetcher. Free, no auth, best for articles/docs. First fast-path of v2 fetch layer.yt-dlpdependency (>=2026.3.17): audio/video extraction for v2 video-to-text skills (bilibili / youtube / douyin / xiaoyuzhou) and media download utilities.video-to-text-groqskill: yt-dlp + Groq Whisper API transcription (free tier). First of the v2 transcription trio; returns raw text + SRT + metadata. Summary is caller's responsibility (tool supplier principle).video-to-text-openaiskill: yt-dlp + OpenAI Whisper API transcription (paid, ~$0.006/min). Second of the v2 transcription trio; paid fallback when Groq is rate-limited. Same output shape asvideo-to-text-groq.video-to-text-localskill: yt-dlp + localmlx-whispertranscription (Apple Silicon, offline, free). Third of the v2 transcription trio; opt-in advanced path for M-series Macs with mlx-whisper installed. Default modelmlx-community/whisper-large-v3-turbo, overridable viaAUTOSEARCH_MLX_WHISPER_MODEL.fetch-crawl4aiskill: deep URL fetch viacrawl4ai(Playwright-backed) for JS-rendered pages, anti-bot sites, and dynamic content. Slower thanfetch-jinabut handles pages that block simple fetchers. Opt-in (user installscrawl4ai+playwright install chromiumseparately; not a default autosearch dep to keep the core lightweight).fetch-playwrightskill: documentation-only skill routing the runtime AI to Microsoft's official@playwright/mcpserver for interactive browser automation (click, type, wait, screenshot, navigate). No autosearch-side Python; the runtime AI calls the MCP tools directly. Install via one MCP-client config block, no API key.mcporterskill: documentation-only routing skill that exposes a curated set of free third-party MCP servers (Exa semantic web search, Weibo, Douyin, Xiaohongshu, LinkedIn) to the runtime AI via the upstreammcporterrouter. Free fallback path before paid TikHub for Chinese UGC and a free semantic-search alternative to Exa/Tavily.autosearch:router+ 14 group index files (progressive disclosure L0 + L1). Router reads at session start (short); runtime AI picks 1-3 groups per task and only then reads the matching group indexes. 14 groups: channels-chinese-ugc / channels-cn-tech / channels-academic / channels-code-package / channels-market-product / channels-community-en / channels-social-career / channels-generic-web / channels-video-audio / tools-fetch-render / workflow-planning / workflow-quality / workflow-synthesis / workflow-growth. Each group index lists its leaf skills with when-to-use / model-tier / auth fields.autosearch:model-routingmeta skill: advisory Fast / Standard / Best tier catalog for all autosearch skills. Tells runtime AI which tier each leaf needs (Fast for ~60 retrieval/normalization skills, Standard for ~20 ranking/extraction skills, Best for ~13 clarify/decompose/synthesize/evaluate-delivery/skill-evolution skills) and when to escalate or de-escalate. Autosearch does not switch models itself; runtime AI is the decision-maker.- Backfill v2 progressive-disclosure metadata (
layer: leaf/domains/scenarios/model_tier: Fast/experience_digest: experience.md) to all 31 existing channel SKILL.md frontmatters (arxiv, bilibili, crossref, dblp, ddgs, devto, douyin, github, google_news, hackernews, huggingface_hub, infoq_cn, kr36, kuaishou, openalex, package_search, papers, podcast_cn, reddit, sec_edgar, sogou_weixin, stackoverflow, tiktok, twitter, v2ex, weibo, wikidata, wikipedia, xiaohongshu, youtube, zhihu). Enables router/group routing to see each leaf's domain + tier without reading the full SKILL.md body. autosearch:tikhub-fallbackmeta skill: advisory decision tree for when the runtime AI should escalate from free native Chinese channels (bilibili / weibo / xiaohongshu / douyin / zhihu) to the paid TikHub fallback. Codifies the "free first, paid only when research-critical" rule, flags Weibo upstream flakiness and Zhihu rate-limit boundaries, and lists 5 covered platforms + what TikHub does NOT cover.- Wave 2 deprecation scaffolding:
deprecated: true+deprecation_noticefrontmatter on 4 legacy prompts (m3_evidence_compaction,m7_section_write,m7_section_write_v2,m7_outline). Deprecation header comments in 3 caller modules (autosearch/core/context_compaction.py,autosearch/core/iteration.py,autosearch/synthesis/section.py). No behavior change — legacy pipeline still runs; wave 3 rewrites entry points and then deletes these. - Gate 12 new bench framing spec (
docs/bench/gate-12-augment-vs-bare.md). New bench comparesclaude -p + autosearch plugin installed(A) vsclaude -p bare(B), measures autosearch as augmentation not adversary. Implementation deferred to wave 3 pendingscripts/bench/judge.pyport to main. - Wave 2 status + wave 3 plan (
docs/proposals/2026-04-22-wave-2-status-and-wave-3-plan.md). Documents what shipped in waves 1-2, why remaining items are deferred, and the W3.1–W3.6 execution sequence (entry-point rewrite → infra port → pipeline removal → first augment-vs-bare bench → experience-layer kick-off). autosearch:experience-capturemeta skill (W3.5 part 1): appends one JSON line per skill execution to<leaf>/experience/patterns.jsonl. Fast tier, no LLM, latency < 50 ms, append-only. Event schema: ts / session_id / skill / group / task_domain / query_type / input_shape / method / environment / outcome / metrics / winning_pattern / failure_mode / good_query / bad_query / evidence_refs / promote_candidate / notes. Privacy rules sanitize PII before capture.autosearch:experience-compactmeta skill (W3.5 part 2): promotes recurring patterns frompatterns.jsonlinto the compactexperience.mddigest (≤120 lines). Triggers on ≥10 new events / >64KB file size / user feedback / session end. Promotion threshold: seen≥3 + success≥2 + last_verified≤30d. Anti-pollution: single success never promotes; user corrections/rubric failures go to Failure Modes only; cold rules expire. Patterns.jsonl rotates toexperience/archive/YYYY-MM.jsonlat 1 MB.scripts/bench/judge.py— pairwise judge for autosearch bench runs (W3.2). Compares two directories of markdown reports (A and B) via Anthropic Claude API (sonnet), randomizes A/B position per pair to suppress position bias, emits per-pair JSON verdicts +pairwise-summary.md+stats.json. Graceful fallback totieon API error, non-JSON response, or malformed verdict. CLI:python scripts/bench/judge.py pairwise --a-dir X --b-dir Y --a-label A --b-label B --output-dir Z [--parallel N] [--model M]. RequiresANTHROPIC_API_KEY. 11 test cases cover success / tie / malformed / api-error / swap ordering / summary stats / markdown render.list_skillsMCP tool (W3.1 first step — tool-supplier entry point). Non-destructively augments the existingresearch()pipeline tool. Returns a structured catalog of all autosearch skills (channels / tools / meta / router) with frontmatter metadata (name, description, layer, domains, scenarios, model_tier, auth_required, cost, deprecated). Filters bygroupanddomain; hidesdeprecated: trueskills by default. Runtime AI callslist_skills()at session start to discover autosearch's surface area without reading 80+ SKILL.md bodies. 11 test cases cover parse / scan / group filter / domain filter / deprecated visibility / MCP registration.run_channelMCP tool (W3.1 second step). Executes a single autosearch channel and returns raw Evidence (slim-dict form) — no synthesis, no compaction. Signature:run_channel(channel_name, query, rationale="", k=10). ReturnsRunChannelResponse{channel, ok, evidence, reason, count_total, count_returned}. Structured error on unknown channel (lists available) or channel exception. Runtime AI: calllist_skills(group="channels")to discover names, then callrun_channel(...)to fetch evidence directly, synthesize in-runtime. 7 test cases cover slim-dict / propagate-exception / registration / unknown-channel / happy-path / channel-exception / model-roundtrip.- W3.2 bench runner:
scripts/bench/bench_augment_vs_bare.py— augment-vs-bare bench driver for Gate 12. For each topic, calls the Anthropic Messages API twice: once with the augmented system prompt (injects the autosearch skill catalog — trio tool names + 10 channel groups + 31 channels), once with the bare system prompt (no autosearch context). Writes paired markdown reports to{output}/a/<topic>-run<N>.mdand{output}/b/<topic>-run<N>.md, ready to feed intoscripts/bench/judge.py pairwise. Approximation of the full E2B-plugin-loading path (boss verification pending); exercises "runtime AI with skill catalog knowledge" vs. "bare runtime AI" directly without needing a sandboxed plugin install. 11 test cases cover yaml loading / API success / error / non-JSON / empty response / prompt content invariants. CLI:python scripts/bench/bench_augment_vs_bare.py --topics scripts/bench/topics/gate-12-topics.yaml --output reports/<date>-augment-vs-bare --parallel 4 --runs-per-topic 1. Topics filescripts/bench/topics/gate-12-topics.yamlshipped with 15 Gate 12 topics spanning Chinese UGC / academic / code / market / English community / time-sensitive categories perdocs/bench/gate-12-augment-vs-bare.md§Hypothesis. - W3.2 select-channels rewrite: new
autosearch:channel-selectionmeta skill with group-first algorithm. Replaces the legacy flat-rankselect-channels(source was in the plugin marketplace, not this repo) with a two-stage pick: select 1-3 groups from the router's 14 group indexes → pick 3-8 leaf channels within those groups. Codifies the boss rule that Chinese queries must retain ≥ 2 chinese-ugc/cn-tech channels regardless of past yield. Includes scoring weights, input/output schema, hard filters, and stage-level boss-rule enforcements. Docs-only skill; runtime AI reads it before fanning outrun_channelcalls. - W3.3 PR E: remove
Pipelineimport + live-instantiation fromautosearch/mcp/server.py._default_pipeline_factory()now raisesNotImplementedErrorinstead of constructing a live Pipeline;create_server(pipeline_factory)type hint loosened toCallable[[], Any] | None. Tests that exercise the legacy env path pass their own stub factory viapipeline_factory=kwarg (autouse fixture already handles this).cli/main.pyandserver/main.pystill import Pipeline for their own factory helpers — a larger refactor deferred (they're single-call sites that already hitPipeline.run()→NotImplementedErrorunder the PR D stub). New tests verify:_default_pipeline_factoryraises;mcp.servermodule has noPipelineattribute. 445 unit tests green. - W3.3 PR D: gut legacy pipeline. Delete 4 modules (
autosearch/core/iteration.py,autosearch/core/context_compaction.py,autosearch/core/delegation.py,autosearch/synthesis/section.py). Reduceautosearch/core/pipeline.pyfrom 751 lines to a ~80-line stub wherePipeline.run()raisesNotImplementedErrorpointing at the v2 trio;Pipeline.__init__accepts any legacy signature for import compat;PipelineEvent+PipelineResultre-exports preserved. Reduceautosearch/synthesis/report.pyfrom 281 lines to a ~40-line stub whereReportSynthesizer.synthesize()raisesNotImplementedError. Keep_bypass_clarify_enabled()helper for backward-compat. Net: ~2500 lines deleted or gutted across 6 files; 437 tests still green (1 CLI test updated to assert new deprecation message). - W3.3 PR C: delete 9 m3/m7 prompt markdown files from
autosearch/skills/prompts/(m3_evidence_compaction, m3_follow_up_query, m3_gap_reflection, m3_gap_reflection_perspective, m3_perspective_labels, m3_search_reflection, m7_outline, m7_section_write, m7_section_write_v2). Replace module-levelload_prompt(...)calls inautosearch/core/iteration.py,autosearch/core/context_compaction.py,autosearch/synthesis/section.pywith empty-string sentinels so imports still succeed — the runtime paths that would use these constants are env-gated behindAUTOSEARCH_LEGACY_RESEARCH=1and will be removed entirely in PR D. Updatetests/unit/test_prompt_loader.pyPROMPT_NAMESlist to drop removed prompts. - W3.3 PR B: delete 22 orphan pipeline-only test files (unit: core/test_context_compaction, core/test_delegation, core/test_perspectives, synthesis/test_section, test_iteration, test_iteration_empty_counts, test_iteration_routing, test_m3_compaction_prompt_preserves_specifics, test_m7_prompt_substance, test_pipeline_channel_error, test_pipeline_channel_scope, test_pipeline_events, test_pipeline_initial_subquery_count, test_pipeline_tokens, test_synthesis; integration: test_full_synthesis, test_iteration_e2e, test_pipeline_clarification_exit, test_pipeline_e2e, test_pipeline_with_session; perf: test_pipeline_large_evidence; real_llm: test_pipeline_demo). Remaining 437 tests stay green. Clears the path for PR C (prompt markdown deletion) and PR D (pipeline internals gut).
- W3.3 PR A: freeze
research()MCP tool to return deprecation response by default (does NOT invoke the legacy Pipeline). Pipeline execution can still be opted-in viaAUTOSEARCH_LEGACY_RESEARCH=1env var for emergency backward-compat or bench. New tests:test_research_default_returns_deprecation_without_pipeline/test_research_legacy_env_opt_in_restores_pipeline_path. Existing pipeline-behavior tests (test_mcp_research_scope.py,test_mcp_server.py) retain green status via autouse monkeypatch fixture that sets the opt-in env var. Prepares the ground for PR B (orphan-test deletion) and PR C (prompt markdown deletion) per the W3.3 plan. - W3.3 pipeline-removal multi-PR plan at
docs/proposals/2026-04-22-w3-3-pipeline-removal-plan.md. Splits the destructive legacy-removal work into 5 sequenced PRs (A freeze research() surface → B delete orphan tests → C delete m3/m7 prompt markdowns → D gut pipeline internals → E delete Pipeline class). Each PR ≤ 1000 lines changed, self-contained, rollbackable. Respects CLAUDE.md "do not take overly destructive actions" by sequencing. Next action after plan merges: boss go for PR A. - Migration guide
docs/migration/legacy-research-to-tool-supplier.md(W3.3 first safe step). Documents how runtime AI moves from the legacyresearch()MCP pipeline to the v2 trio (list_skills+run_clarify+run_channel). Includes minimum migration pattern, quick-research pattern, deep-research composition with wave-3 meta skills, cost comparison, and FAQ. - Runtime
DeprecationWarningonresearch()MCP tool invocation pointing to the migration guide. Legacy pipeline continues to run; the warning surfaces in tool output so integrators notice the v2 path without breaking existing flows. MCP serverinstructionsstring also updated to steer new integrations toward the trio. - 8 new workflow skill candidates landed (W3.6, from v2 proposal §3.7). All docs-only meta skills that codify runtime-AI workflow patterns borrowed from prior art in external deep-research reference repos — they do not add Python code, the runtime AI is the implementer:
delegate-subtask(Standard) — execution contract for isolated sub-tasks (input / budget / output / stop-conditions). Sources: MiroThinker + DeepAgents + deer-flow + DeepResearchAgent.trace-harvest(Standard) — distills successful session trace into promote-candidate experience events. Sources: MiroThinker collect-trace + DeepResearchAgent memory system.reflective-search-loop(Best) — explicit multi-round loop state (gaps / visited / bad_urls / evaluator failures / stop conditions). Sources: WebThinker + node-deepresearch + Scira extreme-search.perspective-questioning(Best) — multi-persona question generation (3-6 stakeholders), union → scope. Source: STORM pre-writing research.citation-index(Standard) — URL canonicalization, dedup, stable citation numbers, subagent merge. Sources: STORM + deepagents.graph-search-plan(Best) — DAG over sub-questions with depends_on edges and parallel execution policy. Source: MindSearch WebSearchGraph.recent-signal-fusion(Standard) — cross-channel time-weighted candidate clustering with platform-spread scoring + anti-collapse guard. Sources: last30days-skill + Scira group mode.context-retention-policy(Fast) — session-level keep-last-k / offload / compact policy with never-compact list. Sources: MiroThinker keep_tool_result + deepagents summarization + deer-flow SummarizationEvent.
run_clarifyMCP tool (W3.1 third step, W3.1 trio complete). Runs the autosearch clarifier on a query without running the pipeline. Signature:run_clarify(query, mode_hint=None). ReturnsClarifyToolResponse{query, ok, need_clarification, question, verification, mode, query_type, rubrics, channel_priority, channel_skip, reason}. Structured error on clarifier exception. Withlist_skills+run_channel+run_clarifyin place, the runtime AI can now drive a full autosearch session end-to-end without touching the legacy m3/m7/iteration/synthesis pipeline — tool-supplier architecture is operational in parallel. 6 test cases cover registration / no-clarify-needed / clarify-needed / exception / model-roundtrip / tool-call-delegation.
- ci: fix codex-autofix-dispatch marker mismatch — loop-prevention guard searched
codex-autofix-dispatch:but write-block emittedcopilot-autofix-dispatch:, so repeat CI failures on the same PR head spammed fresh@copilot please fixcomments. Unified both tocopilot-autofix-dispatch:. - fix(ci): update 6 sync-pack files to v1.4.1 canonical — shellcheck/actionlint/gitleaks/@copilot/tools[] fixes (Closes #208)
- feat(ci): bootstrap AI-native dev environment from sync pack v1.4 (Closes #203)
- docs(mcp): add per-client MCP config guide for Claude Code / Cursor / Zed / Continue; document
research+healthtools and the full input schema. - chore(ci): port E2B validation orchestrator (
run_validation.py,bench_channels.py,bench_variance.py,lib/) into reposcripts/e2b/so nightly/weekly CI workflows stop short-circuiting. Also fixes bench bugs — host-only E2B_API_KEY, null-safe variance summarize, docstring/CLI alignment. - fix(ci): pin e2b nightly/weekly workflow
content-filepathto a concrete date (was a glob peter-evans-create-issue-from-file silently ignored) + add a fallback "failure summary" step so auto-issues always have real content, even when the orchestrator crashed before writing summary.md. - chore(nightly): add
scripts/nightly-local.sh+ macOS launchd / Linux systemd recipes indocs/local-nightly.mdso Gate 13 observation-period evidence can be collected without GitHub Actions secrets. - fix(clarify): add
AUTOSEARCH_BYPASS_CLARIFYenv var so batch / non-interactive callers can proceed pastneed_clarification=trueinstead of halting with CLI exit 2. Unblockszh_tech_moe-class queries in the F203 variance bench. - fix(m7): synthesizer prompt now enforces content-substance rules — concrete specifics (numbers, error codes, benchmarks, issue #s), no generic/meaningless conclusions, no repetition.
- fix(m3): evidence-compaction prompt now preserves specifics verbatim (numbers, error codes, issue numbers, benchmarks, version strings, named entities) instead of collapsing to 5-15 concise bullets. Aligns with the compress-research prompt pattern in open_deep_research.