技能库同步:另一台机的 2026-10-16 包 + element-picker 入包 + 工具归拢到技能级 assets/

product-planning(同步 26 改 65 新)
- 目录约定:docs/pm/<项目>/ ⇒ <工作区>/项目/<产品slug>/ 为产品根,下分 产品规划/ 与 产品原型/{designs,pages}
- ④段骨架六节 ⇒ 七节(新增「原型地址」;后两节改「页面导航」「原型状态取值」)
- ③段新增真机组件库;结案「源站只有暗色主题」,tokens.css(亮色)标为不可用于生产
- ③段改版规则反转为「一个产品只用一套原型、只留当前态」;②段新增 产品规划模板.md(表头唯一定义处)
- scripts:产品根定位重写(含 .registry/current-project 指针),新增 check_terms.py 与 selftest_product_root.py

session-mechanism(同步 3 改 2 新)
- references/06-技能优化规程.md 新增 §5「要求落在生成时看得见的面上」,总表 16 ⇒ 17 条;SKILL.md 同步
- scripts/collabctl.py 取回 _find_board() 候选定位(旧版写死 scripts/board.py,而看板已搬进 boards/会话看板/ ⇒ 旧版本就是坏的)

element-picker(新装)
- 按用户口径作「独立功能加入 product-planning」,非独立全局技能
- 修掉它自身三处路径漂移(技能根写法 ⇒ 同目录;README 两处旧落点;剪贴板示例文案与代码对齐)

工具归拢到技能级 assets/
- diagram-design / design-capture / element-picker / video-capture 从各段 assets/ 移到技能包 assets/
- 新增红线:本包有两处 assets/(技能级工具箱 vs 段内资产),引工具一律写「技能级 assets/<工具名>/」
- 路径口径由两类改三类(技能级工具箱 / 本段自带资产 / 同根技能)

不入库(磁盘保留)
- design-system-tiaoyue 整个目录(用户 2026-10-16 令):git rm -r --cached + .gitignore,理由=14 MB 且可 CDP 重采;
  已在 ③段 SKILL.md 注明「取仓后这一层是空的属正常,用自带套需另取或重采」
- element-picker 的运行期存档 marks/(服务自己会建目录)
This commit is contained in:
admin committed 2026-10-16 23:13:33 +08:00
1 parent 749c0e3d5d
commit 8160f91559
336 files changed
+12821 -6621

No files matched your search

+22 -22
View File
@@ -13,7 +13,7 @@
这三处**没有任何门禁会报错** —— 只能靠回读,而回读会漏。
用法:
python scripts/check_naming.py --ws <工作区> # 查技能包自身 + 该工作区的产出白名单
python scripts/check_naming.py --ws <工作区或产品根> # 查技能包自身 + 该工作区的产出白名单
python scripts/check_naming.py --root <某个技能根> # 只查一份
退出码:0 = 全过;1 = 有 FAIL。
"""
@@ -79,7 +79,7 @@ DEPRECATED = [
]
# ⛔ 2026-10-06 用户定案:①段**产出白名单**——本段只许这五份,第 6 份须用户明确要求。
# 判据:扫 `docs/pm/<项目>/research/` 的实际文件名,出现白名单外的 `.md` 即 FAIL。
# 判据:扫 `产品规划/research/` 的实际文件名,出现白名单外的 `.md` 即 FAIL。
# ⛔ 用 os.walk 时**必须逐层拆开**:`research/` 与 `prd/` 是两个不同的白名单。
WHITELIST = {
"stage-discovery": {
@@ -104,9 +104,9 @@ REMOVED_ASSETS = ["ui-page-design"]
# 总入口的「只读」清单,三处还指着已废的 `strategy/` 与 `ux/`,而当时没有任何门禁会报。
# 豁免:行内出现下面任一废止标记时视为正当留痕(说明"原来叫什么、现在改成什么")。
DEAD_PATHS = {
r"strategy/30-|strategy/31-|docs/pm/[^`\s]*/strategy/":
r"strategy/30-|strategy/31-|产品规划/strategy/":
"已废的 ①段 strategy/ 目录(现全部落 research/1a~1e)",
r"ux/state-machine|ux/diagrams|docs/pm/[^`\s]*/ux/":
r"ux/state-machine|ux/diagrams|产品规划/ux/":
"已废的 ②段 ux/ 目录(状态流转已移进 prd/2a 的功能条目)",
}
DEAD_PATH_EXEMPT = ("旧", "已废", "已改名", "曾", "历史上", "移进", "移到", "改为",
@@ -318,7 +318,8 @@ def check_root(root, label):
# ⇒ 旧名提示恒不触发,`strategy/30-产品策略.md` 这类真残留被静默放过(假绿)。
# 现合并成一个循环,一律用本轮读到的 `tt`。
for dp, dn, fn in os.walk(root):
dn[:] = [d for d in dn if d != "__pycache__"]
dn[:] = [d for d in dn
if d not in ("__pycache__", "_留痕", "归档", "assets")]
for f in fn:
if not f.endswith(".md"):
continue
@@ -358,7 +359,7 @@ def check_root(root, label):
def check_whitelist(ws, label):
"""①②段产出白名单:`docs/pm/<项目>/<dir>/` 里出现白名单外的 .md ⇒ FAIL。
"""①②段产出白名单:`<产品根>/产品规划/<dir>/` 里出现白名单外的 .md ⇒ FAIL。
⛔ 这是**产出层**门禁,与命名门禁不同源:命名管"文档里写的名字有没有漂",
本函数管"磁盘上到底多出了什么文件"。2026-10-06 事故:某轮自作主张多产了一份
@@ -368,11 +369,10 @@ def check_whitelist(ws, label):
"""
import glob
for slug, rule in WHITELIST.items():
pat = os.path.join(ws, "docs", "pm", "*", rule["dir"])
pat = os.path.join(ws, "产品规划", rule["dir"])
for d in glob.glob(pat):
if not os.path.isdir(d):
continue
proj = os.path.basename(os.path.dirname(d))
extra = sorted(f for f in os.listdir(d)
if f.endswith(".md") and f not in rule["allow"])
rel = os.path.relpath(d, ws).replace("\\", "/")
@@ -388,31 +388,31 @@ def main():
ap.add_argument("--root", action="append", default=None,
help="技能根目录,可重复;默认只查本技能包自身")
ap.add_argument("--ws", default=None,
help="工作区根(含 docs/pm 的那一层);默认从 cwd 向上找")
help="工作区根或产品根(含 `产品规划` 与 `产品原型` 的那一层);默认从 cwd 向上找")
args = ap.parse_args()
# 本文件位于 <技能包>/scripts/ ⇒ 上溯 2 层 = 技能包(SKILL.md 就在这层)
skill_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 🔴 产品根定位**沿用③段 `_common.py` 的唯一一份实现**(⛔ 不在这里再抄一套逻辑:
# 两处实现迟早一处改一处漏,同族事故在 2026-10-06 的判据漂移里已经吃过一次)。
_sk_scripts = os.path.join(skill_root, "references", "stage-delivery", "scripts")
if _sk_scripts not in sys.path:
sys.path.insert(0, _sk_scripts)
import _common as C
# 🔴🔴 2026-10-07 技能迁全局后的**必须修正**:
# 旧写法 `ws = os.path.dirname(skill_root)` 是按「技能包在工作区根」写的。
# 技能从工作区搬到技能根(`<技能根>/product-planning/`)之后,
# `ws` 会算成技能根 ⇒ **`docs/pm/*` 一个都扫不到**
# `ws` 会算成技能根 ⇒ **`产品规划/*` 一个都扫不到**
# ⇒ `check_whitelist()` 静默扫零个目录、**恒绿通过**(假绿比报红更危险)。
# ⇒ 工作区一律**显式给**:`--ws <工作区>`;没给就向上找「含 docs/pm 的那一层」,
# ⇒ 工作区一律**显式给**:`--ws <工作区或产品根>`;没给就向上找「含 `产品规划` 与 `产品原型` 的产品根」,
# 再找不到就**明确报 FAIL**,⛔ 绝不静默跳过。
roots = args.root or [skill_root]
ws = args.ws
# `--ws` 收**工作区根或产品根都行**;没给就从 cwd 起认(含向上找)。
ws = C.find_product_root(args.ws) if args.ws else C.find_product_root(os.getcwd())
if not ws:
_p = pathlib.Path.cwd()
for _ in range(6):
if (_p / "docs" / "pm").is_dir():
ws = str(_p)
break
_p = _p.parent
if not ws or not os.path.isdir(os.path.join(ws, "docs", "pm")):
add("FAIL", "找得到工作区(`docs/pm` 那一层)",
"⛔ 未找到 ⇒ 产出白名单**没被真正检查**。请显式传 `--ws <工作区>`。")
ws = ws or os.getcwd()
add("FAIL", "找得到产品根(含 `产品规划` 与 `产品原型` 的那一层)",
"⛔ 未找到 ⇒ 产出白名单**没被真正检查**。请显式传 `--ws <工作区或产品根>`。")
ws = args.ws or os.getcwd()
for r in roots:
check_root(r, os.path.basename(os.path.dirname(r.rstrip("/")) if r.endswith("skills") else r))