存取庫掃描接上 {repo} 代入點 #41

Merged
admin merged 3 commits from feat/scan-repos-for-repo-placeholder into develop 2026-09-07 03:10:23 +00:00
Member

這一批做什麼

把 {repo} 代入點接上真的來源:新增 tools/scan-repos.sh 掃出工作目錄底下的存取庫,run-due.sh 拿它代入點並執行。

這一張疊在 #40 上面,所以差異裡看得到那一支的 commit。#40 合併之後這裡只剩自己的那一個。

掃描起點沒有預設值,這是刻意的

規格寫「掃描根目錄可設定」。給一個預設就等於猜,而猜錯的後果不是掃不到東西——是在猜錯的那些目錄底下跑指令,而那一輪沒有人看得到它跑到哪裡去了。往上猜一層是家目錄,再往上是整台機器。

沒設就回結束碼 3 並說要設哪一個變數。排程那一輪的值由 schedule.sh install 從殼裡快照進條目,跟 wiki 存取庫那幾個變數同一條路。

三種東西一定跳過,但一定印出來

跳過什麼 為什麼
點開頭的目錄 快取、封存、暫存都藏在那裡,掃進去會把封存版當現役版盤點
符號連結 連結會把掃描帶出掃描起點,那條界線一旦被繞過就沒有第二道
路徑帶空白或殼層特殊字元 執行那一支是用 sh -c 送出的,那條路徑會被殼再解一次

被拒的那幾個逐個印成 rejected=,run-due.sh 再原樣轉出成 repo_scan_note=。它們是真的存在卻沒被盤點到的存取庫,只印一個總數會讀成整批都掃過了。

綁了存取庫的那一筆只跑那一個

待辦簿那一筆的 repo 欄有值時只代那一個,值可以是工作目錄路徑,也可以是 {owner}/{repo},兩種都認。對不出掃到的那一份就印 held=,不退回全部存取庫——那一筆指名了一個目標,代成全部就是跑了十九個沒有人要它跑的地方。

順帶補兩個只有真的執行才發現得了的缺陷

一、cron 一行的長度上限。 那個限制是 crontab 在寫入那一刻自己擋的,--dry-run 那一路根本不碰它,所以預演每一次都過。實測踩過一次:整條 PATH 快照進條目那一批預演全綠、安裝回結束碼 4,訊息是一句「command too long」。改成建好條目就量,兩個模式都印 entry_len= 與上限。

二、截錯誤訊息用 cut -c 數的是位元組。 中文字剛好被截在中間就在報告上留下一個替代字元。改成截完再過一次 iconv -c 丟掉那個不完整的序列。這一種不會有人來報:亂碼不影響結束碼。

實測

測什麼 結果
掃這台機器的工作目錄 19 個存取庫,其中一個沒有 origin 而對不出頁名,逐個印出來
頁名與共用 hash-id 比對 plugins/assist 兩邊同值
掃描起點沒設 回 3,帶 {repo} 的那一筆印 held=,執行紀錄與失敗次數一個字都沒動
起點不存在、指到根目錄、深度超範圍 各回 3、2、2
起點指到某個存取庫裡面 回 4:掃過了,一個都沒有
路徑帶空白的存取庫 印 rejected=,不交出去
符號連結指到別處的存取庫 印 skipped_link=,不跟著走
排除清單 assist meta code-* 排掉三個,code 沒被誤排
綁 plugins/pkg 一個目標
綁 /root/plugins/gitea 一個目標
綁一個沒掃到的 印 held=
條目長度 847 個位元組,上限壓到 300 時當場拒絕
四支檢核 lint-scripts、check-behaviors、check-skill-paths、ste100-lint 全 0

邊界

run-due.sh 這一輪真的會對十九個存取庫各跑一次唯讀盤點。實測 list-packages.sh 一次 2 毫秒、這幾個存取庫都沒有套件檔所以輸出零行,週期是七天一次。

JSC_ASSIST_SCAN_ROOT 還沒寫進這台機器的 ~/.bashrc,所以合併部署之後那一輪仍會印 held=——而它會說出要設哪一個變數。那一步等人決定掃描起點指哪裡。

提交之前撞到的第三個缺陷

判定是不是存取庫本來看「.git 在不在」。這台機器的工作目錄底下剛好有一個:.git 只剩一個空的 info/,git 一句「not a git repository」。

掃描把它算成一個存取庫,還印成「沒有 origin」——那個說法讀起來像「這個存取庫還沒接遠端」,不像「這裡根本不是存取庫」。

改成由 git 自己回答,並核對它認定的頂層就是那個目錄:只問「是不是在工作樹裡」不夠,git 會從那裡往上找,.git 壞掉時它會找到上一層的存取庫然後答「是」。存取庫數從 19 個變 18 個。

這一個是要提交之前跑 git status 才撞到的,不是任何一道檢核抓到的。 新寫的那一支自己犯了「拿標記檔頂替真正的判定」這一種。

版本因此再升一次,0.3.2 → 0.3.3。

## 這一批做什麼 把 `{repo}` 代入點接上真的來源:新增 `tools/scan-repos.sh` 掃出工作目錄底下的存取庫,`run-due.sh` 拿它代入點並執行。 **這一張疊在 #40 上面**,所以差異裡看得到那一支的 commit。#40 合併之後這裡只剩自己的那一個。 ## 掃描起點沒有預設值,這是刻意的 規格寫「掃描根目錄可設定」。給一個預設就等於猜,而猜錯的後果不是掃不到東西——是**在猜錯的那些目錄底下跑指令**,而那一輪沒有人看得到它跑到哪裡去了。往上猜一層是家目錄,再往上是整台機器。 沒設就回結束碼 3 並說要設哪一個變數。排程那一輪的值由 `schedule.sh install` 從殼裡快照進條目,跟 wiki 存取庫那幾個變數同一條路。 ## 三種東西一定跳過,但一定印出來 | 跳過什麼 | 為什麼 | | --- | --- | | 點開頭的目錄 | 快取、封存、暫存都藏在那裡,掃進去會把封存版當現役版盤點 | | 符號連結 | 連結會把掃描帶出掃描起點,那條界線一旦被繞過就沒有第二道 | | 路徑帶空白或殼層特殊字元 | 執行那一支是用 `sh -c` 送出的,那條路徑會被殼再解一次 | 被拒的那幾個逐個印成 `rejected=`,`run-due.sh` 再原樣轉出成 `repo_scan_note=`。**它們是真的存在卻沒被盤點到的存取庫**,只印一個總數會讀成整批都掃過了。 ## 綁了存取庫的那一筆只跑那一個 待辦簿那一筆的 `repo` 欄有值時只代那一個,值可以是工作目錄路徑,也可以是 `{owner}/{repo}`,兩種都認。對不出掃到的那一份就印 `held=`,**不退回全部存取庫**——那一筆指名了一個目標,代成全部就是跑了十九個沒有人要它跑的地方。 ## 順帶補兩個只有真的執行才發現得了的缺陷 **一、cron 一行的長度上限。** 那個限制是 `crontab` 在寫入那一刻自己擋的,`--dry-run` 那一路根本不碰它,所以預演每一次都過。實測踩過一次:整條 `PATH` 快照進條目那一批預演全綠、安裝回結束碼 4,訊息是一句「command too long」。改成建好條目就量,兩個模式都印 `entry_len=` 與上限。 **二、截錯誤訊息用 `cut -c` 數的是位元組。** 中文字剛好被截在中間就在報告上留下一個替代字元。改成截完再過一次 `iconv -c` 丟掉那個不完整的序列。這一種不會有人來報:亂碼不影響結束碼。 ## 實測 | 測什麼 | 結果 | | --- | --- | | 掃這台機器的工作目錄 | 19 個存取庫,其中一個沒有 `origin` 而對不出頁名,逐個印出來 | | 頁名與共用 `hash-id` 比對 | `plugins/assist` 兩邊同值 | | 掃描起點沒設 | 回 3,帶 `{repo}` 的那一筆印 `held=`,執行紀錄與失敗次數一個字都沒動 | | 起點不存在、指到根目錄、深度超範圍 | 各回 3、2、2 | | 起點指到某個存取庫裡面 | 回 4:掃過了,一個都沒有 | | 路徑帶空白的存取庫 | 印 `rejected=`,不交出去 | | 符號連結指到別處的存取庫 | 印 `skipped_link=`,不跟著走 | | 排除清單 `assist meta code-*` | 排掉三個,`code` 沒被誤排 | | 綁 `plugins/pkg` | 一個目標 | | 綁 `/root/plugins/gitea` | 一個目標 | | 綁一個沒掃到的 | 印 `held=` | | 條目長度 | 847 個位元組,上限壓到 300 時當場拒絕 | | 四支檢核 | `lint-scripts`、`check-behaviors`、`check-skill-paths`、`ste100-lint` 全 0 | ## 邊界 `run-due.sh` 這一輪真的會對十九個存取庫各跑一次唯讀盤點。實測 `list-packages.sh` 一次 2 毫秒、這幾個存取庫都沒有套件檔所以輸出零行,週期是七天一次。 `JSC_ASSIST_SCAN_ROOT` 還沒寫進這台機器的 `~/.bashrc`,所以合併部署之後那一輪仍會印 `held=`——**而它會說出要設哪一個變數**。那一步等人決定掃描起點指哪裡。 ## 提交之前撞到的第三個缺陷 判定是不是存取庫本來看「`.git` 在不在」。這台機器的工作目錄底下剛好有一個:`.git` 只剩一個空的 `info/`,git 一句「not a git repository」。 掃描把它算成一個存取庫,還印成「沒有 origin」——**那個說法讀起來像「這個存取庫還沒接遠端」,不像「這裡根本不是存取庫」**。 改成由 git 自己回答,並核對它認定的頂層就是那個目錄:只問「是不是在工作樹裡」不夠,git 會從那裡往上找,`.git` 壞掉時它會找到上一層的存取庫然後答「是」。存取庫數從 19 個變 18 個。 **這一個是要提交之前跑 `git status` 才撞到的,不是任何一道檢核抓到的。** 新寫的那一支自己犯了「拿標記檔頂替真正的判定」這一種。 版本因此再升一次,0.3.2 → 0.3.3。
jiantw83 added 2 commits 2026-09-07 02:37:18 +00:00
實測踩到一輪:它報「寫入監控頁失敗——系統的核准機制擋下這個寫入指令,重試
一次仍被擋下,不是 Gitea 回傳的錯誤碼」,然後照規則中止、釋放鎖、不寫心跳。
中止的行為完全正確,寫不成頁就不該假裝跑完。

但那一輪沒說是哪一支工具、哪一條指令。事後把明顯的嫌疑一個一個排除——那一支
腳本實測在無人值守下放行、暫存檔路徑落在檔案規則的範圍內、條目也帶著寫入
確認旗標——真正被擋的那一條始終沒找到。那一輪到現在還是原因不明。

問題在於「擋下」不是工具回的錯誤:沒有結束碼、沒有 stderr、工具自己的日誌上
也沒有痕跡。指令字面是唯一的證據,也是唯一能拿去對允許清單的東西,而清單
比對的是還沒展開的指令字面。所以少了那一行,事後就只能猜。

兩處都加:寫監控頁那一步的失敗分流加一條,界線那一段再加一條通則,涵蓋整輪
任何一次被擋。要求含環境變數前綴——那算指令字面的一部分,今天量過。

三份 manifest 版號從 0.2.9 升到 0.3.1。原本寫 0.2.10,同步 manifest 那一支
把它正規化掉了——那一支不收兩位數的修訂號。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
新增 tools/scan-repos.sh:掃出工作目錄底下的存取庫,交出 {repo} 要代的
那份清單,順便對出每一個存取庫的 REPO_{HASH} 盤點頁頁名(雜湊規則與
盤點頁那一支相同,實測值一致)。

掃描起點刻意沒有預設值。給一個預設就等於猜,而猜錯的後果不是掃不到,
是在猜錯的那些目錄底下跑指令——往上一層是家目錄、再往上是整台機器,
而那一輪沒有人看得到它跑到哪裡去了。沒設就回 3 並說要設哪一個變數。
深度預設一層、上限三層;點開頭的目錄、符號連結、路徑帶空白或殼層特殊
字元的三種一律不交出去,但逐個印出來——那是真的存在卻沒被盤點到的
存取庫,只印一個總數會讀成整批都掃過了。

run-due.sh 改成兩個代入點都代:{cli} 取偵測到的 CLI 代號、{repo} 取
掃到的存取庫,兩個都帶的那一筆目標數是乘積。待辦簿那一筆的 repo 欄
有值時只代那一個,值可以是路徑也可以是 {owner}/{repo};對不出來就
印 held=,不退回全部存取庫——那一筆指名了一個目標。代入之後再驗一次
禁止字元,因為代進去的值是這一輪現場算出來的。

schedule.sh 把 JSC_ASSIST_SCAN_ROOT 與 JSC_ASSIST_SCAN_EXCLUDE 快照進
排程條目。少了掃描起點,帶 {repo} 的內建項每一輪都代不出目標,而那一輪
只印一行 held=,看起來像這一批還沒接上、不像一個變數沒進條目。

同時補兩個只有真的執行才發現得了的缺陷:

一、cron 一行的長度上限只在寫入那一刻由 crontab 自己擋,--dry-run 那一路
根本不碰它,所以預演每一次都過。實測踩過一次:整條 PATH 快照進條目那一批
預演全綠、安裝回結束碼 4。改成建好條目就量,兩個模式都印 entry_len= 與
上限,達到上限當場拒絕並指出長度是從哪幾個快照變數來的。

二、run-due.sh 截錯誤訊息用的 cut -c 數的是位元組不是字元,中文字剛好被
截在中間就在報告上留下一個替代字元。改成截完再過一次 iconv -c 丟掉那個
不完整的序列。這一種不會有人來報:亂碼不影響結束碼。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
jiantw83 added 1 commit 2026-09-07 02:40:00 +00:00
原本看 .git 在不在。這台機器的工作目錄底下剛好有一個目錄的 .git 只剩
一個空的 info/,git 一句「not a git repository」——而掃描把它算成一個
存取庫,還印成「沒有 origin」。那個說法讀起來像「這個存取庫還沒接遠端」,
不像「這裡根本不是存取庫」,兩件事的處置完全不同。

改成由 git 回答,並核對它認定的頂層就是那個目錄:只問「是不是在工作樹裡」
不夠,git 會從那裡往上找,.git 壞掉時它會找到上一層的存取庫然後答「是」。
兩邊都解成實體路徑再比,掃描起點帶符號連結那一段時字串才對得上。

多一個 not_a_repo= 判定行與收尾計數,執行那一支照樣原樣轉出。
存取庫數從 19 個變 18 個。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
admin merged commit 6a2cf045ee into develop 2026-09-07 03:10:23 +00:00
admin deleted branch feat/scan-repos-for-repo-placeholder 2026-09-07 03:10:23 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: plugins/assist#41