skill(notes-vault-curation): 新增 references/migration-pitfalls.md —— 迁移脚本三铁律

2026-09-11 实测事故:P2 迁移脚本丢 90 个文件(465→375),git reset --hard 恢复。
根因①骨架目录名(05-01-定义规范)与映射目标(01-定义规范)不同源
根因②git mv 失败后用 os.replace 兜底=静默毁盘(应 fail-fast)
根因③DRY 模式只验输入不验输出(没查目标目录是否存在)
铁律:命名同源 / fail-fast / 先小样 / 恢复预案先行 / 动手前先 commit
This commit is contained in:
小唯 2026-09-11 02:52:10 +08:00
parent e477643c35
commit 46d0936ca5
36 changed files with 382 additions and 141 deletions

View File

@ -1 +1 @@
{"ts": 1789014710.8236191, "behind": -1, "rev": null, "ver": "0.21.0"}
{"ts": 1789065921.4957573, "behind": -1, "rev": null, "ver": "0.21.0"}

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
x<01><>MJإ0Ew<15> نُ<D986>IDDpق.لثط[غ4%/q<><71>ه<0E>^8<><1C><>,]<5D><>zال<D8A7>:ًl4b2ع+اyت)bت>(V<>ك4ش<>wفع<D981><D8B9><EFBFBD>#vة[`¤ّق،هب<D987>0t<30><74>60تtًsmق­ـ*<2A>gِzشم|x<>ُس<D98F>V<EFBFBD><56>W<EFBFBD>}<7D>j<1C><>قQ<05><06>v<><76>rm']<5D><><EFBFBD>gq<67><71>؛r<><05><>X><3E><>مJ{<7B>]~ط<>^b\e<><65>.EلW<D984>c~<01>ث`A

View File

@ -0,0 +1 @@
xťŽAjÄ0sö+ć´—@$ݬ‘´„Č%żŁń[–‘µ„ü>fó<66>\Ş«¸ä<7¸ýÔŞ$v\ Ä<>sčÜh<C39C>EŃ8ÚűdÄľ"v;UŮŚäňśĽíÄoĽŕ<C4BD>l"´¤)0ÝŰT*|JÍrŔÇ$Ľěe>^§Çôľ¦ő zç<7A>F4ş‡gíµîřQŘä?l%•*pŇyŢh˝Ź ¦Eĺ;«—?µZh´©ďR—c'CµŻ<C2B5>ÄĆĐ{¸\`˙9Ű7ÓýŁľ^˘

View File

@ -0,0 +1,3 @@
x¥UQoÚ0Þs~ÅÍÕD²R(í:MHhZ×Çi{aO¥BNrk‰íÚÎZ„øï;;<3B>Rh¶å!‰ƒï»û¾û|ä•ÎaôéêòÍÉÛaãì0—jˆê7˜•_ju™0Æn «sÃ}Õ—bò—<+˽¶PJçeU¯M%…,¸—ZÁ),,7Kºë¿R"k£­w_I<5F>—}Ю%÷èe<C3A8>À”>In®al¸Ô5ë¦hktÃ6(s´¡ƒZ),|*˜<>Ž×7×ϵ.qb5ëCcådjÌ*•¢Š=<3D>¶i$ÆJåSvvv®XbÍÛr犢ÐgFQºrvkoGw ˆ©©€0øˆEã1eÆòÅzžW8—Jè4ÚÂd,»Û&ª'àeÛG™±\ì2㤎8‡©# ÑöÚÏU<C38F>bŸ„ÊD¤ò’ä}Âêz_ ú‚<1C>iv{~Qð/PbIG(m ©é<C2A9>é—o¥Ÿ¬c‰ˆ
7ÔŒä„\4A7¢eNAqò†ám­º3õ D n[úbëxD*YK,'@WgÐMkŠ…´ÉOOR…ÉÕåœ{R¬É@ÁVX9„ï¤h¢\¶#ÓFí/<2F>ø¢ â T~.Ë6fouÒ•>S¡Ì Ï>°˜?¬ã }ˆØáC|!–Ä!ì}¦@+pÅ<70>‡Ñ:Å+7n{0H£<48>¯ ý9ýšu'*HxO <07>æ®É<C2AE>·é:dØôGýÑye8+<2B>UÔ=†ëКa¼4ò mI)ã+<2B>á¢kÝèc=16Ì*¢yxˆï»Þ†=[O¬Ë ÝT´ ÅyA<79>v^PÒ]» õÚÀèjŸs°<73>¢iw”{g½uL°Ù#þ:ÕÑÕ Ø§zµµéåÞÚñŧ͖ÏÎ
á<EFBFBD>±z"<22>B>ÆyneÞÄ1ÞNÂP?ýú<02>§FÜá®WKT-h%!ôÄl6×j 7´œÍzàÞ˜CÚý<C39A>`™õ^@#ñ؈¬§)‹¥¼ªóoÚÁgg_0²i1¾8ßêùŽQ•

View File

@ -0,0 +1 @@
x+)JMU04²`040031QH/J,بˆ/(تOJص+¨dHشiùQ5‡?ٌّAس âf¼ح:أ¨ٹ©ز¤´ îëصبM3ق= ق¨:ظڑ‹S©1Hé¦ىo³¦ù¬»ج¹¸¶nخ5فيqف¯÷6ژ

View File

@ -0,0 +1 @@
x<01>ÍAjÃ0Fá¬}ŠŸ,º Áò ÙJ‡B7¹Æx2F&R5%Ð÷äÙ>øxSZ*ÈÒªUˆŸü §i¦™¨wd,qgYæÁ9Þ³½mø»†\pÔô†¯ r¾æåR±Ïô³p< üÎô=ÇÆxcy«¾bIç\ÿ:-Žïˆ7l#£½siã2µIS.<2E>å»¶ Ã[‡_å¶d> 2Öã8âú¨¡ù£ŸM÷

View File

@ -1 +1 @@
{"workdir": "/home/muc/.hermes/kanban/workspaces/t_68cbf702", "created_at": 1789062726.1700513, "last_touch": 1789065880.2005036, "workdir_parent_dev": 64512, "workdir_parent_ino": 10487295}
{"workdir": "/home/muc/.hermes/kanban/workspaces/t_68cbf702", "created_at": 1789062726.1700513, "last_touch": 1789066107.280351, "workdir_parent_dev": 64512, "workdir_parent_ino": 10487295}

View File

@ -0,0 +1 @@
{"workdir": "/home/muc/.hermes/kanban/workspaces/t_9fe5b918", "created_at": 1789066163.53903, "last_touch": 1789066315.0608737, "workdir_parent_dev": 64512, "workdir_parent_ino": 10487295}

View File

@ -1 +1 @@
{"workdir": "/home/muc/.hermes", "created_at": 1786156902.830349, "last_touch": 1789065892.0533488, "workdir_parent_dev": 64512, "workdir_parent_ino": 7864322}
{"workdir": "/home/muc/.hermes", "created_at": 1786156902.830349, "last_touch": 1789066330.2326653, "workdir_parent_dev": 64512, "workdir_parent_ino": 7864322}

View File

@ -0,0 +1 @@
57da7b32306f8f3a3372639f424a3d62e0f5d0b6

View File

@ -5,9 +5,9 @@ model:
base_url: https://api.deepseek.com/v1
context_length: 1048576
fallback_providers:
- gmi-cloud
- llama-local
- zhipu
- gmi-cloud
- llama-local
- zhipu
providers:
agnes:
base_url: https://apihub.agnes-ai.com/v1
@ -15,7 +15,7 @@ providers:
default_model: agnes-2.5-flash
key_env: AGNES_API_KEY
models:
- agnes-2.5-flash
- agnes-2.5-flash
rate_limit: 1000
timeout: 60
deepseek:
@ -24,8 +24,8 @@ providers:
default_model: deepseek-v4-flash
key_env: DEEPSEEK_API_KEY
models:
- deepseek-v4-flash
- deepseek-v4-pro
- deepseek-v4-flash
- deepseek-v4-pro
rate_limit: 1000
timeout: 30
mimo:
@ -34,8 +34,8 @@ providers:
default_model: mimo-v2.5-pro
key_env: XIAOMI_API_KEY
models:
- mimo-v2.5-pro
- mimo-v2.5
- mimo-v2.5-pro
- mimo-v2.5
rate_limit: 1000
timeout: 60
newapi-local:
@ -44,10 +44,10 @@ providers:
cost_factor: 0.0
default_model: agnes-2.5-flash
models:
- nvidia/nemotron-mini-4b-instruct
- openai/gpt-oss-120b
- nvidia/nvidia-nemotron-nano-9b-v2
- meta/llama-3.1-8b-instruct
- nvidia/nemotron-mini-4b-instruct
- openai/gpt-oss-120b
- nvidia/nvidia-nemotron-nano-9b-v2
- meta/llama-3.1-8b-instruct
rate_limit: 1000
timeout: 30
omniroute-local:
@ -56,9 +56,9 @@ providers:
cost_factor: 0.0
default_model: auto/chat
models:
- auto/chat
- auto/best-free
- auto/coding
- auto/chat
- auto/best-free
- auto/coding
rate_limit: 1000
timeout: 30
opencode-free:
@ -67,12 +67,12 @@ providers:
cost_factor: 0.0
default_model: x-preview-f-free
models:
- x-preview-f-free
- hy3-free
- laguna-s-2.1-free
- nemotron-3-ultra-free
- nemotron-3.5-lightning-free
- muse-spark-1.2-contributor-free
- x-preview-f-free
- hy3-free
- laguna-s-2.1-free
- nemotron-3-ultra-free
- nemotron-3.5-lightning-free
- muse-spark-1.2-contributor-free
rate_limit: 1000
timeout: 30
sensenova:
@ -81,18 +81,18 @@ providers:
cost_factor: 0.0
default_model: deepseek-v4-flash
models:
- deepseek-v4-flash
- glm-5.2
- sensenova-6.8-flash-lite
- deepseek-v4-flash
- glm-5.2
- sensenova-6.8-flash-lite
rate_limit: 1000
timeout: 30
zhipu:
api_key: ${ZHIPU_API_KEY}
base_url: https://open.bigmodel.cn/api/paas/v4
models:
- glm-4-flash
- glm-4-air
- glm-4-long
- glm-4-flash
- glm-4-air
- glm-4-long
type: openai
llama-local:
api_key: local-key
@ -100,7 +100,7 @@ providers:
cost_factor: 0.0
default_model: minicpm5-2b
models:
- minicpm5-2b
- minicpm5-2b
rate_limit: 100
timeout: 300
context_length: 45056
@ -116,17 +116,17 @@ providers:
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/120.0 Safari/537.36
fallback_providers:
- provider: agnes
model: agnes-2.5-flash
- provider: zhipu
model: glm-4-flash
- provider: sensenova
model: deepseek-v4-flash
- provider: opencode-free
model: x-preview-f-free
- provider: agnes
model: agnes-2.5-flash
- provider: zhipu
model: glm-4-flash
- provider: sensenova
model: deepseek-v4-flash
- provider: opencode-free
model: x-preview-f-free
toolsets:
- hermes-cli
- web
- hermes-cli
- web
agent:
max_turns: 90
gateway_timeout: 1800
@ -251,24 +251,24 @@ auxiliary:
timeout: 120
download_timeout: 30
fallback_chain:
- provider: newapi-local
model: meta/llama-3.2-11b-vision-instruct
base_url: http://127.0.0.1:3000/v1
api_key: 0ExNiLblJvIWBDpkS50fwOBw4MmqLyKdHJK5iQtlw9dOMWBP
timeout: 90
- provider: newapi-local
model: meta/llama-3.2-11b-vision-instruct
base_url: http://127.0.0.1:3000/v1
api_key: 0ExNiLblJvIWBDpkS50fwOBw4MmqLyKdHJK5iQtlw9dOMWBP
timeout: 90
compression:
provider: agnes
model: agnes-2.5-flash
context_length: 512000
fallback_chain:
- provider: zhipu
model: glm-4-flash
base_url: https://open.bigmodel.cn/api/paas/v4
key_env: ZHIPU_API_KEY
timeout: 90
base_url: https://apihub.agnes-ai.com/v1
api_key: sk-7k9e9KGcoZdDuYt2LSA4YXdBTioczleGJm2zzLWCku072ikW
timeout: 120
context_length: 512000
fallback_chain:
- provider: zhipu
model: glm-4-flash
base_url: https://open.bigmodel.cn/api/paas/v4
key_env: ZHIPU_API_KEY
timeout: 90
skills_hub:
provider: zhipu
model: glm-4-flash
@ -364,9 +364,9 @@ display:
ephemeral_system_ttl: 0
runtime_footer:
fields:
- model
- context_pct
- cwd
- model
- context_pct
- cwd
copy_shortcut: auto
tool_progress: all
tool_progress_style: accumulate
@ -470,12 +470,12 @@ moa:
fanout: user_turn
reference_max_tokens: 800
reference_models:
- model: deepseek-v4-flash
provider: deepseek
- model: agnes-2.5-flash
provider: agnes
- model: glm-4-flash
provider: zhipu
- model: deepseek-v4-flash
provider: deepseek
- model: agnes-2.5-flash
provider: agnes
- model: glm-4-flash
provider: zhipu
skills:
external_dirs: []
template_vars: true
@ -527,51 +527,52 @@ approvals:
mcp_reload_confirm: true
destructive_slash_confirm: false
command_allowlist:
- SQL TRUNCATE
- overwrite system file via redirection
- script execution via -e/-c flag
- stop/restart system service
- pipe decoded content to shell (possible command obfuscation)
- copy/move file into sensitive credential/SSH/shell-rc path
- copy/move file into system config path
- recursive delete
- kill hermes/gateway process (self-termination)
- overwrite system file via tee
- pipe remote content to shell
- script execution via heredoc
- shell command via -c/-lc flag
- force kill processes (killall -KILL)
- in-place edit of Hermes config/env
- command parser limit or malformed executable payload
- git force push (rewrites remote history)
- force kill processes
- stop/restart hermes gateway (kills running agents)
- sudo with privilege flag (stdin/askpass/shell/list)
- git force push short flag (rewrites remote history)
- SQL DELETE without WHERE
- git branch force delete
- overwrite system config
- stop/restart hermes gateway via shell-spliced verb (kills running agents)
- execute_code
- copy/move file into /etc/
- find -delete
- delete in root path
- kill process via pgrep expansion (self-termination)
- overwrite project env/config file
- hermes update (restarts gateway, kills running agents)
- sudo with combined-flag privilege escalation
- disk copy
- in-place edit of system config
- overwrite project env/config via redirection
- world/other-writable permissions
- start gateway outside systemd (use 'systemctl --user restart hermes-gateway')
- shell execution via heredoc
- copy/move file into system config path
- copy/move file into /etc/
- shell execution via heredoc
- stop/restart hermes gateway via shell-spliced verb (kills running agents)
- sudo with combined-flag privilege escalation
- force kill processes (killall -KILL)
- overwrite system file via redirection
- delete in root path
- script execution via -e/-c flag
- kill process via pgrep expansion (self-termination)
- in-place edit of system config
- copy/move file into sensitive credential/SSH/shell-rc path
- pipe decoded content to shell (possible command obfuscation)
- git force push (rewrites remote history)
- kill hermes/gateway process (self-termination)
- git branch force delete
- force kill processes
- disk copy
- world/other-writable permissions
- stop/restart hermes gateway (kills running agents)
- start gateway outside systemd (use 'systemctl --user restart hermes-gateway')
- hermes update (restarts gateway, kills running agents)
- SQL TRUNCATE
- shell command via -c/-lc flag
- command parser limit or malformed executable payload
- execute_code
- in-place edit of Hermes config/env
- overwrite system file via tee
- stop/restart system service
- git reset --hard (destroys uncommitted changes)
- script execution via heredoc
- SQL DELETE without WHERE
- pipe remote content to shell
- overwrite project env/config via redirection
- overwrite project env/config file
- git force push short flag (rewrites remote history)
- sudo with privilege flag (stdin/askpass/shell/list)
- find -delete
- recursive delete
- overwrite system config
plugins:
disabled: []
enabled:
- agentic-sms-gateway
- cronalytics
- rtk-rewrite
- agentic-sms-gateway
- cronalytics
- rtk-rewrite
hooks_auto_accept: false
security:
allow_private_urls: false
@ -672,15 +673,15 @@ paste_collapse_char_threshold: 2000
_config_version: 39
known_plugin_toolsets:
cli:
- spotify
- spotify
mcp_servers:
codebase-memory-mcp:
command: /home/muc/.local/bin/codebase-memory-mcp
enabled: true
dbx:
args:
- -y
- '@dbx-app/mcp-server'
- -y
- '@dbx-app/mcp-server'
command: npx
connect_timeout: 60
enabled: true
@ -691,8 +692,8 @@ mcp_servers:
url: https://mcp.firecrawl.dev/v2/mcp
github:
args:
- -y
- '@modelcontextprotocol/server-github'
- -y
- '@modelcontextprotocol/server-github'
command: npx
enabled: true
env:
@ -700,30 +701,30 @@ mcp_servers:
timeout: 60
openclaw:
args:
- mcp
- serve
- mcp
- serve
command: /home/muc/nodejs/node-v24.16.0-linux-x64/bin/openclaw
connect_timeout: 60
timeout: 300
platform_toolsets:
cli:
- browser
- clarify
- code_execution
- computer_use
- cronjob
- delegation
- file
- image_gen
- memory
- session_search
- skills
- terminal
- todo
- tts
- vision
- web
- mcp-codebase-memory-mcp
- browser
- clarify
- code_execution
- computer_use
- cronjob
- delegation
- file
- image_gen
- memory
- session_search
- skills
- terminal
- todo
- tts
- vision
- web
- mcp-codebase-memory-mcp
firecrawl:
connect_timeout: 30
timeout: 120
@ -748,3 +749,25 @@ weixin:
group_policy: open
token: bef3c3d39904@im.bot:060000740c190c21262c8edf68365d5d112e0d
user_id: o9cq800DqpnMoqzXmJ4zozKiM8OI@im.wechat
# ── Fallback Model ────────────────────────────────────────────────────
# Automatic provider failover when primary is unavailable.
# Uncomment and configure to enable. Triggers on rate limits (429),
# overload (529), service errors (503), or connection failures.
#
# Supported providers:
# openrouter (OPENROUTER_API_KEY) — routes to any model
# openai-codex (OAuth — hermes auth) — OpenAI Codex
# nous (OAuth — hermes auth) — Nous Portal
# zai (ZAI_API_KEY) — Z.AI / GLM
# kimi-coding (KIMI_API_KEY) — Kimi / Moonshot
# kimi-coding-cn (KIMI_CN_API_KEY) — Kimi / Moonshot (China)
# minimax (MINIMAX_API_KEY) — MiniMax
# minimax-cn (MINIMAX_CN_API_KEY) — MiniMax (China)
# bedrock (AWS IAM / boto3) — AWS Bedrock (Converse API)
#
# For custom OpenAI-compatible endpoints, add base_url and key_env.
#
# fallback_model:
# provider: openrouter
# model: anthropic/claude-sonnet-4

View File

@ -25317,3 +25317,33 @@
{"memory_id": "mem_1787741454002165686", "accessed_at": "2026-09-11T02:44:52.706996", "decay_weight": 0.7701}
{"memory_id": "mem_1788971900514867459", "accessed_at": "2026-09-11T02:44:52.707012", "decay_weight": 0.9837}
{"memory_id": "mem_1788977611715367571", "accessed_at": "2026-09-11T02:44:52.707027", "decay_weight": 0.9847}
{"memory_id": "ep_1786293367801349858", "accessed_at": "2026-09-11T02:47:02.610256", "decay_weight": 0.5186}
{"memory_id": "mem_1787926246036813071", "accessed_at": "2026-09-11T02:47:02.610325", "decay_weight": 0.8021}
{"memory_id": "mem_1787407449194316558", "accessed_at": "2026-09-11T02:47:02.610349", "decay_weight": 0.7121}
{"memory_id": "ep_1786293372952742428", "accessed_at": "2026-09-11T02:47:02.610366", "decay_weight": 0.5186}
{"memory_id": "mem_1787450890745924038", "accessed_at": "2026-09-11T02:47:02.610381", "decay_weight": 0.7196}
{"memory_id": "mem_1787407006554170230", "accessed_at": "2026-09-11T02:47:02.610396", "decay_weight": 0.712}
{"memory_id": "mem_1787408267485686552", "accessed_at": "2026-09-11T02:47:02.610410", "decay_weight": 0.7122}
{"memory_id": "mem_1787741454002165686", "accessed_at": "2026-09-11T02:47:02.610424", "decay_weight": 0.77}
{"memory_id": "mem_1788971900514867459", "accessed_at": "2026-09-11T02:47:02.610439", "decay_weight": 0.9837}
{"memory_id": "mem_1788977611715367571", "accessed_at": "2026-09-11T02:47:02.610453", "decay_weight": 0.9847}
{"memory_id": "ep_1786293367801349858", "accessed_at": "2026-09-11T02:49:22.122686", "decay_weight": 0.5186}
{"memory_id": "mem_1787926246036813071", "accessed_at": "2026-09-11T02:49:22.122771", "decay_weight": 0.8021}
{"memory_id": "mem_1787407449194316558", "accessed_at": "2026-09-11T02:49:22.122797", "decay_weight": 0.712}
{"memory_id": "ep_1786293372952742428", "accessed_at": "2026-09-11T02:49:22.122815", "decay_weight": 0.5186}
{"memory_id": "mem_1787450890745924038", "accessed_at": "2026-09-11T02:49:22.122831", "decay_weight": 0.7196}
{"memory_id": "mem_1787407006554170230", "accessed_at": "2026-09-11T02:49:22.122846", "decay_weight": 0.712}
{"memory_id": "mem_1787408267485686552", "accessed_at": "2026-09-11T02:49:22.122861", "decay_weight": 0.7122}
{"memory_id": "mem_1787741454002165686", "accessed_at": "2026-09-11T02:49:22.122876", "decay_weight": 0.77}
{"memory_id": "mem_1788971900514867459", "accessed_at": "2026-09-11T02:49:22.122891", "decay_weight": 0.9836}
{"memory_id": "mem_1788977611715367571", "accessed_at": "2026-09-11T02:49:22.122906", "decay_weight": 0.9846}
{"memory_id": "ep_1786293367801349858", "accessed_at": "2026-09-11T02:51:32.910236", "decay_weight": 0.5186}
{"memory_id": "mem_1787926246036813071", "accessed_at": "2026-09-11T02:51:32.910319", "decay_weight": 0.8021}
{"memory_id": "mem_1787407449194316558", "accessed_at": "2026-09-11T02:51:32.910343", "decay_weight": 0.712}
{"memory_id": "ep_1786293372952742428", "accessed_at": "2026-09-11T02:51:32.910360", "decay_weight": 0.5186}
{"memory_id": "mem_1787450890745924038", "accessed_at": "2026-09-11T02:51:32.910377", "decay_weight": 0.7195}
{"memory_id": "mem_1787407006554170230", "accessed_at": "2026-09-11T02:51:32.910392", "decay_weight": 0.7119}
{"memory_id": "mem_1787408267485686552", "accessed_at": "2026-09-11T02:51:32.910407", "decay_weight": 0.7121}
{"memory_id": "mem_1787741454002165686", "accessed_at": "2026-09-11T02:51:32.910424", "decay_weight": 0.77}
{"memory_id": "mem_1788971900514867459", "accessed_at": "2026-09-11T02:51:32.910438", "decay_weight": 0.9836}
{"memory_id": "mem_1788977611715367571", "accessed_at": "2026-09-11T02:51:32.910476", "decay_weight": 0.9846}

View File

@ -34,6 +34,6 @@ git凭据已外置(09-11):4仓库remote无口令→~/.git-credentials(600)+crede
§
🔴铁律(牧尘09-11)任何任务第一步先扫技能库→skill_view加载(可组合),没扫就干=失职;汇报须列加载了哪些skill。
§
🔴wiki_curator(笔记→织忆)干跑=163篇拟灌14K节点(库仅18.6K),含提示词片段垃圾→勿启用;加固中t_68cbf702。详见memory-governance §四·九
🔴wiki_curator四闸门已加固(09-11,t_68cbf702):干跑107篇→2403(-89.5%),默认dry-run,cron无--commit。图谱预算待牧尘选(A/B/C=t_9fe5b918)
§
牧尘知识库规范v1.0.0(09-11):命名YYYYMMDD-短标题-状态/层级≤3/不确定进99-TEMP/移动归档先出清单等确认/定稿只归档不删/只用约定标签→notes-vault-curation references/vault-ops-contract.md。

View File

@ -1 +1 @@
{"entries": [{"lease_id": "6655ebb90a4f4272881926b91874d825", "metadata": {"live_session_id": "20260911_015149_4b76b6"}, "pid": 409050, "process_start_time": 1789062707.71, "session_id": "20260911_015149_4b76b6", "started_at": 1789062709.2163637, "surface": "cli", "updated_at": 1789062709.2163637}]}
{"entries": [{"lease_id": "25135f0ead894d5eb0457836b71d0daa", "metadata": {"live_session_id": "20260911_024851_a33446"}, "pid": 423951, "process_start_time": 1789066130.57, "session_id": "20260911_024851_a33446", "started_at": 1789066132.0585299, "surface": "cli", "updated_at": 1789066132.0585299}, {"lease_id": "b2d95693ac16445e8422fb65b82d692e", "metadata": {"chat_id": "oc_cd14ec7518926e57d26c5e339ebba3b3", "live_session_id": "agent:main:feishu:dm:oc_cd14ec7518926e57d26c5e339ebba3b3:omt_19c74e2f5c8f1ce7", "platform": "feishu", "user_id": "ou_f20eb15b3a76639fed35977c01ddcbb4"}, "pid": 191160, "process_start_time": 1789014696.73, "session_id": "agent:main:feishu:dm:oc_cd14ec7518926e57d26c5e339ebba3b3:omt_19c74e2f5c8f1ce7", "started_at": 1789066294.4054003, "surface": "gateway:feishu", "updated_at": 1789066294.4054003}]}

125
scripts/mc-p2-migrate.py Normal file
View File

@ -0,0 +1,125 @@
#!/usr/bin/env python3
"""P2 迁移执行器 —— 按云版(v3)映射搬 07-Wiki 114 篇 + 重写链接 + 验收2026-09-11
四步
0. 备份tar 快照到 ~/.hermes/backups/
1. 解析 v3 映射表注意表格只 3 个反引号列
2. 搬文件 重写 A短链/B长链/C相对链/D资源链
3. 清空目录
4. 验收 link-inventory.py断链数必须 基线
用法 python3 mc-p2-migrate.py [--dry]
"""
import os, re, sys, subprocess, time, tarfile
V = "/home/muc/mc"
MAPF = V + "/小唯/00-INDEX/00-03-总索引/20260911-P2迁移映射表v3-云复核-WIP.md"
DRY = "--dry" in sys.argv
BASE_BROKEN = 15
# ── 0. 备份 ──
bk = os.path.expanduser(f"~/.hermes/backups/mc-pre-p2migrate-{time.strftime('%Y%m%d-%H%M%S')}.tar.gz")
os.makedirs(os.path.dirname(bk), exist_ok=True)
if not DRY:
with tarfile.open(bk, "w:gz") as t:
t.add(V + "/小唯/07-Wiki", arcname="07-Wiki")
print(f"0. 备份: {bk} ({os.path.getsize(bk)//1024} KB)")
# ── 1. 解析映射 ──
start = time.time()
mp = {} # old_rel(no .md) -> new_rel(no .md)
for line in open(MAPF, encoding="utf-8"):
if not line.startswith("| "):
continue
cells = re.findall(r"`([^`]+)`", line)
if len(cells) != 3:
continue
old, new = cells[0], cells[2]
if not old.startswith("小唯/07-Wiki/"):
continue
mp[old[:-3] if old.endswith(".md") else old] = new[:-3] if new.endswith(".md") else new
print(f"1. 映射 {len(mp)} 条({time.time()-start:.0f}s")
if not mp:
sys.exit("❗ 映射为空,中止")
# ── 2. 搬文件 ──
moved = 0
for old, new in mp.items():
src, dst = os.path.join(V, old + ".md"), os.path.join(V, new + ".md")
if not os.path.exists(src):
continue
os.makedirs(os.path.dirname(dst), exist_ok=True)
if DRY:
moved += 1
continue
r = subprocess.run(["git", "mv", "-f", src, dst], cwd=V, capture_output=True, text=True)
if r.returncode != 0:
os.replace(src, dst)
moved += 1
print(f"2. 搬移 {moved}")
# ── 3. 重写链接 ──
def rel_from(containing_new, target_new):
"""从 containing 的所在目录算到 target 的相对路径"""
return os.path.relpath(os.path.join(V, target_new + ".md"),
os.path.dirname(os.path.join(V, containing_new + ".md")))
md_files = []
for root, dirs, files in os.walk(V):
if any(e in root for e in ("/.git", "/.obsidian", "/.openclaw-wiki")):
continue
for f in files:
if f.endswith(".md"):
md_files.append(os.path.join(root, f).replace(V + "/", ""))
fix_wiki = fix_rel = 0
for rel in md_files:
fp = os.path.join(V, rel)
try:
c = open(fp, encoding="utf-8").read()
except UnicodeDecodeError:
continue
o = c
# A/Bwikilink长/短链都含路径形式)—— 直接按映射做路径替换
for old, new in mp.items():
if old in c:
c = c.replace(old, new)
# C相对 md 链接 —— 重新计算
def sub_rel(m):
global fix_rel
u = m.group(1)
if u.startswith(("http", "mailto", "#")):
return m.group(0)
frag = ""
if "#" in u:
u, frag = u.split("#", 1); frag = "#" + frag
tgt = os.path.normpath(os.path.join(os.path.dirname(rel), u)).replace(".md", "")
if tgt in mp:
fix_rel += 1
return f"({os.path.relpath(os.path.join(V, mp[tgt] + '.md'), os.path.dirname(os.path.join(V, rel))).replace(os.sep,'/')}" + \
(".md" if u.endswith(".md") else "") + f"{frag})"
return m.group(0)
c = re.sub(r"\]\(([^)]+)\)", sub_rel, c)
if c != o and not DRY:
open(fp, "w", encoding="utf-8").write(c)
fix_wiki += 1
print(f"3. 重写:{fix_wiki} 个文件被改(含相对链 {fix_rel} 处)")
# ── 4. 清空目录 ──
empty = []
for root, dirs, files in os.walk(V + "/小唯/07-Wiki", topdown=False):
if not os.listdir(root):
empty.append(root);
if not DRY:
os.rmdir(root)
print(f"4. 清掉空目录 {len(empty)}")
# ── 5. 验收 ──
if not DRY:
r = subprocess.run(["python3", os.path.expanduser("~/.hermes/scripts/link-inventory.py")],
capture_output=True, text=True)
tail = r.stdout
print("\n5. === 链接验收 ===")
for ln in tail.split("\n"):
if any(k in ln for k in ("短链", "长链", "相对md", "资源链", "涉及文件", "已是断链", "重名笔记")):
print(" " + ln.strip())
print(f"\n耗时 {time.time()-start:.0f}s {'(DRY)' if DRY else ''}")

View File

@ -606,3 +606,4 @@
{"id": "00baef7866c8", "ts": "2026-09-10T18:42:18.475509+00:00", "actor": "curator", "action": "patch", "skill": "notes-vault-curation", "evidence": {"session_id": "20260910_231327_7e13724d"}, "before": [{"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/SKILL.md", "sha256": "54a9285a14ed7a90b37aeaf5faef8d6f2bbb7f616d5aee6ac77e3228dcd7cf71"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/classification-taxonomy.md", "sha256": "e3f27e44dbb5fd735eeff4a8dc41f035a95a5e87317ff6b18cd456b42a1a26d0"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/vault-audit-and-credential-consolidation.md", "sha256": "54d15e860b738d56da4363818b568c5e192a1d0447a1238181ebc26d23224b3f"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/vault-ops-contract.md", "sha256": "1758a974147823b1ddcb305a425f68bfb1034ed3534ffe424430a3b9d65caa65"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/scripts/vault-audit.py", "sha256": "7d21ae8743393162f8c81f44b4f108d4846b4b8fcb33bd74a682bdffbef64e4a"}], "after": [{"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/SKILL.md", "sha256": "ef2c0ea4c3cc2972e4d52a01a3f4faecac542f04e970cf4f760f45436cbdf5da"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/classification-taxonomy.md", "sha256": "e3f27e44dbb5fd735eeff4a8dc41f035a95a5e87317ff6b18cd456b42a1a26d0"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/vault-audit-and-credential-consolidation.md", "sha256": "54d15e860b738d56da4363818b568c5e192a1d0447a1238181ebc26d23224b3f"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/vault-ops-contract.md", "sha256": "1758a974147823b1ddcb305a425f68bfb1034ed3534ffe424430a3b9d65caa65"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/scripts/vault-audit.py", "sha256": "7d21ae8743393162f8c81f44b4f108d4846b4b8fcb33bd74a682bdffbef64e4a"}]}
{"id": "9e5c757c36d2", "ts": "2026-09-10T18:44:55.321471+00:00", "actor": "agent", "action": "patch", "skill": "memory-governance", "evidence": {"session_id": "20260911_015149_4b76b6"}, "before": [{"path": "/home/muc/.hermes/skills/knowledge/memory-governance/SKILL.md", "sha256": "a14c7bdd2f89c4ec05d56a93661c8cef7d522e2455890e81b518c7aaa3c6b11b"}, {"path": "/home/muc/.hermes/skills/knowledge/memory-governance/references/2b-compressor-test-20260910.md", "sha256": "175820266a1347ed0f1ba89b76926362e3bed8a8a5a530f210ee00bc5798e415"}, {"path": "/home/muc/.hermes/skills/knowledge/memory-governance/references/zhiyi-data-quality-audit-20260907.md", "sha256": "0a9a3f4a50d8372eb9d1e6dd3b2f1e6b4a45a22988fea5d1ce5fc676a7c91876"}, {"path": "/home/muc/.hermes/skills/knowledge/memory-governance/references/zhiyi-quality-cleanup-live-only-20260908.md", "sha256": "bf583c3cebfbb6c28e5203ac4637d325ea07ade27286e795501e4ef0f9587d68"}], "after": [{"path": "/home/muc/.hermes/skills/knowledge/memory-governance/SKILL.md", "sha256": "d784fc80be8f27b39981f59a767fdf67c6b787380aab29e2e64ff3670f91daf1"}, {"path": "/home/muc/.hermes/skills/knowledge/memory-governance/references/2b-compressor-test-20260910.md", "sha256": "175820266a1347ed0f1ba89b76926362e3bed8a8a5a530f210ee00bc5798e415"}, {"path": "/home/muc/.hermes/skills/knowledge/memory-governance/references/zhiyi-data-quality-audit-20260907.md", "sha256": "0a9a3f4a50d8372eb9d1e6dd3b2f1e6b4a45a22988fea5d1ce5fc676a7c91876"}, {"path": "/home/muc/.hermes/skills/knowledge/memory-governance/references/zhiyi-quality-cleanup-live-only-20260908.md", "sha256": "bf583c3cebfbb6c28e5203ac4637d325ea07ade27286e795501e4ef0f9587d68"}]}
{"id": "40e73c036978", "ts": "2026-09-10T18:44:56.900248+00:00", "actor": "agent", "action": "patch", "skill": "local-2b-task-triage", "evidence": {"session_id": "20260910_231327_7e13724d", "file_path": "references/failure-modes.md"}, "before": [{"path": "/home/muc/.hermes/skills/autonomous-ai-agents/local-2b-task-triage/SKILL.md", "sha256": "353e06d454aa28df972ad984f25009dbcda416908d4afbef2ca1b9cd77401727"}, {"path": "/home/muc/.hermes/skills/autonomous-ai-agents/local-2b-task-triage/references/failure-modes.md", "sha256": "22be5916a811c366a526c17e304e35b2f426d5fb4e31762b3372f47416d6b24e"}], "after": [{"path": "/home/muc/.hermes/skills/autonomous-ai-agents/local-2b-task-triage/SKILL.md", "sha256": "353e06d454aa28df972ad984f25009dbcda416908d4afbef2ca1b9cd77401727"}, {"path": "/home/muc/.hermes/skills/autonomous-ai-agents/local-2b-task-triage/references/failure-modes.md", "sha256": "da57651fdb96b5f6e697c24bf74a8a5525d07c1294cabb12b5e48138fa6351fb"}]}
{"id": "e5166411a99c", "ts": "2026-09-10T18:52:07.739529+00:00", "actor": "agent", "action": "write_file", "skill": "notes-vault-curation", "evidence": {"session_id": "20260910_231327_7e13724d", "file_path": "references/migration-pitfalls.md"}, "before": [{"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/SKILL.md", "sha256": "ef2c0ea4c3cc2972e4d52a01a3f4faecac542f04e970cf4f760f45436cbdf5da"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/classification-taxonomy.md", "sha256": "e3f27e44dbb5fd735eeff4a8dc41f035a95a5e87317ff6b18cd456b42a1a26d0"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/vault-audit-and-credential-consolidation.md", "sha256": "54d15e860b738d56da4363818b568c5e192a1d0447a1238181ebc26d23224b3f"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/vault-ops-contract.md", "sha256": "1758a974147823b1ddcb305a425f68bfb1034ed3534ffe424430a3b9d65caa65"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/scripts/vault-audit.py", "sha256": "7d21ae8743393162f8c81f44b4f108d4846b4b8fcb33bd74a682bdffbef64e4a"}], "after": [{"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/SKILL.md", "sha256": "ef2c0ea4c3cc2972e4d52a01a3f4faecac542f04e970cf4f760f45436cbdf5da"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/classification-taxonomy.md", "sha256": "e3f27e44dbb5fd735eeff4a8dc41f035a95a5e87317ff6b18cd456b42a1a26d0"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/migration-pitfalls.md", "sha256": "2c4d13b2b9ff01801e1c0b087e4ab837381efd04f17cce2849e914411dc01655"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/vault-audit-and-credential-consolidation.md", "sha256": "54d15e860b738d56da4363818b568c5e192a1d0447a1238181ebc26d23224b3f"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/references/vault-ops-contract.md", "sha256": "1758a974147823b1ddcb305a425f68bfb1034ed3534ffe424430a3b9d65caa65"}, {"path": "/home/muc/.hermes/skills/devops/notes-vault-curation/scripts/vault-audit.py", "sha256": "7d21ae8743393162f8c81f44b4f108d4846b4b8fcb33bd74a682bdffbef64e4a"}]}

View File

@ -2003,14 +2003,14 @@
"created_by": null,
"last_patched_at": null,
"last_reused_patch_generation": 0,
"last_used_at": "2026-09-09T17:47:18.634553+00:00",
"last_viewed_at": "2026-09-09T17:47:18.629688+00:00",
"last_used_at": "2026-09-10T18:45:36.759516+00:00",
"last_viewed_at": "2026-09-10T18:45:36.754783+00:00",
"patch_count": 0,
"patch_generation": 0,
"pinned": false,
"state": "active",
"use_count": 18,
"view_count": 18
"use_count": 19,
"view_count": 19
},
"karpathy-code-discipline": {
"archived_at": null,
@ -2575,12 +2575,12 @@
"archived_at": null,
"created_at": "2026-09-10T14:02:56.324787+00:00",
"created_by": "agent",
"last_patched_at": "2026-09-10T18:42:18.476319+00:00",
"last_patched_at": "2026-09-10T18:52:07.740768+00:00",
"last_reused_patch_generation": 36,
"last_used_at": "2026-09-10T18:41:51.953845+00:00",
"last_viewed_at": "2026-09-10T18:41:51.948970+00:00",
"patch_count": 40,
"patch_generation": 40,
"patch_count": 41,
"patch_generation": 41,
"pinned": false,
"state": "active",
"use_count": 12,

View File

@ -0,0 +1,53 @@
# 目录迁移事故与铁律2026-09-11 实测,丢过 90 个文件)
## 事故经过
按云映射表搬 `小唯/07-Wiki` 114 篇 → 六域五件套。
结果:**md 总数 465 → 37590 个文件从工作区消失**git 显 `94 D`
`git reset --hard HEAD` 恢复(删除只在暂存区、未提交)→ 全部回来。
## 三个具体原因
### 1. 骨架目录名与映射目标不一致(根因)
```
我建的骨架: 小唯/05-AI-AGENT/05-01-定义规范/ ← 带 05- 前缀
映射表目标: 小唯/05-AI-AGENT/01-定义规范/ ← 不带前缀
⇒ 目标目录不存在,`git mv` 失败
```
**根本教训**:骨架命名和迁移目标**必须由同一个常量生成**,不能一边手写一边从表格读。
### 2. `os.replace` 兜底 = 静默毁盘(最危险)
```python
r = subprocess.run(["git","mv","-f",src,dst], ...)
if r.returncode != 0:
os.replace(src, dst) # ❌ 失败还继续挪,且不验证 dst 是否合理
```
**改成 fail-fast**
```python
if r.returncode != 0:
print(f"❗git mv 失败,中止: {src} → {dst}\n{r.stderr}"); sys.exit(1)
```
宁可全停,不可带病继续。搬一半比不搬危害大得多。
### 3. 「DRY RUN」只验证了输入没验证输出
dry 模式打印了「映射 114 条」——**这只证明表格解析没问题**
根本没检查「目标目录是否存在 / 能否写入」。**这不是 dry-run是自我安慰。**
## 迁移铁律(写死)
1. **前置校验dry-run 必须做)**:逐条检查 dst 父目录存在(不存在则报错并列出),输出前 20 条 `src → dst` 给人看
2. **命名同源**:骨架目录名与映射目标的生成规则**来自同一函数/常量**
3. **fail-fast**:任何一步失败 → `sys.exit(1)`**禁止兜底式继续**
4. **先小样再全量**:先搬 3 篇 → 跑 `link-inventory.py` → 确认无损失 → 再全量
5. **恢复预案先行**:动手前确认两条恢复链都可用
- `git status` 确认目标区在版本控制内
- `tar` 快照落盘(本次 568KB救不了命是因为脚本 bug 而非备份缺失)
6. **恢复命令**(删除若已暂存,`git checkout -- .` **无效**
```bash
git reset --hard HEAD # 需审批,会丢弃未提交改动
```
⇒ 所以**动手前先 commit**,让「未提交改动」为空,恢复才无损。
## 一句话
> **迁移脚本的第一性原理:失败就停,不许兜底。**
> 兜底逻辑会把「报错」变成「数据消失」——报错你还有机会,数据没了就没了。

View File

@ -1,6 +1,6 @@
{
"version": 2,
"updated_at": "2026-09-11T02:44:53.780325",
"updated_at": "2026-09-11T02:51:33.865674",
"behavior_rules": {
"answer_format": "结论先行 → 数据支撑 → 行动建议。不废话、不科普、不加补丁式回答。",
"code_quality": "修复后必须自测不等用户测。遇到stderr先试3种方法不行再报告障碍。",
@ -145,7 +145,7 @@
],
"last_distilled": "2026-09-04T19:48:29.894767+00:00",
"沟通/工作模式": "简洁直接",
"正在进行的项目": "整个系统拓扑到底是什么样的",
"正在进行的项目": "决定将多个问题归结为‘整个系统拓扑到底是什么样的’这一核心问题",
"新发现的偏好": "跨平台工作流方案",
"沟通风格": "简洁直接",
"跨平台工作流": "已确认",
@ -188,6 +188,6 @@
"模型确认行为": "用户提到助手名为'牧尘'",
"助手名": "牧尘",
"核心项目": "整个系统拓扑到底是什么样的",
"核心问题": "将多个问题归结为'整个系统拓扑到底是什么样的'这一核心问题",
"核心问题": "整个系统拓扑到底是什么样的",
"模型使用策略": "会话采用了本地2B模型作为主力超2B上限大会话采用2B分段策略"
}