Skip to content

Semantic Scholar API:Akashic 共用的金鑰與存取方式(往回、往前、相似作品、作者著作、書目查詢) #664

Description

@kiki830621

Problem

Original text:
「我有semantic scolor的api,是不是 /akashic 也可以支援api查詢功能 ?」
— Source: 使用者,2026-09-28(+08:00)對話

使用者有 Semantic Scholar(S2)的 API 金鑰,希望 Akashic 能用它查詢。

目前 Akashic 的外部查詢走 OpenAlex、Crossref、ORCID 與 DOI 解析,全都在 skill 層、經 safari-browser 取得(.claude/rules/web-access-via-safari-browser.md)。Sources/ 沒有 HTTP client(2026-09-28 量:URLSession/URLRequest 0 處)。

S2 是另一個獨立的學術圖譜,而且有幾種能力是現有來源沒有、或正是其他開著的 issue 需要的。本單要定下讓整個 Akashic 共用的 S2 存取方式,讓各個 skill 都能用。#640 是其中一個使用者。

Type

feature

S2 能提供什麼(2026-09-28 量:官方 OpenAPI 規格 graph/v1/swagger.json 與 recommendations/v1/swagger.json)

S2 端點 用途 對應的 Akashic 需求
GET /paper/{paper_id}/references 一篇論文的參考文獻 #640:akashic-work-references(#617)的第三來源
GET /paper/{paper_id}/citations 引用某篇的論文 #620:akashic-work-cited-by(往前追)
GET /papers/forpaper/{paper_id}(Recommendations API) 給一篇論文,回傳相似的論文 #621:akashic-work-connected(相似作品)
GET /author/search、GET /author/{author_id}/papers 作者搜尋與著作清單 #622:akashic-person-works
GET /paper/search/match、POST /paper/batch、GET /paper/{paper_id} 標題比對、批次查詢、單篇查詢 akashic-bootstrap 補書目欄位(現在用 Crossref、OpenAlex)

額度(S2 官方 API 頁):有金鑰時的起始額度是所有端點合計每秒 1 次。

Expected

  1. 定下存取方式。這要先決定,因為它牽動專案規則:
  2. 共用的節流:所有 skill 合計遵守每秒 1 次。多個 skill 或多個 session 同時跑時怎麼協調
  3. 每個使用者 skill 各自接上,不在本單一次做完:akashic-work-references:以 Semantic Scholar references 作為第三來源(API key 經 keychain)(sibling concern from #639) #640、新 skill akashic-work-cited-by(akashic-discovery plugin):往前的引用追蹤——找出引用某篇的論文,產出候選清單由使用者勾選才建檔,絕不自動匯入 #620、新 skill akashic-work-connected(akashic-discovery plugin):依書目耦合與共被引找相似作品,庫內計算優先,產出附連結理由的候選清單、勾選才建檔 #621、新 skill akashic-person-works(akashic-discovery plugin):給一個人找出他的所有著作並補進 library,從 akashic-bootstrap 移出 person → works 路徑 #622、akashic-bootstrap 各自以本單的存取方式為前提
  4. S2 回傳的資料一律是線索,不是寫入依據:依 source-of-truth-over-consent(Akashic 欄位值以文稿本身為最終依歸——文稿與 registry(Crossref/OpenAlex)不一致時的裁決原則 #639、library 沒有機器可讀的成員規則——封閉目錄被往回追誤掛 52 筆,要能在寫入時擋下 #642 定案),書目欄位的依據是作品本身,身分要判定

Actual

Impact

與既有 issue 的關係

待定

  • keychain 的 service handle(由使用者提供;本 issue 不記任何金鑰內容)
  • 存取方式(上面第 1 點)
  • 先接哪一個 skill

Clarity Surface(idd-clarify run 2026-09-28T01:57:47Z)

Type Source Question for you Status
ambiguity 「是不是 /akashic 也可以支援api查詢功能」 你要的是一個自己能直接下的 S2 查詢(例如「查這篇被誰引用」),還是讓既有的 skill 在流程裡用 S2 查資料,或兩者都要? resolved @ 2026-09-28T04:47:10Z (reason: 兩者都要:使用者可直接下的查詢,與 skill 流程中的取用,走同一個接口)
ambiguity 「是否仍經 safari-browser(頁內 fetch),還是改在 akashic CLI 裡直接呼叫」 帶金鑰的 S2 呼叫,可以讓 web-access 規則為它開一個封閉例外、不經 safari-browser 嗎? resolved @ 2026-09-28T04:47:10Z (reason: 要:帶金鑰的 S2 呼叫列為 web-access 規則的封閉例外,不經 safari-browser)
missing-context 「keychain 的 service handle(由使用者提供;本 issue 不記任何金鑰內容)」 S2 金鑰已經存進 keychain 了嗎?service 名稱是什麼? resolved @ 2026-09-28T04:47:10Z (reason: 尚未存入,由使用者自行存入(user-only action)。提案 service semantic-scholar、account default,以值不經呼叫端的對話框寫入)
missing-context 「所有 skill 合計遵守每秒 1 次。多個 skill 或多個 session 同時跑時怎麼協調」 這把金鑰只給這台電腦上的 Akashic 用,還是其他機器或其他工具也會用?(2026-09-28 量:本機其他 repo 沒有原始碼呼叫 S2 API) resolved @ 2026-09-28T04:47:10Z (reason: 只在這台電腦用:節流只需協調本機的 skill/session。其他使用者要用時,由 skill/MCP 提示他們自行設定金鑰)
missing-context 「先接哪一個 skill」 第一個接上 S2 的要是哪一個:#640、#620、#621、#622,還是 akashic-bootstrap? resolved @ 2026-09-28T04:47:10Z (reason: 做成一個共用接口,每個功能都從它取用;本單交付接口本身,#640、#620、#621、#622、#665 各自接上)

Linked-Context Siblings Filed (v2.48.0+ #529)

Filed: #665


Current Status

Phase: implemented(已推送到 main;R4 無 HIGH/MEDIUM;R4 之後的小修未再驗證)
Last updated: 2026-10-07 by idd-verify(R4 與推送紀錄:https://github.com/PsychQuant/Akashic-Library/issues/664#issuecomment-6023704389)
Dashboard: #664 (comment)

Key Decisions

  • 已推送:修正輪在 main(b089dc73..074a2097,快轉、8 個 commit);pre-push 的建置、全套測試、守衛全過,0 個失敗。推送後量:快取目錄只有 s2-throttle、沒有任何 x-api-key
  • verify 四輪(pai-ensemble,4 lens+DA+Codex):R1 FAIL(4 個 HIGH)→ R2(0 HIGH、9 MEDIUM)→ R3(0 HIGH、7 MEDIUM)→ R4(0 HIGH、0 MEDIUM,26 LOW);R4 確認 R3 的修正成立。R4 之後的修正(小,文字與錯誤訊息字串)沒有再經 ensemble 驗證(任務 12.6)。整體判定是 FINDINGS(只剩 LOW),不是 PASS,所以沒有打 idd-664-verified
  • 金鑰:使用者 2026-10-06 裁決沿用舊金鑰、不輪替(原話「這用舊的沒官系」,原文如此);那些快取檔已刪。changelog 有給「從公開 main 建置過」的人的影響窗口提醒(2026-09-29 到這次推送之間)
  • S2 的取得順序(使用者 2026-09-29 裁決「有 key 走 key,沒 key 最後才用 safari-browser」;R3、R4 後補完):看 keychain.present/readable,不只看結束碼——都是 true → 接口;present 為 false(keychain 明確說找不到)→ 請使用者自己存、最後才經 safari-browser 不帶金鑰查;present 為 true 但讀不到(鎖著、權限、內容壞、不明錯誤)或其他結果 → 停下回報,不退到頁面;查詢本身回 3/1/64 時重跑 status --json 再選路。錯誤訊息分不出「鎖著」與「權限」(同一個狀態碼):先解鎖、仍讀不到才查權限。解鎖、刪除、重存都是使用者自己在 Terminal 的動作
  • 實作完成:spectra change semantic-scholar-interface 14/14;實機驗證通過(真金鑰查得 Hamaker 等 2015)
  • 實作中修改 artifacts 五處(base URL 覆寫時不讀 keychain、blockedUntil、錯誤在擲出端清理、環境覆寫回 1、parity 守衛的名稱 regex),詳見 Implementation Complete
  • spectra-discuss 收斂(2026-09-29):新 library target AkashicS2,CLI akashic s2 與 MCP akashic_s2 直接呼叫、不經 AkashicService;八個端點一次做完
  • 金鑰:keychain semantic-scholar/default,程序內非互動讀取,只對 api.semanticscholar.org 帶 x-api-key;讀不到就停下並指向設定文件
  • 節流:全機每秒至多 1 次,429 退避共用,同一請求最多重試 3 次
  • Complexity = Spectra;否決 skill 層 shell+curl 與 safari-browser 頁內 fetch

Scope Changes

Blocking

Tasks

  • 1.1 在 Package.swift 新增 library target AkashicS2(依賴 AkashicCore)與 test target AkashicS2Tests,讓 akashic 與 akashic-mcp 依賴 …
  • 2.1 [P] 先寫測試再實作 S2KeyProvider:以 Security framework(kSecUseAuthenticationContext 搭配 interactionNotAllowed = true 的 `LAContext …
  • 2.2 先寫測試再實作 S2Client 的 host 規則與錯誤分類:x-api-key 只附給 https://api.semanticscholar.org,loopback 覆寫一律不帶;404 回報找不到的識別碼,其他 4xx、5xx、連 …
  • 3.1 [P] 先寫測試再實作 S2Throttle 的時段預約:以 flock 鎖住狀態檔、讀寫 nextAllowedAt、解鎖後才等待;存的時間比現在晚超過 60 秒時視為過期並從現在重設;狀態檔預設在 `~/Library/Caches/a …
  • 3.2 先寫測試再實作 429 退避與重試:把共用的 nextAllowedAt 推到「現在+Retry-After」(秒數或 HTTP-date),沒有 header 時依序等 2、4、8 秒,同一請求最多重試 3 次,Retry-After 超 …
  • 4.1 先寫測試再實作八個端點的請求組裝與分頁(S2Endpoints):以 10. 開頭的裸 DOI 補上 DOI:、id 百分比編碼、batch 至多 500 個 id、references/citations/author-papers 翻頁 …
  • 4.2 [P] 先寫測試再實作 S2Output:S2 回應中的每個字串遞迴經過 displaySafe;依傳入的位元組上限只保留完整筆數,回報 returned、truncated、nextOffset(Requirement「Text …
  • 5.1 先寫測試再實作 akashic s2 子命令群:八個端點各一個子命令,外加 status(design「每個端點一個具型別子命令」);--json 信封含 source、endpoint、request、fetchedAt( …
  • 5.2 跨程序節流驗收:兩個 akashic 子程序共用同一個 AKASHIC_S2_STATE_DIR,各送 3 個請求到 loopback stub(Requirement「Requests are throttled machine-wide」) …
  • 6.1 先寫測試再在 Sources/akashic-mcp/Server.swift 註冊 akashic_s2,在 async 的 CallTool handler 內分流:akashic_s2 走 async 的處理函式,其餘工具照舊走同 …
  • 7.1 [P] 先寫負對照 akashic-guards network-confinement-mutations(RED),再寫 akashic-guards network-confinement,並在 `Sources/akashic-guar …
  • 8.1 [P] 改寫 .claude/rules/web-access-via-safari-browser.md:第 2 條改為只有 Sources/AkashicS2/ 例外;例外清單從一類改為兩類(帶金鑰的 S2 呼叫經 akashic s2 …
  • 8.2 [P] 寫設定文件 plugin/skills/akashic-bootstrap/references/semantic-scholar.md(存金鑰的指令、ACL 取捨、以 akashic s2 status 確認、結束碼 3 的兩種原因) …
  • 8.3 整體驗證:swift build 與 swift test 全綠,且 RealHomeSandboxGuard 未報錯;bash .githooks/run-guards.sh 全綠;`spectra validate semantic …
  • 9.1 連線不快取、不跟隨轉址:預設連線改為 ephemeral(urlCache、cookie 儲存為 nil),每個請求帶不快取、不處理 cookie,task delegate 把 3xx 當最終回應;測試 `S2SessionHardeningTe …
  • 9.2 429 共用與狀態檔:放棄之前先記退避、長退避有自己的過期門檻(最多一小時)、其他呼叫者對超過 60 秒的封鎖快速失敗(結束碼 4);狀態檔不跟隨 symlink、收緊到 0600、errno 先取走
  • 9.3 續查契約:S2Result.hasMore 取自 S2 的 next;不分頁的端點與空的一頁 nextOffset 為 null;第一筆就超過 48 KiB 回錯誤並點名 fields;MCP limit 預設 100、至多 100 …
  • 9.4 JSON 面的清理改為字串原樣+序列化後無損逃脫(documentSafeJSON);位元組上限量實際輸出
  • 9.5 其餘程式修正:空白 --title/--name 回 64、--ids-file 大小上限與識別碼形狀檢查、金鑰錯誤訊息帶可照做的指令並先講「keychain 鎖著」
  • 9.6 規則、規格與文件:取得順序補「其他結果停下回報」、mcp-cli-parity 例外改封閉列舉、-T 兩個 binary、skill/agent 不得直接讀 keychain 項目、akashic_s2 附在 tools 陣列最後、prop …
  • 10.1 連線層的保證:逐請求的 cachePolicy 擋不住寫入(R2 實測),所以注入的連線若帶磁碟快取就拒絕(S2Client.isCacheFree);預設連線全程序共用一個(S2Client.defaultSession,每次新建會在長 …
  • 10.2 Retry-After 封頂一天(Int.max 轉 Int(delay) 會讓整個程序當掉);backOff 先清掉過期的遠期狀態再合併;--ids-file 的上限量讀進來的位元組(/dev/zero 與 FIFO 量屬性 …
  • 10.3 取得順序補洞:結束碼 3 且 keychain.present 為 true(項目在、讀不到)不是沒有金鑰,停下請使用者解鎖或改權限,不退到 safari-browser;skill/agent 不代使用者存金鑰
  • 10.4 文字追上契約:parity 表 akashic_s2 列(續查看 nextOffset、JSON 面無損、結束碼清單、MCP 專有的三項限制)、README、規格的過期狀態情境、設定文件的過期門檻與 recommend 的建議、`netw …
  • 10.5 追蹤與記錄:「不跳授權框」的人工實機驗證追蹤在 S2:非互動 keychain 讀取「不跳授權框」尚未在實機驗證(一次性的人工驗證) #725;金鑰輪替(使用者 2026-10-06 裁決沿用)、AKASHIC_S2_STATE_DIR 正式環境也接受、硬連結、nextOffset 以筆數計、預約時段的 60 秒門檻,都記進 …
  • 11.1 結束碼 3 的路由:present 只在 keychain 明確回答找不到時是 false(itemMayExist(forAttributeStatus:),有單元測試);取得順序改成看 present/readable,不只看結束 …
  • 11.2 使用者自己的動作:解鎖(security unlock-keychain,不加 -p)與重存都是使用者在自己 Terminal 的事,登入密碼與金鑰不進對話;缺金鑰與讀不到的錯誤訊息都這樣寫
  • 11.3 S2Client 拒絕帶磁碟快取的注入連線改為 send 的錯誤(S2Error.unsafeSession),不再 precondition;有測試
  • 11.4 Retry-After 比 Int 還大的數字視為封頂值,不是「沒給」;backOff 寫進狀態檔的 blockedUntil 有測試;被拒的識別碼不回顯內容;缺金鑰訊息拆成多行(plugin 安裝處的路徑不再被行長上限截掉)
  • 11.5 plugin/CHANGELOG.md 與 changelog/2026-10-06-s2-interface-664.md;「看過、沒有修」表更正兩條站不住的理由,並補上暴露期
  • 11.6 R3 之後的修正已在 R4 驗證(見下一組)
  • 12.1 我引入的回歸:akashic s2 --help 與 MCP 工具描述補回 plugin 安裝處的設定文件位置
  • 12.2 路由文字照實:錯誤訊息分不出「鎖著」與「權限」(同一個狀態碼)——先解鎖、仍讀不到才查權限;查詢本身回結束碼 3/1/64 時重跑 status --json 再選路;「其他結果」補上 MCP status 的 isError 與 `BA …
  • 12.3 錯誤訊息:刪除與重存的「agent 不代刪、代存」、invalidValue 把 -U 指令印出來、不明的 keychain 錯誤指向文件並說明不是「沒有金鑰」、解鎖是否跨工作階段的提醒(未實測,併進 S2:非互動 keychain 讀取「不跳授權框」尚未在實機驗證(一次性的人工驗證) #725)
  • 12.4 規格補 present 的語意與兩個情境;Retry-After 的句子改成 min(delay, 1 hour);design 更正「不叫使用者重存」、--ids-file 的不做理由(承認第三方機密的殘餘風險)、「只有那一筆」限定 …
  • 12.5 追蹤:五個小決定開成 S2 接口:五個看過、沒有修的小決定(#664 verify 留下的) #727;changelog 補「給從公開 main 建置過的人」的影響窗口提醒
  • 12.6 R4 之後的修正(小,多為文字與錯誤訊息字串)沒有再經 ensemble 驗證;推送時 pre-push 會跑全套測試

Commits

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew capability

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions