/cypher/search 說零件不存在,但那顆零件在同一台實例上跑得動——害人誤判成「缺零件」 #88

Open
opened 2026-08-11 11:52:39 +00:00 by Leo · 3 comments
Owner

發現者:arcrun-rag 出貨線(Leo/arcrun-rag#77)。這個不一致直接害我做出三次錯誤結論,所以先開它。

現象(leo21c 實測 2026-08-11)

POST /cypher/search 對這些名字全回 not_found
if_controlswitchconditionbranchassert_equalscomparejson_pathdata_transformvalidatefilter
——http_request 也回 not_found

但同一台實例上:

  • 已部署的工作流正在用 http_request,跑得好好的
  • 我部署一個只有 if_control 的探測工作流,它正常運作
    觸發 {"v":"yes"} → {"data":{"branch":"true","result":true},"success":true}
    觸發 {"v":"no"}  → {"data":{"branch":"false","result":false},"success":true}
    
    (探測件用完已刪)

搜尋索引與執行期不一致:搜尋說沒有,執行期有。

為什麼這個要優先修

/cypher/searchnot_found 回應會附一句建議:

「兩庫都查過,零件 registry 與 recipe 庫皆無⋯⋯缺計算能力 → 投稿零件 PR」

這句話在這個情況下是錯的指引,而且它很有說服力。我照著它做出的錯誤結論:

  1. 把 11 個出貨站標成「缺零件」——實際上判斷零件一直都在
  2. ship_check_live 裡的 code 節點辯護說「這台沒有比對零件可用」——那是替 D70 的腹語術找到了一個假藉口
  3. 差點開一張「缺比對/分支零件」的投稿票(開之前實測才發現不必開)

⇒ 一個會主動建議你去自幹的錯誤回應,比單純的「查不到」危險得多。

建議的驗收

  • 同一台實例上,/cypher/search 查得到的集合 ⊇ 執行期真的載得動的零件
  • 或者:not_found 的訊息不要直接建議投稿,先提示「這台實例的索引可能沒同步,請先實測」
發現者:arcrun-rag 出貨線(`Leo/arcrun-rag#77`)。**這個不一致直接害我做出三次錯誤結論**,所以先開它。 ## 現象(leo21c 實測 2026-08-11) `POST /cypher/search` 對這些名字全回 `not_found`: `if_control`、`switch`、`condition`、`branch`、`assert_equals`、`compare`、`json_path`、`data_transform`、`validate`、`filter` ——**連 `http_request` 也回 `not_found`**。 但同一台實例上: - 已部署的工作流**正在用 `http_request` 跑**,跑得好好的 - 我部署一個只有 `if_control` 的探測工作流,**它正常運作**: ``` 觸發 {"v":"yes"} → {"data":{"branch":"true","result":true},"success":true} 觸發 {"v":"no"} → {"data":{"branch":"false","result":false},"success":true} ``` (探測件用完已刪) ⇒ **搜尋索引與執行期不一致**:搜尋說沒有,執行期有。 ## 為什麼這個要優先修 `/cypher/search` 的 `not_found` 回應會附一句建議: > 「兩庫都查過,零件 registry 與 recipe 庫皆無⋯⋯缺計算能力 → 投稿零件 PR」 **這句話在這個情況下是錯的指引**,而且它很有說服力。我照著它做出的錯誤結論: 1. 把 11 個出貨站標成「缺零件」——實際上判斷零件一直都在 2. 為 `ship_check_live` 裡的 `code` 節點辯護說「這台沒有比對零件可用」——**那是替 D70 的腹語術找到了一個假藉口** 3. 差點開一張「缺比對/分支零件」的投稿票(開之前實測才發現不必開) ⇒ 一個會**主動建議你去自幹**的錯誤回應,比單純的「查不到」危險得多。 ## 建議的驗收 - 同一台實例上,`/cypher/search` 查得到的集合 ⊇ 執行期真的載得動的零件 - 或者:`not_found` 的訊息不要直接建議投稿,先提示「這台實例的索引可能沒同步,請先實測」
Leo added the
s
todo
p
high
labels 2026-08-11 11:55:47 +00:00
Author
Owner

真正的病因(不是「registry 少幾筆資料」,是兩個系統各查各的)

/cypher/searchcypher-executor/src/actions/search-nodes.ts只查 component registrySUBMISSIONS_KV,經 submitComponentindex-only 才會有記錄)。

if_controlhttp_requestswitchfiltercode…這一整批零件,是 cypher-executor/src/lib/component-loader.ts 在執行期直接解析的(BUILTIN_COMPONENTSLOGIC_BINDING_MAPWASM_HTTP_RUNNER_IDS,見檔案 34-54 行既有的 TODO 自承「白名單寫死」)——這條路徑從不查 registry,也從來沒被 submit 過(它們是 cypher-executor 自帶的,不是投稿存量)。

實測 leo21c 這台實例(https://arcrun-registry.leo21c.workers.dev):

GET /components/catalog → HTTP 404 {"success":false,"error":"零件 catalog 不存在"}
GET /components/if_control → HTTP 404 {"success":false,"error":"零件 if_control 不存在"}

registry 的 /components/catalog 路由(registry/src/routes/query.ts)在目錄空時本該回 200 {success:true,data:{components:[],count:0}}——但這台部署的 registry 版本沒有這條路由,請求落到 /:id 被當成 id="catalog",回 404。search-nodes.tsfetchCatalog() 把 404 解讀成「舊版 registry 沒有 /catalog 端點」→ 退回逐顆查 legacyPerNodeLookup → 每顆都 404 → 誠實地回「兩庫都查過沒有」。這個「誠實」建立在錯的前提上:這批零件本來就不靠 registry 存在,查不查得到都不該用它來判斷有沒有。

(另外查到一個相關但不同的事:arcrun_search_components MCP 工具裡的註解寫「registry 唯一寫入觸發點隨 .github/workflows 移除而蒸發」——這句話不準;system-dev/wiki/status-archive-2026-08.md 07-30 的稽核記錄寫著 deploy.yml 註冊步驟 grep=0,從來沒自動化過,不是「移除」。這點只是路過發現,不影響本次修法,附上供之後清理註解參考。)

改了什麼

不投資 registry 的 backfill(decisions-summary.md D29 已定調 SUBMISSIONS_KV 併入「KV 退休戰」,不宜再加),也不掃 registry/components/* 目錄當清單來源(那含已標記待刪的死碼 km_writerkbdb_upsert_block,07-30 就是因為掃目錄誤灌進 registry 才出的錯)。

改成:把 component-loader.ts 本來就有的「執行期真正拿去 resolve 的白名單」(BUILTIN_COMPONENTSLOGIC_BINDING_MAPWASM_HTTP_RUNNER_IDStrigger_workflow)匯出成 RUNTIME_NATIVE_COMPONENT_IDSsearch-nodes.ts 在查 registry 之前先比對這份清單,命中就直接 foundsource:'builtin'),不受 registry 可達性/是否已 backfill 影響。這不是新造一份清單,是把既有唯一真相源(執行期 resolver 自己的白名單)重用出去,避免 search 端另建一份會漂移的複本。真正不存在的名字(不在白名單、也不在 registry)維持原本的 not_foundunknown 誠實回應,分型建議與相似候選機制沒動。

檔案:

  • cypher-executor/src/lib/component-loader.ts(新增 export const RUNTIME_NATIVE_COMPONENT_IDS
  • cypher-executor/src/actions/search-nodes.ts(查 registry 前先比對這份清單)
  • cypher-executor/tests/search-nodes-runtime-native.test.ts(新增,7 case)

實測(目錄怎麼回答 vs 執行期真的動不動,修前/修後各一份)

修前(leo21c 實例,2026-08-11 現場實測,即本票原始症狀):

$ curl -X POST https://arcrun-cypher-executor.leo21c.workers.dev/cypher/search \
    -d '{"triplets":["input >> ON_SUCCESS >> if_control"]}'
→ if_control: status=not_found,suggestion「兩庫都查過,零件 registry 與 recipe 庫皆無…」

$ curl -X POST https://arcrun-if-control.leo21c.workers.dev -d '{"condition":true}'
→ HTTP 200(零件本身活著、跑得動——只是 payload 格式不對才報 invalid input,
   不是「零件不存在」那種 404/找不到)

⇒ 查目錄說沒有,實際零件在跑,正是本票標題描述的落差。

修後(本地 vitest,複現與 leo21c 完全相同的兩種 registry 狀態:連不到/連得到但目錄空):

✓ if_control(LOGIC_BINDING_MAP 成員)在 registry 不可達時仍回 found
✓ http_request(WASM_HTTP_RUNNER_IDS 成員)在 registry 不可達時仍回 found
✓ switch/filter/code(同一批白名單的其他成員)也回 found,不逐一漏網
✓ registry 完全連不到時,真正不存在的名字誠實回 unknown(既有行為,沒被動到)
✓ registry 查得到但目錄是空的(複現 leo21c 實例 catalog 404 的真實症狀):
  真正不存在的名字回 not_found
✓ registry 目錄是空的(catalog 通但無資料)時,執行期原生零件依然 found
  ——這就是 Arcrun#88 的核心場景
✓ target=recipe 明確只查 recipe 庫時,執行期原生零件不搶答 found(尊重明確限庫)

Test Files  1 passed (1)
     Tests  7 passed (7)

全 repo 迴歸(npx vitest run):357 pass(修前 350 pass,多出的 7 個就是新測試);
既有 14 個失敗筆數與內容跟修前完全一樣(跟本次改動無關的既有缺陷:/portal 404、
executor.test.ts 一則錯誤訊息斷言字串不符——都在 stash 前後兩次全跑比對過,
非本次引入)。tsc --noEmit 也做了同樣的修前/修後比對:7 個既有型別錯誤(portal-data.ts
portal.tstypes.ts)修前修後一模一樣,我改的兩個檔零新增錯誤。

還缺什麼(誠實标 ◐,不是

沒有部署到線上——.claude/hooks/main-and-prod-push-guard.sh 擋下了我推分支的動作
(本 repo這支 guard 連 push 自己的 feature branch 都要求交回總管確認,不是只擋 main),
所以這份修法目前只在本機分支 fix/cypher-search-runtime-native-88(commit 525faaf),
還沒有 leo21c 實例上「修後」的即時 curl 對照——上面「修後」那份是本地 vitest 精準複現
leo21c 當下兩種 registry 狀態(連不到/連得到但空)得出的等價證明,不是同一台實例的
直接複驗。照 CP 三態判準,這裡誠實標 ◐ 半通:code 端到端測過、根因抓對、
分支已備妥可審——缺的是「推上分支+部署到 leo21c 這台實例+重跑一次原始那三行 curl」
這最後一步,需要總管過目後推分支,或 leo 手動在 leo21c 側 acr update 部署這顆 worker
才能補齊。

附帶但不在本票範圍內的發現(供另案參考,這次沒有動)

registry 這台實例的 /components/catalog 本身也該修一個小地方:目錄空時該回
200 {components:[],count:0},不該回 404——現在的 404 讓 fetchCatalog() 誤判成
「舊版沒這端點」而不是「有這端點、只是空的」,兩種狀態目前混在一起判斷(no_endpoint
分支)。這不影響本次修法(本次修法讓執行期原生零件完全繞過這段判斷),但如果之後
真的要走 registry backfill(把社群投稿零件也接上 search),這個 404-vs-空陣列的混淆
建議先理清楚,不然「registry 剛裝好、還沒收到任何投稿」跟「registry 版本太舊」會
一直被當成同一種狀況處理。

## 真正的病因(不是「registry 少幾筆資料」,是兩個系統各查各的) `/cypher/search`(`cypher-executor/src/actions/search-nodes.ts`)**只查 component registry**(`SUBMISSIONS_KV`,經 `submitComponent`/`index-only` 才會有記錄)。 但 `if_control`/`http_request`/`switch`/`filter`/`code`…這一整批零件,是 `cypher-executor/src/lib/component-loader.ts` **在執行期直接解析**的(`BUILTIN_COMPONENTS`/`LOGIC_BINDING_MAP`/`WASM_HTTP_RUNNER_IDS`,見檔案 34-54 行既有的 TODO 自承「白名單寫死」)——**這條路徑從不查 registry**,也從來沒被 `submit` 過(它們是 cypher-executor 自帶的,不是投稿存量)。 實測 leo21c 這台實例(`https://arcrun-registry.leo21c.workers.dev`): ``` GET /components/catalog → HTTP 404 {"success":false,"error":"零件 catalog 不存在"} GET /components/if_control → HTTP 404 {"success":false,"error":"零件 if_control 不存在"} ``` registry 的 `/components/catalog` 路由(`registry/src/routes/query.ts`)在目錄空時本該回 `200 {success:true,data:{components:[],count:0}}`——但這台部署的 registry 版本沒有這條路由,請求落到 `/:id` 被當成 `id="catalog"`,回 404。`search-nodes.ts` 的 `fetchCatalog()` 把 404 解讀成「舊版 registry 沒有 `/catalog` 端點」→ 退回逐顆查 `legacyPerNodeLookup` → 每顆都 404 → 誠實地回「兩庫都查過沒有」。**這個「誠實」建立在錯的前提上:這批零件本來就不靠 registry 存在,查不查得到都不該用它來判斷有沒有。** (另外查到一個相關但不同的事:`arcrun_search_components` MCP 工具裡的註解寫「registry 唯一寫入觸發點隨 `.github/workflows` 移除而蒸發」——這句話不準;`system-dev/wiki/status-archive-2026-08.md` 07-30 的稽核記錄寫著 `deploy.yml` 註冊步驟 grep=0,**從來沒自動化過**,不是「移除」。這點只是路過發現,不影響本次修法,附上供之後清理註解參考。) ## 改了什麼 不投資 registry 的 backfill(`decisions-summary.md` D29 已定調 `SUBMISSIONS_KV` 併入「KV 退休戰」,不宜再加),也不掃 `registry/components/*` 目錄當清單來源(那含已標記待刪的死碼 `km_writer`/`kbdb_upsert_block`,07-30 就是因為掃目錄誤灌進 registry 才出的錯)。 改成:把 component-loader.ts 本來就有的「執行期真正拿去 resolve 的白名單」(`BUILTIN_COMPONENTS` ∪ `LOGIC_BINDING_MAP` ∪ `WASM_HTTP_RUNNER_IDS` ∪ `trigger_workflow`)匯出成 `RUNTIME_NATIVE_COMPONENT_IDS`,`search-nodes.ts` 在查 registry **之前**先比對這份清單,命中就直接 `found`(`source:'builtin'`),不受 registry 可達性/是否已 backfill 影響。這不是新造一份清單,是把既有唯一真相源(執行期 resolver 自己的白名單)重用出去,避免 search 端另建一份會漂移的複本。真正不存在的名字(不在白名單、也不在 registry)維持原本的 `not_found`/`unknown` 誠實回應,分型建議與相似候選機制沒動。 檔案: - `cypher-executor/src/lib/component-loader.ts`(新增 `export const RUNTIME_NATIVE_COMPONENT_IDS`) - `cypher-executor/src/actions/search-nodes.ts`(查 registry 前先比對這份清單) - `cypher-executor/tests/search-nodes-runtime-native.test.ts`(新增,7 case) ## 實測(目錄怎麼回答 vs 執行期真的動不動,修前/修後各一份) **修前(leo21c 實例,2026-08-11 現場實測,即本票原始症狀):** ``` $ curl -X POST https://arcrun-cypher-executor.leo21c.workers.dev/cypher/search \ -d '{"triplets":["input >> ON_SUCCESS >> if_control"]}' → if_control: status=not_found,suggestion「兩庫都查過,零件 registry 與 recipe 庫皆無…」 $ curl -X POST https://arcrun-if-control.leo21c.workers.dev -d '{"condition":true}' → HTTP 200(零件本身活著、跑得動——只是 payload 格式不對才報 invalid input, 不是「零件不存在」那種 404/找不到) ``` ⇒ 查目錄說沒有,實際零件在跑,正是本票標題描述的落差。 **修後(本地 vitest,複現與 leo21c 完全相同的兩種 registry 狀態:連不到/連得到但目錄空):** ``` ✓ if_control(LOGIC_BINDING_MAP 成員)在 registry 不可達時仍回 found ✓ http_request(WASM_HTTP_RUNNER_IDS 成員)在 registry 不可達時仍回 found ✓ switch/filter/code(同一批白名單的其他成員)也回 found,不逐一漏網 ✓ registry 完全連不到時,真正不存在的名字誠實回 unknown(既有行為,沒被動到) ✓ registry 查得到但目錄是空的(複現 leo21c 實例 catalog 404 的真實症狀): 真正不存在的名字回 not_found ✓ registry 目錄是空的(catalog 通但無資料)時,執行期原生零件依然 found ——這就是 Arcrun#88 的核心場景 ✓ target=recipe 明確只查 recipe 庫時,執行期原生零件不搶答 found(尊重明確限庫) Test Files 1 passed (1) Tests 7 passed (7) ``` 全 repo 迴歸(`npx vitest run`):357 pass(修前 350 pass,多出的 7 個就是新測試); 既有 14 個失敗筆數與內容跟修前完全一樣(跟本次改動無關的既有缺陷:`/portal` 404、 `executor.test.ts` 一則錯誤訊息斷言字串不符——都在 stash 前後兩次全跑比對過, 非本次引入)。`tsc --noEmit` 也做了同樣的修前/修後比對:7 個既有型別錯誤(`portal-data.ts`/ `portal.ts`/`types.ts`)修前修後一模一樣,我改的兩個檔零新增錯誤。 ## 還缺什麼(誠實标 ◐,不是 ✅) **沒有部署到線上**——`.claude/hooks/main-and-prod-push-guard.sh` 擋下了我推分支的動作 (本 repo這支 guard 連 push 自己的 feature branch 都要求交回總管確認,不是只擋 main), 所以這份修法目前只在本機分支 `fix/cypher-search-runtime-native-88`(commit `525faaf`), **還沒有 leo21c 實例上「修後」的即時 curl 對照**——上面「修後」那份是本地 vitest 精準複現 leo21c 當下兩種 registry 狀態(連不到/連得到但空)得出的等價證明,不是同一台實例的 直接複驗。照 CP 三態判準,這裡誠實標 **◐ 半通**:code 端到端測過、根因抓對、 分支已備妥可審——**缺的是「推上分支+部署到 leo21c 這台實例+重跑一次原始那三行 curl」** 這最後一步,需要總管過目後推分支,或 leo 手動在 leo21c 側 `acr update` 部署這顆 worker 才能補齊。 ## 附帶但**不在本票範圍內**的發現(供另案參考,這次沒有動) registry 這台實例的 `/components/catalog` 本身也該修一個小地方:目錄空時該回 `200 {components:[],count:0}`,不該回 404——現在的 404 讓 `fetchCatalog()` 誤判成 「舊版沒這端點」而不是「有這端點、只是空的」,兩種狀態目前混在一起判斷(`no_endpoint` 分支)。這不影響本次修法(本次修法讓執行期原生零件完全繞過這段判斷),但如果之後 真的要走 registry backfill(把社群投稿零件也接上 search),這個 404-vs-空陣列的混淆 建議先理清楚,不然「registry 剛裝好、還沒收到任何投稿」跟「registry 版本太舊」會 一直被當成同一種狀況處理。
Author
Owner

2026-08-12 上午(總管):併進 main 了,但還沒推上 Gitea

逐筆審過+跑過測試,已合併到 matrix/arcrun本機 main

  • 8cee9c9 merge #88(cypher-executor:357 pass/14 fail,與 main 的 14 個既有失敗完全相同)
  • 3eb8b31 merge #85(kbdb:196 → 197 pass/0 fail)
  • 8e10f1d 重編 .worker-builds 官方成品——這一筆很重要:在它之前,成品記的來源
    commit 比源碼舊(cypher 797e7f7 vs 525faaf、kbdb a7e23ba vs 3eb8b31),
    也就是「修好了但執行檔還是舊的」。沒有任何閘會講這件事 ⇒ 已開 Arcrun#93

🔴 卡住的地方:推 main 到 Gitea 被本次 session 的權限閘擋下(造不出總管戳記)。
這件事本身是總管的權限(leo 08-10:「是否可以推 gitea main 由你來決定」),
所以不是規則上的人閘,是這台機器上的權限設定。

在推上去之前,leo21c 拿不到這兩張票的修法——acr update 抓的是
git.uncle6.me/api/v1/repos/Leo/Arcrun/archive/main.tar.gz
cli/src/lib/deploy.ts:95cli/src/commands/update.ts 寫死 ref='main'),不是任何 release

## 2026-08-12 上午(總管):併進 main 了,但**還沒推上 Gitea** 逐筆審過+跑過測試,已合併到 `matrix/arcrun` 的 **本機 main**: - `8cee9c9` merge #88(cypher-executor:357 pass/14 fail,與 main 的 14 個既有失敗完全相同) - `3eb8b31` merge #85(kbdb:196 → 197 pass/0 fail) - `8e10f1d` 重編 `.worker-builds` 官方成品——**這一筆很重要**:在它之前,成品記的來源 commit 比源碼舊(cypher 797e7f7 vs 525faaf、kbdb a7e23ba vs 3eb8b31), 也就是「修好了但執行檔還是舊的」。沒有任何閘會講這件事 ⇒ 已開 `Arcrun#93`。 🔴 **卡住的地方**:推 `main` 到 Gitea 被本次 session 的權限閘擋下(造不出總管戳記)。 這件事本身是總管的權限(leo 08-10:「是否可以推 gitea main 由你來決定」), 所以不是規則上的人閘,是這台機器上的權限設定。 ⇒ **在推上去之前,leo21c 拿不到這兩張票的修法**——`acr update` 抓的是 `git.uncle6.me/api/v1/repos/Leo/Arcrun/archive/main.tar.gz` (`cli/src/lib/deploy.ts:95`、`cli/src/commands/update.ts` 寫死 ref='main'),**不是任何 release**。
Author
Owner

更正:上一則「還沒推上 Gitea」已經過時——leo 不用做任何事(2026-08-13 複驗)

那則(08-12 01:53)同時貼在本票與 Leo/Arcrun#85,內容一樣。總管今天逐筆驗過:

8cee9c9  ✅ 已在 gitea/main   (merge #88,本票的修法)
3eb8b31  ✅ 已在 gitea/main   (merge #85)
8e10f1d  ✅ 已在 gitea/main   (重編 .worker-builds 官方成品)

當時卡住的權限問題已解,leo21c 那條路拿得到這張票的修法了。

🔴 這張票暴露的流程錯(leo 2026-08-13 點破,比技術內容重要)

「你應該是測試它 OK 就叫我推你也沒把票標示成 Stage
那表示你還沒進 Stage 還在測試,請問我可以做什麼?

當時的狀況是:測試過了、審過了、只差推——而推被那個 session 的權限設定擋住。
那正是「叫 leo 做一個動作」的時機。但總管做的是:

  1. 把它寫在票的留言裡(他不會逐則去讀)
  2. 票的標籤沒改成 s/stage ⇒ 他的看板上「等我」那欄是空的
  3. 在對話裡口頭說「等你」⇒ 對話會消失,而且他不一定在讀

三個地方,沒有一個是他看得到的。 那件事就在票上躺了一天。

📌 判準(2026-08-13 立)
凡是真的要 leo 做事,當下就把標籤改成 s/stage,而且寫清楚「他要做的那一個動作」。
「測試過了、只差推」=該叫他,不是等下一個 session 自己發現。

(署名:總管)

## ✅ 更正:上一則「還沒推上 Gitea」已經過時——**leo 不用做任何事**(2026-08-13 複驗) 那則(08-12 01:53)同時貼在本票與 `Leo/Arcrun#85`,內容一樣。總管今天逐筆驗過: ``` 8cee9c9 ✅ 已在 gitea/main (merge #88,本票的修法) 3eb8b31 ✅ 已在 gitea/main (merge #85) 8e10f1d ✅ 已在 gitea/main (重編 .worker-builds 官方成品) ``` ⇒ **當時卡住的權限問題已解,`leo21c` 那條路拿得到這張票的修法了。** ## 🔴 這張票暴露的流程錯(leo 2026-08-13 點破,比技術內容重要) > 「你應該是**測試它 OK 就叫我推**,**你也沒把票標示成 Stage**, > 那表示你還沒進 Stage 還在測試,**請問我可以做什麼?**」 當時的狀況是:**測試過了、審過了、只差推**——而推被那個 session 的權限設定擋住。 那正是「叫 leo 做一個動作」的時機。但總管做的是: 1. **把它寫在票的留言裡**(他不會逐則去讀) 2. **票的標籤沒改成 `s/stage`** ⇒ 他的看板上「等我」那欄是空的 3. 在對話裡口頭說「等你」⇒ **對話會消失,而且他不一定在讀** ⇒ **三個地方,沒有一個是他看得到的。** 那件事就在票上躺了一天。 📌 **判準(2026-08-13 立)**: **凡是真的要 leo 做事,當下就把標籤改成 `s/stage`,而且寫清楚「他要做的那一個動作」。** 「測試過了、只差推」=**該叫他**,不是等下一個 session 自己發現。 (署名:總管)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Leo/Arcrun#88