按「主文留头量、深规程外置」重写本仓技能,全部是逐字搬移:
搬移前断言原文每条非空行必须出现在新主文或 reference 文件里,
0 丢失才落盘;步骤编号一律不重排(正文有「第 12 步」交叉引用);
每个切点保留原小标题 + 索引(加粗引导句与步骤标题)+ 指针行。
主文变化(上限口径 = 插件写侧 65536 字节,见上一笔 skill-size 钩子):
- id-family-semantic-migration 33392 -> 10968(17%),reference 3 篇
- stale-doc-count-sweep 19811 -> 6945(11%),reference 2 篇
- mem-budget 19963 -> 13042(19%),reference 3 篇
- keil-build 12917 -> 8879(14%),reference 2 篇
- task-worktree 72601 -> 28139(42%),reference 8 篇
task-worktree 本笔同时收录另一会话已写完的 C2/D/G 三节正文——那
三处手改与我的拆分落在同一份文件改动里,不可分离;其内容同样已
随 reference/ 外置,主文只剩标题、索引与指针。
外置语料合计 122211 字节 / 30 篇:围栏数逐篇为偶,无 BOM/CR/U+FFFD。
draw-diagram 与 serial-boot-test 脚本是另一会话的在飞改动,本笔未含。
skill-size 钩子在本笔首次真跑(前一笔无 .dsh/skills 文件可触发)。
gate: pre-commit 全绿(doc-links、id-check-new、check-yaml、
skill-size、check-added-large-files);30 篇 reference 手工字节
体检 clean;skill() 逐个复载确认加载的是拆分版。
28 KiB
name, description, whenToUse
| name | description | whenToUse |
|---|---|---|
| task-worktree | 多任务并行开发的空间管理(git worktree 生命周期):`@task new` 开工作树+任务分支、目录联接共享 .venv 与模拟器 SDK、活跃上限 8 与腾位(A 节)、build/bench 两类独占锁与非登记持有者「缺台账」释放不掉(B 节)、`done` 是合并点不是查看器(C 节)、主工作树被别的并发会话弄脏时的手工合并路径(C2 节,详情已外置)、门禁指标异常增长时用净室工作树逐文件归因(D 节,外置)、回收 `@task list` 看不到的工作树并清悬挂台账(E 节,外置)、与 DSH worktree 插件 `/worktree`、`worktree_create` 共存(F 节,外置)、任务树内跑门禁与 `simulator/SDL2` 联接假红、树内提交/合并信息的禁词自检(G 节,外置)、插件树两条共享联接的分级(`simulator/SDL2` 是硬需求、`.venv` 有解释器逃生门,F 节,外置)、并行上限数字的唯一事实源(`MAX_CONCURRENT`)。规格见 docs/环境与部署/并行任务工作树方案.md;标「外置」的深规程全文在本技能目录 reference/ 下,动手前先读对应那篇。 | 要同时推进多个任务、担心同分支同文档互相冲突;要为新任务开隔离空间;要把任务合并回主干;或遇到 `new` 报「已有 8 个活跃任务(上限 8)」、`lock release` 报「任务 X 不存在(缺台账)」、`done` 报「门禁未全绿」或「主工作树不干净」而那份未提交改动是别的会话/插件留下的、两个任务抢 COM6 / UV4、"改了文档被覆盖"、并集合并残留;或要在任务树里跑文档/审计门禁(往 `ci-artifacts/` 写输出报 ENOENT、`--all` 的问题全在 `simulator/SDL2` 联接下);或门禁指标异常增长(如不可判定数 +16)却查不出是哪个文件造成的;或要回收 `@task list` 里根本看不到的工作树、清台账里 branch/path 都已不存在的悬挂条目;或任务是在任务树里改文档再合主干、要写提交/合并信息(被清退的主题不得在消息里复现);或想确认插件工作树里 `.venv` 与 `simulator/SDL2` 到底哪个必须补;或要改并行上限这个数字并同步全仓口径。 |
task-worktree — 多任务并行开发空间(短命令 @task)
执行体 = 本 skill 自带脚本 .dsh/skills/task-worktree/scripts/task_worktree.py
(纯标准库,任意 python3;拷整个 skill 目录到别的项目即可用)。
本文档受 dsh-mnemon 写侧上限 65536 字节约束(实测 2026-10-29:正文涨到 72,601 字节后,技能自进化每次「生成草案」都被写侧拒绝、 那一行永久卡在「生成中」)。所以新增的深规程写进 reference/<篇名>.md,本文只留可执行判据的摘要 + 指针;瘦身前的 frontmatter 原文逐字留在 reference/frontmatter-history.md。动手做某条深规程前,先把对应那篇 reference 读完(摘要只用来判定要不要读)。
@T3@powershell
cwd = 仓库根(或任意子目录)
& $PY ".dsh\skills\task-worktree\scripts\task_worktree.py" <子命令> [参数] @T3@
bash(ops_bash)里固定两个变量,下文用 $TW 代指脚本:
@T3@bash PY=".venv/Scripts/python.exe"; TW=".dsh/skills/task-worktree/scripts/task_worktree.py" "$PY" "$TW" list @T3@
退出码:0=成功 / 1=操作失败 / 2=前置或环境错误 / 3=用法。
⚠ 这几个码只有「不接管道」时才读得到——原因与对策见「读输出」一节。
固定命令
| 命令 | 作用 |
|---|---|
new <ID> <slug> |
建分支 task/<ID>-<slug> + 工作树 + 共享联接 + 台账;打印新空间路径 |
list |
所有任务一览:分支 / 落后领先 / 脏文件数 / 台架状态 + 两个锁的归属 |
status <ID> |
单任务详情(未提交清单、相对基线漂移、台架记录、已建联接) |
sync <ID> |
在任务工作树里 rebase 追平主干,把冲突控制在任务分支上 |
lock acquire|release|status <build|bench> |
独占资源锁 |
plugin list|adopt|unadopt [插件树名] |
与 DSH worktree 插件的桥:看清单 / 补共享联接 / 摘联接(不删树)→ F 节 |
done <ID> |
预演 → 合入主干 → 并集残留审计 → 重生成产物 → 门禁 → 清场(主树被别的会话弄脏时改走 C2 手工合并) |
abort <ID> |
放弃任务(工作树 + 分支一起删,永久丢弃) |
new 常用开关:--base <分支>(默认 v2-on-ui)· --needs-bench(无台架 PASS 则 done 拒合)·
--lean(跳过 Git LFS smudge)· --no-bootstrap(不建联接)·
--force(仅跳过并发上限 8 的检查,不解决「谁该让位」,见 A 节)。
done 常用开关:--dry-run(只预演,零改动)· --skip-build · --skip-gates · --force(清场时强制移除工作树)。
lock 开关:--task <ID>(acquire 必填)· --wait <秒> · --ttl <小时>(自报窗口)· --note <文本> ·
--bench-pass(release 时给台账记 PASS)· --force。
⚠ --note 只在 acquire 时写进锁 payload,release 时被忽略——别指望它留下验收证据(证据写进主干提交说明或文档)。
环境变量(高级):DTU_WT_ROOT(任务容器位置,默认仓库同级 _wt/)·
DTU_TASK_BASE(默认基线分支,默认 v2-on-ui)·
DTU_INTEGRATION_WORKTREE(集成点,默认主工作树——用于隔离演练/测试)。
典型流程
@T3@powershell & $PY ".dsh\skills\task-worktree\scripts\task_worktree.py" new N21 dhara-isfree --needs-bench
→ 把新会话的工作目录切到打印出来的 _wt/N21-dhara-isfree/,在那里干活
& $PY ".dsh\skills\task-worktree\scripts\task_worktree.py" lock acquire bench --task N21
烧录 / @test / 板级套件……
& $PY ".dsh\skills\task-worktree\scripts\task_worktree.py" lock release bench --task N21 --bench-pass
回到主工作树执行回收
& $PY ".dsh\skills\task-worktree\scripts\task_worktree.py" done N21 @T3@
读输出:管道与截断(两起误判的共同根因)
... 2>&1 | tail -N的退出码是tail的,恒为 0 → 脚本的1/2全被吞。实测三条印着 「rc=0」的输出其实都是 exit 2:new撞活跃上限、lock release缺台账两次。 所以判据先看文本([ok]/!!/前置/环境错误:/失败:),要真码就直接执行不接管道或补一句echo RC=$?;坚持接管道就在 bash 里取${PIPESTATUS[0]}。done/done --dry-run的输出不要用tail -2截:接管道时 python 的 stdout 是块缓冲、git 子进程的 stderr 不缓冲,两股流错位混排,tail -2只剩「--dry-run:到此为止…」加上 stderr 里带conflict字样的片段 → 据此误判「有冲突」。实测:tail -2误读成 conflict,放宽到tail -10才看到[ok] 无冲突,预演结果树 <sha>。dry-run 全文只有 5~8 行,直接读全量。
分步操作(八条运行时机制)
A. new 被拒「已有 8 个活跃任务(上限 8)」——怎么腾位
- 读原文:
前置/环境错误:已有 8 个活跃任务(上限 8);先 done/abort,或加 --force(exit 2)。 上限是脚本常量MAX_CONCURRENT = 8;「活跃」的判据 =_wt/.state/<ID>.json台账存在,且台账里path指向的目录还在(手工删了工作树目录就不占名额,但会留下悬挂台账,见第 5 步与 E 第 6 步)。 $TW list看全景(分支 / 落后领先 / 脏文件数)决定谁让位:已完成的先done(合并回收,一步不省)。- 没人认领、零提交、尚未 claim 的空闲树 →
abort <ID>腾位(实测就是 abort 掉排在后面的空闲树换出名额)。abort= 工作树 + 分支一起删、永久丢弃;工作树有未提交改动或已有提交时脚本会拒绝,确认可弃再加--force。 - 确实要同时开第 9 棵才
new <ID> <slug> --force:磁盘代价约 83 MB/棵(--lean约 45 MB), 并行度上去了、冲突面与台架排队也一起上去——不是免费的。 - 别用手工
git worktree remove给「登记任务」腾位:台账不会被删(下次new同 ID 会报「任务 已存在」), 还绕过了「先摘联接」(铁律 5),有让 git 递归进联接把主工作树.venv删掉的风险。要回收的若是非登记树 ($TW list里根本没有它:new出来又被手工删掉只剩悬挂台账的残骸 / D 节--detach净室 / 别的会话手工建的) → 腾位与回收一起走 E 节,那里有「怎么证明这棵树零联接所以可以 remove」的可执行判据。 - 腾位后复验:
$TW list的条目数与ls _wt的目录数一致,再new。
B. 非登记持有者占的锁:lock release --bench-pass 曾报「任务 X 不存在(缺台账)」
症状(lead 在主工作树跑台架验收窗,用临时名占锁 lock acquire bench --task acceptwin):
@T3@bash "$PY" "$TW" lock release bench --task acceptwin --bench-pass 前置/环境错误:任务 acceptwin 不存在(缺台账 _wt/.state/acceptwin.json) # 锁照旧挂着 "$PY" "$TW" lock release bench --task acceptwin --force --bench-pass # 同一句错误,锁仍在 @T3@
根因:release 分支里只要带 --bench-pass 就先 load_state(task) 去台账写 PASS,而 acquire 侧
不查台账——这个不对称让「释放」被「记账」挡死(--force 只覆盖持有者不符与陈旧接管,管不到台账)。
后果比报错本身大:锁没放,done 的前置 release_stale_locks() 对未到 TTL 的活锁直接判失败 →
一个名字没登记,就挡住所有任务的收口。
2026-10-29 起已修(task_worktree.py:无台账降级为 [warn] …跳过 PASS 记录,仅释放锁 并照常释放)。
现在的正解只有三步,不再需要手写占位台账:
$TW lock status认现场(持有者 / pid / 已持有时长 / TTL)——别对同一句报错反复重试 release。$TW lock release <build|bench> --task <NAME> [--bench-pass]直接放;PASS 记不上会打印 warn,锁照放。- PASS 后面还要用(
done只认台账里的bench_pass)→ 从一开始就用已new出来的任务 ID 占锁, 或把验收结论写进主干提交说明 / 文档。插件树pw:<name>天然没有台账,别指望它留 PASS → F 节。
最后手段(脚本本身都走不通时):锁就是 _wt/.state/locks/<name>.lock 里的单行 JSON
(name/task/pid/host/epoch/at/note/ttl),release 的实现就是 unlink 它——手工删这个文件等价于
「不记 PASS 的强制释放」,只在前面几步都不可用时才用。历史遗留的占位台账(早期为绕这个坑手写的
_wt/.state/<NAME>.json)现在已无必要:它活着时既占 MAX_CONCURRENT = 8 名额又被 list 当任务列出,
按 E 第 6 步备份后删掉即可。
C. done <ID> 的正确用法(它是合并点,不是查看器)
- 合并前确认任务属主已把全部改动提交完。
$TW status <ID>看未提交清单与领先提交数;跨会话任务 再问一句属主(send_message)。实测教训:属主还剩「2/2」没提交就done,把只含 1/2 的分支合进了主干, 只能另开一棵树补后半并向对方说明(是自己的时序错,不是分支问题)。 - 先
--dry-run,并读全量输出(别tail -2,见「读输出」)。判据两行:[ok] 前置检查通过(领先 <base> 共 N 个提交)+[ok] 无冲突,预演结果树 <sha>; N 必须等于属主应交的提交数,对不上回到第 1 步。dry-run 零改动。 - 正式
$TW done <ID>——必须在主工作树(铁律 1)。 - 输出
!! 门禁未全绿:工作树与分支**保留**,未清场时,紧跟的主干已含合并提交 <sha>已经说明 合并落进主干了。- ✅ 走提示里的 a) 在主工作树修正后追加提交;
- ❌ 绝不用 b) 的
git -C "<主树>" reset --hard <sha>——那是丢弃已入库的合并提交,而reset --hard本身是项目级 Never(会连未提交工作一起丢)。提示 b 只是列出的可能性,不是建议。 - 先定位是哪条钩子红:门禁输出里的
[SUMMARY] static: pre-commit hooks -- passed=N failed=M, 不同根因处置不同(见陷阱「done的门禁 =pre-commit run --all-files」)。最常态是.map滞后 → 第 5 步。
- 补绿固定链(2026-10-25 实测;顺序即因果,全在主工作树跑,逐条不接管道看退出码):
@T3@bash "$PY" scripts/check_mem_numbers.py --write # 台账受管区 ↔ 新 .map 对齐 "$PY" scripts/ram_baseline.py --write # RAM 快照 / 92% 预算台账 "$PY" scripts/ram_baseline.py --update # 趋势基线追加一行 "$PY" scripts/check_test_coverage.py --update-baseline # 覆盖率基线(新单测 / 新套件时必刷) "$PY" scripts/check_doc_links.py --all # 文档链接与章节引用 git add <上面几条刷出来的基线/快照文件> # 显式列文件,别 -A 把别人在飞的改动一起提交 git commit -F <UTF-8 无 BOM 的正文文件> # 提交属 Ask first(AGENTS.md 边界),按用户指示再做 @T3@
为什么必然要补,见陷阱「done 的门禁跑在 @build 之前」。
6. 重跑 done 之前主工作树必须干净——否则前置检查直接
失败:主工作树不干净(…)——合并会把未提交改动卷进来,所以第 5 步的产物必须先提交。重跑时若分支
已并入,会打印 [i] task/<ID>-<slug> 已合入 <base>,跳过合并,直接清场 → 摘联接 → 完成(分支此前已合入)。
7. 清场完成后再敲一次 done <ID> 会得到 前置/环境错误:任务 <ID> 不存在(缺台账 …json)(exit 2)——
这不是失败:清场的最后一步 unlink 了台账。判完成以 git log 为准。
C2. done 被「主工作树不干净」挡住,而那份脏改动是别的并发会话留下的
- 不许对那份外部脏改动做 stash / checkout / reset / 提交 / 删除(项目级 Never,你也不知道它写没写完);
done的前置要求主工作树干净,于是合并与回收一起被挡——这是挡给你看的保护,不是工具坏了。 - 正解链(六步):取证(mtime + diff 定性有无交集,顺手
worktree list看有没有别人中途新建的树)→git merge-tree --write-tree <base> <task 分支>预演(判据:打出结果树 sha 且 RC=0)→ 主树git merge --no-ff --no-edit -F ci-artifacts/merge-msg-<slug>.txt <task 分支>→ 合并后把git hash-object <外部文件>与git diff --stat和合并前存下的值逐项对账(实测同为369380ca…、2+/2− → 证明 pre-commit 自己的 stash 往返没动别人的工作)→ 台账先cp成<ID>.json.state-bak再让done(或 E 节 手工路径)自己摘 .venv / simulator/SDL2 联接拆树 →worktree list+lock status复验收工。 - 报告里要写明绕开
done的理由并逐项补回它的证据:预演 sha + RC=0、blob id 对账、合并后在 主树跑全库check_doc_links.py --all(见 G 节)、两把锁空闲;并且点名那份外部脏文件与中途冒出来的第二棵树 (谁的、怎么定性、你没动它的证据)。blob id 变了 = stash pop 半冲突:立刻停止收工,两份 blob id 与两份 diff 交给该文件属主,绝不checkout抹平。 - 认得出它:本仓这份外部脏改动两次都是
.dsh/skills/serial-boot-test/scripts/run_boot_test.py(2+/2−,别的会话/插件正在写它)——别把它当成自己漏提交的文件去提交或清掉。同一次窗口里git -C "$MAIN" worktree list还会冒出别人中途新建的第二棵树(实测data-trust-restructure),那是并发会话的硬证据:点名写进报告,并且不是你的树就别顺手回收(→ E 节)。 - 合并信息也过 G 节的禁词自检:清退/删主题类任务,
merge:那行与正文里被清退主题的关键词计数必须是 0。
详情已外置(本文件须留头量给自进化:dsh-mnemon 写侧上限 65536 字节,超限的技能再也生不成草案)。全文见 reference/merge-dirty-main-tree.md —— 主树被别的并发会话弄脏时的手工合并路径(取证 →
merge-tree预演 → 主树merge --no-ff -F→ 外部改动 blob id /diff --stat前后对账)。
D. 门禁指标异常增长 → 逐文件归因(把净室工作树当测量仪,主树全程只读)
详情已外置(本文件须留头量给自进化:dsh-mnemon 写侧上限 65536 字节,超限的技能再也生不成草案)。全文见 reference/clean-room-measure.md —— 把仓外 detached 工作树当净室测量仪:一次只注入一份在飞文件、与 HEAD 基线差分做逐文件归因、主树全程只读。
E. 回收非登记工作树($TW list 为空 / detached HEAD / 树里有在飞或未跟踪内容)
详情已外置(本文件须留头量给自进化:dsh-mnemon 写侧上限 65536 字节,超限的技能再也生不成草案)。全文见 reference/reclaim-unregistered.md —— 回收
@task list看不到的工作树:逐文件内容三桶归类、reparse/联接只读预扫、唯一残留先备份再--force、悬挂台账清理复验。
F. 与 DSH worktree 插件(/worktree、模型工具 worktree_create)共存
- 两条共享联接不同级(别答成「两个都必须」):
simulator/SDL2= 硬需求——simulator/CMakeLists.txt:12是普通set(SDL2_DIR "${CMAKE_CURRENT_SOURCE_DIR}/SDL2/SDL2-2.32.10")而非CACHE,既没有环境变量也没有-DSDL2_DIR=逃生门,include /lib/x64/SDL2.dll三条路径全从它派生(:34:70:71:180:207)→ 缺它build_sim.bat当场失败。.venv= 软需求——scripts/ci_local.py有DTU_PRECOMMIT_PYTHON显式逃生门 + 五级解释器候选(显式 var →sys.executable→ 仓库.venv→which python→ 机器级常见位置),绕开联接只是静默落到机器级解释器(缺 fontTools →generated-fresh假红)。plugin adopt两条都补是因为便宜,不是两条都硬。 - 「有插件了为什么还自持 Python 生命周期」别凭印象答:先实读插件包(
npm root -g→node_modules/@deepseek-ai/dsh/下定位插件、读package.json记版本),再 grep 三个概念名并报命中数——独占锁lock、共享目录联接(.venv/simulator-SDL2)、联接状态三态显示;插件侧零命中就是自持的理由。重叠面只有开/收两个动作(两侧底层都是git worktree add,没重造「建树」);锁、联接、台账与done的「预演 → 合并 → 审计 → 门禁 → 清场」编排才是插件没有的东西(本仓资源各只有一份:一块 ST-LINK、一套 Keil 授权、一个 COM6,SDL2 又无逃生门 → 必须串行 + 必须共享)。
详情已外置(本文件须留头量给自进化:dsh-mnemon 写侧上限 65536 字节,超限的技能再也生不成草案)。全文见 reference/dsh-plugin-bridge.md —— 与 DSH worktree 插件(
/worktree、worktree_create)共存:plugin adopt补共享联接(两条联接的分级:SDL2 硬 /.venv软)、锁归属pw:<name>、回收仍归 /worktree、以及「为什么不用插件而自持生命周期」的取证姿势(F-2)。
G. 任务树内跑门禁与审计:输出落点(ci-artifacts)与 SDL2 联接假红
- 新建的任务树里没有
ci-artifacts/(被.gitignore忽略 → 不会被检出):重定向输出或fs.writeFileSync直接ENOENT,整段程序零执行。落盘前先单独一条mkdir -p ci-artifacts;树内输出 一律用树内相对路径(cd进树后../_wt/x.txt会落到_wt/_wt/,实测就是这句报错)。 - 文档门禁在树内按单文件跑,全库
--all基线留到合并后在主树跑:树内的simulator/SDL2是指向 主树同一份的目录联接,--all会把这份「第二份仓库副本」一起扫:实测树内打 222 个文档 / 35 处问题、RC=1 而 35 处全在联接下、要改的文档一条没有 = 假红;合并后主树同一条命令 = 2,597 处 / 194 个文档 / rc=0, 这才是有效基线(单文件实测 161 处/98%/rc=0、16 处/88%/rc=0)。 - 确要在树内跑
--all:判红固定三步——① 主树同命令拿基线 ② 过滤simulator/SDL2联接下的问题行 ③ 剩下的逐行比。只做一步(见 RC=1 就报「门禁挂了」/ 过滤后为空就报「全绿」)都是误判。 - 跑门禁前先做一次字节体检(文档改动在树内提交前的固定项):
lines / bytes / BOM / CR / U+FFFD / 三连续空行 / 行尾空格 / 末行单个 LF+ 自写 Markdown 表格每行列数一致性检查。报出来的坏行未必是本次改动(实测 2,665 行的需求文档里两处坏表格与本次编辑无关)——先定位归属再决定动不动手,别顺手改别人的区域。这些面doc-links/no-mojibake只覆盖编码那半,表格断列与多出的空行要自己数。 - 提交/合并信息一律
-F读文件(UTF-8 无 BOM、标题 ≤100 字符、正文每行 ≤80,文件放ci-artifacts/),清退类任务另加一条禁词自检:git log -1 --pretty=%B | grep -c '<被清退主题的关键词>'必须是 0(标题与正文都不许再出现那个关键词,改用「其它串口通道对照内容」这类语义短语;合并信息同样查一遍)。提交前自查消息里的行数/统计有没有算错;未推送前发现错了 →git commit --amend -F <改好的文件>就地修,别追加一笔「更正」提交(那等于把禁词又写回历史)。
详情已外置(本文件须留头量给自进化:dsh-mnemon 写侧上限 65536 字节,超限的技能再也生不成草案)。全文见 reference/gates-in-tree.md —— 任务树内跑门禁与审计:
<tree>/ci-artifacts/先mkdir -p、文档链接按单文件在树内跑、全库--all合并后在主树跑、simulator/SDL2联接假红、提交/合并信息禁词自检、改完文档的字节与表格体检。
铁律
done只能在主工作树执行——主干分支检出在主工作树,git 不允许同一分支在两处检出。done不 push。它结束于本地合入 + 门禁全绿;推送需用户明确许可(项目既有纪律)。build与bench都必须串行:UV4 不能两个实例同时-b;串口 COM6、ST-LINK、 设备 IP192.168.1.100各只有一份。构建与烧录都不可并发。build锁由@build自持自释,调用方无需手工 acquire/release;bench锁必须手工:lock acquire bench --task <ID>→ 烧录/@test/探针 →lock release bench --task <ID> --bench-pass。非登记持有者(lead 的验收窗、插件树pw:<name>)占了锁 怎么放 → B 节(2026-10-29 起无台账也只 warn、照常释放);插件树整体口径 → F 节。
- 单写者文档:
docs/任务规划/(整个文件夹)、AGENTS.md的任务表块、MDK-ARM/*.uvprojx、.pre-commit-config.yaml、内存快照 —— 任务期不在任务工作树里改,留到done统一处理。 - 清场必须先摘联接:脚本会先
os.rmdir掉.venv/simulator/SDL2联接再git worktree remove。手工清场时千万别直接git worktree remove——git 可能递归进联接, 把主工作树的.venv一起删掉。手工拆任何一棵树之前先跑 E 第 3 步的预扫,拿到REPARSE: none才动手。 - 活跃任务硬上限 8(脚本常量
MAX_CONCURRENT = 8,每棵约 83 MB 检出——du 口径,内容字节和 84.0 MiB →docs/环境与部署/并行任务工作树方案.md§4)。满了new直接 exit 2, 腾位顺序与--force的代价 → A 节;悬挂台账的清理与复验 → E 第 6 步。 改上限 = 只改task_worktree.py里那一行常量(MAX_CONCURRENT,:30):报错文案「已有 N 个活跃任务(上限 8)」 与new打的「另有 N 个 DSH 插件工作树(.dsh-worktrees/,不计入上限 8)」提示都是.format(…, MAX_CONCURRENT)插值该常量(实测task_worktree.py:764-766/:768-771)——AGENTS.md、方案文档、本技能 frontmatter 与 A 节里的 数字全是引用同步,不是第二处事实源。全形态扫描(最多 N/N 棵/三棵/第 N+1 棵/白占 N 个名额/MAX_CONCURRENT = N/ 硬上限)与「上限真生效」的隔离小仓验证(REPO_ROOT由__file__反推 → 脚本必须按同一 目录深度放,才能测到同级_wt/)→stale-doc-count-sweepskill;每棵树的磁盘代价按实测口径重述,别照抄旧数。 @task的工作树放仓库同级_wt/,绝不在仓库内部——否则污染git status、pre-commit --all-files与全库搜索。唯一例外 = DSH worktree 插件写死的仓内.dsh-worktrees/(改不了;已用「预置 .gitignore + 三个全库扫描门禁排除」兜住,见 F 节)。自己新建的树一律走_wt/。done是合并点:属主没提交完就别done;合并提交一旦进了主干,只用「主工作树补提交」收尾, 不用reset --hard反悔 → C 节。- 非登记 / detached 的树绝不跑
done/abort:两者都以台账为前置,无台账直接 exit 2;带着残留台账时abort --force会绕过内容保全把别人的在飞改动连树一起删。回收走 E 节(全景 → 分桶 → 联接预扫 → 备份再拆 → 复验 + 清悬挂台账)。
陷阱(实测)
详情已外置(本文件须留头量给自进化:dsh-mnemon 写侧上限 65536 字节,超限的技能再也生不成草案)。全文见 reference/pitfalls.md —— 「陷阱(实测)」逐条清单原文。
验证
详情已外置(本文件须留头量给自进化:dsh-mnemon 写侧上限 65536 字节,超限的技能再也生不成草案)。全文见 reference/verification.md —— 「验证」清单原文。
与其它 skill 的衔接
- 构建 =
keil-buildskill(@build);烧录/回读 =stlink-flashskill;串口闭环 =serial-boot-testskill - 烧录产物的真实 hex 路径以
.serialtest/config.json的 hex 键为准(实测MDK-ARM/Objects/STM32F407-Demo.hex这个路径并不存在),拷错等于烧了旧镜像 →serial-boot-testskill - 新
.c文件 =new-source-fileskill(uvprojx与CMakeLists.txt双端注册) - DSH worktree 插件(人类命令
/worktree、模型工具worktree_create,树在仓内.dsh-worktrees/) 与本 skill 的分工、桥接命令与锁归属 → F 节(本 skill 不删插件树,插件也不删_wt/) .map口径 / RAM 台账与趋势 →mem-budgetskill;UI 回归 →ui-verifyskill- 完整机制与目录分配 →
docs/环境与部署/并行任务工作树方案.md