FR-174 · 設計文件 · 2026-11-01 定稿
外部連結型 Profile 解析成功當下存成檔案,從此與上傳檔案同一條路同步給 Agent;拆卡表由 handoff/cards.py 產,9 張 6 批
🔴 這份是設計決策,不是現況。 前提:Agent 不連外網(FR-172 已裁),所以「主系統把網址丟給 Agent 自己抓」這條路要整條拔掉;出貨前無客戶,不做舊版相容、不寫回填,既有兩筆按一次「重新解析」就轉型。本案推翻 jedi-detection 一條明文不變式(網址型下載內容不落儲存),理由見 D1。
📑 本頁是 v1.0(定稿)。 實作中有設計異動,見 設計 v1.1(補開 E-1、A-2,H-1 挪批 5、Z-1 挪批 6,工具代號更正)。本頁內容保留定稿原樣,不回頭改。
整案一句話:主系統登記「外部連結」型的檢測 Profile 時,背景下載解析完順手把那份壓縮檔存起來,這一版從此是檔案型;既有的「只同步檔案型給 Agent」機制不用改,Agent 主控台下拉自然就有東西;網址留著當「來源網址」做新鮮度檢查。
| 階段 | 做什麼 | 卡 | 完成怎麼判定(決策者檢查法) |
|---|---|---|---|
| E 環境 | 主系統開發期改裝本機 jedi-detection | E-0 | 小弟回寫貼出 import 路徑在工作區底下 |
| P 套件 | 解析成功就存檔轉型、約束放寬、派工只認檔案型、刪網址分支;公版兩支範例改成隨套件帶檔 | P-1、P-2 | Nexus 上有 jedi-detection 1.8.0b1/b2;P-1 回寫貼出新測試清單與約束驗證結果 |
| H 主系統 | DEV 套 014、兩支 dev-sec 按「重新解析」轉型、本機 Agent 下拉看到兩支 | H-1 | 你親眼看:本機 Agent 主控台 CINC 掃描表單的 Profile 下拉出現「dev-sec Linux 基準」「dev-sec Windows 基準」,名稱與主系統 Profile 頁相同 |
| F 前端 | 版本明細多「來源網址」列、提示文案改 | F-1 | 主系統 Profile 頁 dev-sec 那版同時看到檔名與網址 |
| A Agent | 拔掉「網址原樣交給引擎」分支 | A-1 | 小弟回寫貼出 grep SOURCE_TYPE_URL 為 0 |
| Z 結案 | 發正式版、改回釘版、收口、回報基線重產 | Z-1 | git status 乾淨;回寫列出基線要補的兩列 |
依賴一句:E-0 → P-1 → (P-2、F-1、A-1)→ (E-1 環境對齊 FR-171、A-2 Agent 快取路徑)→ H-1 → Z-1。你第一個看得到畫面的是批 5 的 H-1。
| # | 題目 | 定案 | 被排除的 | 理由 |
|---|---|---|---|---|
| D1 | 網址型 Profile 怎麼同步給 Agent | A 案:解析成功當下把下載到的壓縮檔存進 upload_files,該版 source_type 改 file、file_id 有值;掃描、同步、對帳全走檔案型既有路徑 |
B 案:保留 url 型、放寬約束讓它同時帶 file_id,同步條件也放寬 |
A 讓「平台解析的」與「Agent 掃的」是同一份檔,正好解掉套件不變式擔心的「兩邊對不上」;B 是同一版兩個來源,Agent 該用哪個要另訂規則,日後兩個真相。且 FR-172 已裁 Agent 不連外網,「Agent 自己拉網址」本來就走不通,不變式的前提已不存在 |
| D2 | 來源網址存哪 | 沿用既有 url 欄;約束 chk_dpv_source_exclusive 改成「file 型 file_id 必填、url 可有可無;url 型 url 必填、file_id 必空」 |
另加 source_url 欄 |
兩欄存同一串網址只差生命週期階段,是多餘複製;沿用一欄少一次搬移、少一組讀寫。這不是 B 案:B 案的問題是「網址型同時帶檔案」會有兩個掃描來源,這裡是「檔案型附帶出處」,掃描來源永遠只有檔案一個 |
| D3 | 轉型時機 | 解析成功落庫那一刻(_persist 同一個 transaction):寫控制項、寫 file_id、改 source_type、寫 sha256 與 ETag 一起 commit |
下載完就先存檔再解析 | 下載成功但解析失敗(不是合法 inspec 包)時不該留一個檔案型的壞版本;同一 transaction 保證「有檔必有控制項、有控制項必有檔」 |
| D4 | 下載或解析失敗的版本 | 維持 url 型、extraction_status=failed、file_id 空;既有派工守門(failed 拒派)與「修正來源」流程照舊 |
半成品也轉型 | 失敗版本沒有檔可同步,轉型只會讓 Agent 拉到空 |
| D5 | 來源更新偵測與重抽 | 保留:file 型且 url 非空的版本開控制項頁時照舊 HEAD 比 ETag,變了就重抽;重抽成功同一版換檔(新 upload_files 列、file_id 指過去、sha256 更新;舊檔由 delete_file 清掉)。Agent 下次同步比 sha256 不同就重拉 |
偵測到變更就長新版 | 套件文件已排除「自動長 v2」(任務綁的版本 uid 會指不到實際掃的內容);同版換檔讓「版本」仍是使用者的語意、「檔」是內容的語意 |
| D6 | 「Agent 自己拉網址」掃描路徑 | 整條拔掉:套件 build_payload 只回 file 形狀、派工對 url 型版本 raise;Agent resolve_profile_source 刪 url 分支;相關 docstring 與不變式註解改寫 |
留著當備援 | 出貨前無客戶不做相容;留著是死碼,且與「Agent 不連外網」矛盾,六個月後沒人知道哪條是主路徑 |
| D7 | 安裝包的 dev-sec 兩支公版範例 | 改成檔案型隨套件帶:兩支 tar.gz 進 jedi-detection assets/+storage-seed.map,seed 004 兩列改 file 型反查 upload_files uid、url 留著;主專案基線 upload_files 補兩列(基線重產屬決策者裁示,卡只回報) |
從種子拿掉由客戶自己匯入 | 新裝客戶內網到不了 GitHub,網址型種子裝完下拉一樣空;TWGCB 八支已走這條路,不新開機制 |
| D8 | 既有資料(DEV、189 各兩筆) | 不寫回填 migration;升級後到控制項頁按一次「重新解析」即轉型 | 回填腳本 | 出貨前無客戶;189 兩筆是 Demo 資料,按一下就好 |
| D9 | 套件版本基底 | 從 FR-171 CM-3382 發的 1.7.3b1 往上長 1.8.0b1(P-1)、1.8.0b2(P-2)、正式 1.8.0(Z-1);套件分支基底是 jedi-python-package 的 ws-CM-3379(FR-171 批 3 合回後以 feature/FR-172 為準) |
從 Nexus 1.7.2 長 | 主系統在 FR-171 分支已釘 1.7.3b1,從 1.7.2 長會把 FR-171 的改動蓋掉 |
| D10 | 與 FR-171 B 主題(設定通道)的接點 | 不碰。本案主系統端不改 _agent_profile_sync.py、不改心跳回應;Profile 清單的查法 list_current_files_visible_to 不變,轉型後的版本自然納入。FR-171 B-1 之後把清單搬去 GET /agents/config 時查法照用 |
等 B-1 合回再做 | 主系統端零程式改動,與 FR-171 批 4 不撞檔;不必等 |
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
sequenceDiagram
autonumber
participant U as 管理者(主系統 Profile 頁)
participant S as 主系統(jedi-detection)
participant F as upload_files/儲存
participant A as Agent
U->>S: 新增 Profile,來源=外部連結 https://…
S->>S: 建版 v1:source_type=url、file_id=NULL、status=pending
S->>S: 背景 worker:下載(60 秒內、50 MB 內、SSRF 五道防護)
S->>S: cinc-auditor 解析(28~117 秒)
rect rgb(226,240,241)
Note over S,F: 本案新增:解析成功 → 存檔 → 轉型(同一 transaction)
S->>F: 壓縮檔 bytes 存成 upload_files(save_dir=detection-profiles,sha256 回填)
S->>S: 寫控制項;source_type=file、file_id=新列、url 保留、sha256=bytes 雜湊、ETag
end
A->>S: 心跳(FR-171 B 之後改 GET /agents/config)
S-->>A: 現行 file 型清單(含這一版:uid、version、sha256、file_uid、tool、name)
A->>S: GET /agents/files/<file_uid>
S-->>A: 壓縮檔
A->>A: 對帳 sha256 → 解壓進 cache → 主控台下拉出現
U->>S: 開控制項頁
S->>S: HEAD 來源網址比 ETag;變了 → 同版重抽、換檔(D5)
被拔掉的舊路:派工 _profile payload 帶 {source_type:url, url} → Agent 把網址原樣丟給 cinc-auditor exec。本案後派工只會有 file 形狀;Agent 收到 url 形狀一律報「派工資料錯誤」。
jedi_detection/common/profile_snapshot.py:store_snapshot(file_upload_service, upload_file_domain_service, raw: bytes, file_name: str, scope: str, login_name: str) -> UploadFileEntity。內部把 bytes 包成 werkzeug FileStorage,走 與 DetectionProfileService._store_file 完全相同的分流(SYSTEM 走 upload_system_file、TENANT 走 upload_files,save_dir="detection-profiles"),再 _backfill_sha256。_store_file 本身改成呼叫這支(1,146 行的檔只准一行呼叫,不複製)。DetectionProfileExtractionService._extract_in_thread:下載成功、解析成功後,在 _persist 的 session 內呼叫 store_snapshot,把回來的 file_id 交給 _persist。順序:先 store_snapshot(檔進儲存)→ replace_for_version(控制項)→ 改版本列。存檔在 session 內是可以的:它是本機/物件儲存寫入,不是外部網站。_persist(…, file_id=None):file_id 有值時 version.source_type = "file"、version.file_id = file_id;url、source_etag、source_last_modified、sha256 照舊寫。_persist 發現版本已有 file_id 且本次又存了新檔 → 舊 file_id 收進一個清單,commit 後 file_upload_service.delete_file(old_uid)(失敗只 log,不回滾——孤兒檔比壞版本便宜)。_download() 從網址推得的 name;推不出時用 <profile uid>-v<version>.tar.gz。common/detection_profile_ref.build_payload:刪 url 分支;source_type != "file" 直接 raise ValueError(派工層包成 DETECTION_PROFILE_NOT_DISPATCHABLE)。detection_orchestration_service._load_profile 之後一律 _load_profile_file,不再依 source_type 分流。url 型且 failed 的版本本來就被 assert_profile_dispatchable 擋;url 型且 pending/running 的版本(還在抽)由 build_payload 擋,錯誤訊息「此版本尚未解析完成,無法派工」。_check_source_freshness:條件從「source_type == url」改成「url 非空 且 status == succeeded 且有驗證器」。_read_controls 已把 _source_url 帶出來,不用改。list_current_files_visible_to、current_profiles_for_heartbeat、record_agent_states:不動。-- jedi-detection 014:外部連結型 Profile 解析成功後存成檔案(FR-174 D1/D2)
-- Date: 2026-11-0X
-- 🔴 套件只提供、不執行;冪等。
ALTER TABLE config.detection_profile_versions DROP CONSTRAINT IF EXISTS chk_dpv_source_exclusive;
ALTER TABLE config.detection_profile_versions ADD CONSTRAINT chk_dpv_source_exclusive CHECK (
(source_type = 'file' AND file_id IS NOT NULL)
OR (source_type = 'url' AND url IS NOT NULL AND file_id IS NULL)
);
COMMENT ON COLUMN config.detection_profile_versions.source_type IS 'file=有檔(上傳或由來源網址解析後存下)/url=只登記網址、尚未解析成功';
COMMENT ON COLUMN config.detection_profile_versions.url IS '來源網址;file 型有值代表這份檔是從該網址解析存下的,開頁時拿它比 ETag';主專案側由 flatten_pkg_migrations.sh 攤平到 scripts/sql/packages/jedi_detection/014-…,DEV 手套並登記 schema_migrations(登記名 packages/jedi_detection/014-fr174-url-profile-snapshot.sql)。
detection_profile_extraction_service.py 檔頭「url 型:平台代為下載,但只在記憶體」整段、_download() docstring 紅字、detection_profile_version.py 兩個欄位 comment=、detection_profile_ref.build_payload docstring 的兩形狀表。改成描述新規則與陷阱(「解析失敗不轉型,否則 Agent 會拉到空」「重抽換檔要清舊檔」),不留「原本/改判」字樣。
| 端 | 改什麼 | 不改什麼 |
|---|---|---|
| 主系統(H-1) | DEV 套 014;兩支 dev-sec 按「重新解析」;一支守衛測試(core/plugins/、app/ 下不得出現 source_type == "url" 分支) |
_agent_profile_sync.py、心跳回應、retry 端點、agents/files 端點 |
| 前端(F-1) | 版本列與明細:有 url 就多顯示「來源網址」,圖示改依「有無網址」;快照提示改「內容取自來源網址的當下快照,Agent 掃描用的是同一份檔案」;過期提示刪「與實際掃描的內容不一致」 |
新增 Profile 表單(仍選上傳或外部連結)、修正來源對話框 |
| Agent(A-1) | profile_cache.resolve_profile_source 刪 url 分支與 SOURCE_TYPE_URL;inspec.py docstring 三路改兩路;兩支測試改預期 raise |
心跳、同步、cache、主控台下拉(都已是 file 型路徑) |
底表 handoff/cards.py(兩個斷言已過:依賴都在更早的批、同批同 repo 不改同一既有檔)。
| 批 | 卡 | 階段 | repo | 做什麼 | reuse/extend/new | 改既有檔 | 新開檔 | 依賴 | 驗收(小弟本機) | model/effort |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | E-0 | 環境 | BE | 環境卡:主系統開發期改裝 jedi-detection 本機路徑(工作坊工作區 develop 模式),驗 import 路徑在工作區底下;改動不 commit | reuse:FR-171 E-0(CM-3385)的做法原封照抄,只是套件換 jedi-detection | pyproject.toml(path dependency,assume-unchanged 不 commit) |
docs/features/FR-174-2611-url-profile-snapshot-sync/handoff/dev-env.md |
— | python -c "import jedi_detection,inspect;print(inspect.getfile(jedi_detection))" 印出 jedi-python-package/.worktrees/<母卡號>/jedi-detection/ 底下;PORT=8003 python main.py 起得來、GET /api/1.0/detection-profiles 200;git status 看不到 pyproject.toml(assume-unchanged);dev-env.md 寫清楚怎麼還原 |
sonnet/low |
| 2 | P-1 | 套件 | jedi 套件 | jedi-detection 1.8.0b1:網址型解析成功就存檔轉 file 型(url 留作來源網址)、約束放寬 file 可帶 url、新鮮度檢查改看 file 型的 url、派工只認 file 型、刪「網址丟給 Agent」分支與不變式註解 | extend:_extract_in_thread 下載成功後多一步 _store_snapshot()(組 FileStorage 走既有 DetectionProfileService._store_file 同一條,抽成兩支共用的 module 函式);_persist 多收 file_id 並把 source_type 寫成 file;_check_source_freshness 條件改「有 url 且 succeeded」不看 source_type;build_payload 刪 url 分支;list_current_files_visible_to 不動(轉型後自然撈到);migrations/014 改約束。new:common/profile_snapshot.py(bytes→upload_files 的共用小函式,因為 detection_profile_service.py 1,146 行已超標只准一行呼叫) |
jedi_detection/app/service/detection_profile_extraction_service.pyjedi_detection/app/service/detection_profile_service.py(一行呼叫)jedi_detection/common/detection_profile_ref.pyjedi_detection/app/service/detection_orchestration_service.py(_load_profile 之後一律走 _load_profile_file)jedi_detection/infra/detection_tools/model/detection_profile_version.py(欄位註解)jedi_detection/api/serializers/detection_profile.py(controls 回 source_url)jedi_detection/app/dto/detection_profile_dto.pytests/test_detection_source_upload.pytests/test_agent_profile_sync_service.pypyproject.toml(版號 1.8.0b1) |
jedi_detection/migrations/014-fr174-url-profile-snapshot.sqljedi_detection/common/profile_snapshot.pytests/test_profile_snapshot.py |
E-0 | pytest 全綠含新測:①網址型抽取成功後該版 source_type=file、file_id 有值、url 仍是原網址、sha256=下載 bytes 雜湊、upload_files.sha256 同值(突變:不存檔→紅);②下載失敗仍是 url 型 failed、file_id NULL;③build_payload 對任何版本只回 file 形狀,餵一個 source_type=url 的版本會 raise;④_check_source_freshness 對 file 型且有 url 的版本會探測、對沒 url 的不探測;⑤約束:INSERT source_type='file', file_id=1, url='https://x' 過、source_type='url', file_id=1 被擋(對本機 DEV 套 014 後 psql 驗)。poetry publish -r nexus 1.8.0b1,回寫版號 |
opus/high |
| 3 | P-2 | 套件 | jedi 套件 | jedi-detection 公版範例改檔案型:dev-sec linux/windows 兩支 tar.gz 進 assets/+storage-seed.map 兩列、seed 004 兩列 versions 改 file 型(file_id 反查 upload_files uid、url 留著)、回報主專案基線 upload_files 要補兩列 |
extend:照 TWGCB 八支同一條路(assets+storage-seed.map+004 反查 uid);不新開機制 | jedi_detection/migrations/004-detection-profiles-seed.sqljedi_detection/assets/storage-seed.mappyproject.toml(版號 1.8.0b2;include 已含 assets) |
jedi_detection/assets/dev-sec-linux-baseline.tar.gzjedi_detection/assets/dev-sec-windows-baseline.tar.gz |
P-1 | 兩支 tar.gz 的 sha256 與 004 寫的 sha256 一致、檔名在 map 內;本機乾淨庫跑 001~014 後 select source_type,file_id is not null,url from config.detection_profile_versions where uid in (dev-sec 兩個 uid) 回 `file |
t |
| 3 | F-1 | 前端 | FE | FE 版本明細與控制項頁:file 型帶 url 時多一列「來源網址」;清單圖示依「有無來源網址」而非 source_type;快照提示文案改成「內容取自來源網址的當下快照,Agent 掃描用的是同一份檔案」;過期提示拿掉「與實際掃描的內容不一致」 | extend:ProfileVersionTable.vue/ProfileDetailDialog.vue/DetectionProfileControlsView.vue 既有條件改判 url 有無;i18n 兩個 key 改文案、加一個 field_source_url |
src/views/detection-profile/components/ProfileVersionTable.vuesrc/views/detection-profile/components/ProfileDetailDialog.vuesrc/views/detection-profile/DetectionProfileControlsView.vuesrc/config/locales/i18n/zh-tw/detection-profile-manage.jsonsrc/config/locales/i18n/en/detection-profile-manage.json |
— | P-1 | vitest 既有綠;本機對 8003 開 Profile 頁:dev-sec 版本列顯示檔名與來源網址兩者、明細有「來源網址」列、控制項頁提示新文案;grep -rn border-left src/views/detection-profile 為 0 |
sonnet/low |
| 3 | A-1 | Agent | evidence-agent | Agent 拔掉「url 型原樣交給引擎」分支:resolve_profile_source 只認 file 型,收到 url 型明確報派工資料錯誤;模組與 connector docstring 三路改兩路;對應測試改成預期 raise |
extend:刪分支與常數 SOURCE_TYPE_URL,錯誤走既有 ProfilePayloadError |
guidant_agent/sync/app/profile_cache.pyguidant_agent/scan/adapters/connectors/inspec.py(docstring)test/test_profile_cache.pytest/test_inspec_connector.py |
— | P-1 | poetry run pytest test/test_profile_cache.py test/test_inspec_connector.py 綠;突變:把 raise 改回 return url 對應測試要紅;grep -rn SOURCE_TYPE_URL guidant_agent 為 0 |
sonnet/low |
| 4 | E-1 | 環境 | jedi 套件 | 套件環境對齊 FR-171:把 feature/FR-172(已含 171 正式版)合進 174 工作坊分支,解 jedi-detection/pyproject.toml 版號衝突(版號取 174 的 1.8.0b2、相依下限取 171 的 remote-agent>=1.12.0);主系統 .venv-fr174 的 jedi-remote-agent/jedi-agent-protocol 換成正式版 |
reuse:純合併與環境對齊,不改套件程式碼 | jedi-detection/pyproject.toml |
— | P-2 | git merge-tree 確認只有 jedi-detection/pyproject.toml 一處衝突並解掉;174 工作坊分支 jedi-detection 版號 1.8.0b2、相依 jedi-remote-agent>=1.12.0;.venv-fr174/bin/python -c 印三支版本:protocol 0.2.0、remote-agent 1.12.0、detection 1.8.0b2(工作區原始碼);jedi-detection 全部 pytest 綠 |
sonnet/low |
| 4 | A-2 | Agent | evidence-agent | Agent Profile 快取路徑改可設定:profile_cache.CACHE_ROOT 寫死 /data/content/cache,Mac 本機跑會 Read-only file system;改讀環境變數 AGENT_CONTENT_CACHE_DIR(預設不變),本機 start-agent.sh 補一行指到 $DATA/content-cache |
extend:profile_cache.CACHE_ROOT 改成函式讀 env、預設值不變;不新增模組 |
guidant_agent/sync/app/profile_cache.pytest/test_profile_cache.py |
— | — | poetry run pytest test/test_profile_cache.py 綠,新增一條:設 env 後 build_cache_dir 落在該目錄(突變:拿掉讀 env → 紅);本機 start-agent.sh 補 export AGENT_CONTENT_CACHE_DIR="$DATA/content-cache" 後起 Agent,log 不再出現 Read-only file system: '/data'、ls ~/guidant-agent-local/data/content-cache 看得到已同步的 Profile 目錄 |
sonnet/low |
| 5 | H-1 | 主系統 | BE | 主系統接線:釘 jedi-detection 1.8.0b1(path 模式下先不改 pin)、scripts/sql/packages/ 攤平 014、DEV 套 014、DEV 兩支 dev-sec 按「重新解析」轉成 file 型、本機 Agent 下拉出現兩支 CINC Profile;守衛測試 |
reuse:全部走既有機制(flatten_pkg_migrations、_agent_profile_sync 不動、retry 端點不動);只加一支守衛測試 |
docs/features/FR-174-2611-url-profile-snapshot-sync/handoff/dev-env.md(補 DEV 已套 014) |
test/test_fr174_profile_snapshot_guard.py |
P-1, E-1, A-2 | DEV(localhost:5432)psql 套 packages/jedi_detection/014 並登記 schema_migrations;對 dev-sec 兩版打 POST .../versions/<uid>/extraction/retry,輪詢到 succeeded 後 DB 查到 source_type=file、file_id 有值、url 保留;GET /api/1.0/agents/heartbeat 回應(或 Agent log)清單含這兩支;本機 Agent 主控台 GET /console/scan/profiles?tool=cinc_auditor 回兩筆、label 與主系統名稱相同;守衛測試:主系統 core/plugins/ 與 app/ 下 grep 不到 source_type == "url" 分支(突變:加一行→紅) |
sonnet/medium |
| 6 | Z-1 | 結案 | BE | 結案:jedi-detection 發正式 1.8.0、主系統改回釘版並取消 assume-unchanged、poetry update jedi-detection、守衛全綠、FR-174 STATE/README 收口、CM-3410 卡 append 指向本案完成;回報基線重產清單 |
reuse:FR-171 Z-2 結案卡同形 | pyproject.tomlpoetry.lockdocs/features/FR-174-2611-url-profile-snapshot-sync/README.mddocs/features/FR-174-2611-url-profile-snapshot-sync/handoff/FR-174-STATE.md |
— | P-2, H-1, F-1, A-1, E-1, A-2 | pip show jedi-detection 1.8.0 且路徑在 site-packages;git status 乾淨;pytest test/test_module_boundaries.py test/test_fr174_profile_snapshot_guard.py 綠;README 總進度全 ✅;回寫列「出貨基線待重產:upload_files 兩列+packages manifest 014」 |
sonnet/medium |
共 9 張、6 批;BE 3、jedi 套件 3、evidence-agent 2、FE 1。
linux-baseline-master.tar.gz(或推得的檔名)與來源網址;明細有「來源網址」列。source_etag 成假值再開頁 → 出現「有更新版本,正在重新解析」→ 抽完 file_id 換成新列、舊 upload_files 列消失、Agent 下次同步重拉(sha256 變了)。file_id 空、派工被擋 412。grep -rn "source_type == \"url\"\|SOURCE_TYPE_URL" 在主系統 core//app/ 與 Agent guidant_agent/ 為 0。