@lark-apaas/coding-steering 0.1.18-dev.0d26fd3 → 0.1.18-dev.12ae0d8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/coding-steering",
3
- "version": "0.1.18-dev.0d26fd3",
3
+ "version": "0.1.18-dev.12ae0d8",
4
4
  "description": "Stack-specific steering content for miaoda-coding templates",
5
5
  "type": "module",
6
6
  "files": [
@@ -0,0 +1,147 @@
1
+ ---
2
+ name: pptx-style-extract
3
+ description: 从 PPTX/POTX 附件抽取 deck 风格包 v2(design.md + layouts.md + assets/ + ref/)。**对话里出现 .pptx / .potx 附件就先跑本 skill**——默认它是要参考的模板,不需要用户明说「按这个风格」。只有用户点明了另一种意图(只要翻译、只要总结、只要提取文字、要改这份文件本身)才跳过。附件文本摘要不能替代抽取。
4
+ metadata:
5
+ display-names:
6
+ zh-CN: PPT 模板风格抽取
7
+ en-US: PPTX Style Extract
8
+ ---
9
+
10
+ # pptx-style-extract(PPT 模板风格抽取)
11
+
12
+ 一份 PPTX → 一个风格包:`manifest.json`(机器清单)+ `design.md`(消费入口)+ `layouts.md` + `assets/` + `ref/`。
13
+
14
+ 三步依次跑完才有这个包:**抽取**(脚本出草案)→ **判断**(你改草案里的 TODO——认图、命名、写气质)→ **打包**(脚本产出 `design.md` + `layouts.md`)。deck 的版式坐标、资产路径、logo 出现在哪些页型,全部从包里读。
15
+
16
+ 脚本路径相对本 skill 根目录;不做环境检测,依赖缺失脚本自己降级并在输出里报。
17
+
18
+ ## When To Use This Skill
19
+
20
+ 对话里出现 `.pptx` / `.potx` 附件,**默认它是要参考的模板**——先跑本 skill 抽风格,再动手做 deck。用户上传一份 PPT 却不说要干什么时,绝大多数情况就是「照着这个做」;等他明说才抽,等于把默认值设反了。
21
+
22
+ 只有用户点明了另一种意图才跳过:只要翻译、只要总结、只要提取文字、要修改这份文件本身。
23
+
24
+ `SummarizeAttachmentOrFile` 的文本摘要不能替代抽取——它丢掉主题色、字体、母版几何、版式坐标和可复用的视觉资产,正是做 deck 最需要的那些。
25
+
26
+ ## Runtime Contract
27
+
28
+ - Required dependency boundary: Python 3 standard library only.
29
+ - Pillow may be present and improves image hashing, palette extraction, contact sheets, and asset transcoding. If Pillow is missing or fails, continue with degraded extraction and record the degradation in outputs.
30
+ - Do not run `pip install`, `uv pip install`, `npm install`, or any other dependency installation in the user session.
31
+ - Run Python with bytecode disabled: `PYTHONDONTWRITEBYTECODE=1 python3 -B ...`.
32
+ - Default working directory: `tmp/pptx-style-extract/<unique-id>/`, **relative to the project root**. The sandbox file tools (`read_file` / `write` / `multi_edit`) only accept project-relative paths — an absolute `/tmp/...` workdir makes every draft edit fall back to hand-written shell scripts.
33
+ - Intermediates stay under the project's `tmp/`; they are scratch, not deliverables. Only the final deck assets copied by the deck authoring step enter the app source tree.
34
+ - `package.py` only runs v1 checks when `--check-v1 <path>` is passed or `DSM_V1_DIR` points to a sibling checker. It must not rely on developer-machine paths in the sandbox.
35
+
36
+ ## Fast Path Contract
37
+
38
+ Generated packages must make the attachment-consumption path explicit in `design.md` and exported consumer attachments, not in the user prompt:
39
+
40
+ - `design.md` and `layouts.md` are the authoritative generation entrypoints. Audit files under `ref/` and zip payload internals are not generation material.
41
+ - If an attachment summary returns `assetRoot` / `assetPaths`, treat `assetRoot` as an opaque prefix and only concatenate declared asset paths. Do not inspect, list, glob, or repair attachment directories.
42
+ - The generated Agent Fast Path must forbid shell exploration such as `ls <assetRoot>`, `ls <assetRoot>/assets/backgrounds`, `find <assetRoot>`, `glob("<assetRoot>/**")`, or any command containing `assets/design-style-packages`.
43
+ - If self-checking asset usage is needed, inspect final HTML/CSS for the declared path strings or use browser runtime resource checks. Do not fall back to shell directory exploration.
44
+ - Background, logo, layout safety, and asset-use rules belong in the generated style package (`design.md` / `layouts.md`), not in ad hoc query wording.
45
+
46
+ ## 1. 抽取
47
+
48
+ 附件的真实路径通常已经在用户消息的 `<<< 附件信息 >>>` 块里给出(`附件已保存到 <path>`)——直接用那个路径。**只有**消息里没给路径时才列目录,用列出来的名字,不要按附件标题猜文件名:
49
+
50
+ ```bash
51
+ ls -la .agent/<conversation_id>/attachments/
52
+ ```
53
+
54
+ 一条命令,写成单行并带 `2>&1`:
55
+
56
+ ```bash
57
+ mkdir -p tmp/pptx-style-extract/<unique-id> && PYTHONDONTWRITEBYTECODE=1 python3 -B scripts/extract.py "<真实路径>" tmp/pptx-style-extract/<unique-id>/stage1 2>&1
58
+ ```
59
+
60
+ 输出最后一行必是这两个哨兵之一,照它走,不要用 `ls` 去探查目录——那会白花好几轮还是查不出原因:
61
+
62
+ - `EXTRACT_OK <outdir>/l-out` — 跑完了,进第 2 步
63
+ - `EXTRACT_PARTIAL ...` — 普查产物齐全、只有草案挂了,按它给的命令单独重跑 `draft.py`,不要重跑整条抽取
64
+ - 两个都没有 — 输出被截断(退出码可能仍是 0),原样重跑一次
65
+
66
+ **目录里没有 `.pptx` / `.potx`**(只有 `skills/` 之类)说明这次上传没有落成沙箱本地文件,本 skill 无法执行:如实告诉用户模板文件在沙箱里取不到、请重新上传或反馈平台,然后停下。此时**不要**用 `summarize_attachment_or_file` 的文本摘要当风格来源,也不要用 `generate_image` 自造配图充当模板视觉——那样产出的 deck 与模板无关,却看起来像成功了。
67
+
68
+ 一条命令出全部:`extract.json`(普查数值)、`media-out/`(候选图)、`ref/`(审计层)、`l-out/`(**四件判断单草案 + BRIEF.md + contact-sheet.png + layout-sheet.png**)。
69
+
70
+ 非 OOXML / 损坏 / 加密 → 报告调用方,不产半成品。
71
+
72
+ ## 2. 判断
73
+
74
+ 1. 读 `<outdir>/l-out/BRIEF.md` —— 事实、草案依据、待判断清单一页看完。清单是实时扫出来的,**只列真正还有 TODO 的文件**,没列到的那份不用打开。
75
+ 2. 看 `<outdir>/l-out/contact-sheet.png` 与 `<outdir>/l-out/layout-sheet.png` —— 候选图和代表页型都已拼好,对应 BRIEF 的表。
76
+ 3. 用 `multi_edit` 一次批量改掉四件草案里的每一处 `TODO`:风格命名与气质、页型角色、以及下面第 4 条的禁放区。草案就在项目内相对路径下,直接编辑,**不要写脚本去改 YAML**。看过重建图后真有这套模板特有的硬规则(例如主色只许用在哪类元素)再往 `## Hard Rules` 补一条;没有就不补,别为凑数编规则。
77
+ 4. `layouts.yaml` 顶部 `bg_rules:` 按**背景资产**分组(不是按页型),逐张背景填 `text_safe` / `avoid` / `pairing_rule`:看图标清视觉主体、强光斑、深色透明区,打包时自动并入用该背景的所有页型。标题、正文、关键数字、图表、卡片、时间线及其容器的外接矩形都不得压住背景主体,透明容器也不能跨进禁放区。
78
+
79
+ `layouts.yaml` 的 `layouts:` 段是普查数值——页型、坐标、字号、色值、对齐、以及各页型自带的 `role: logo` 资产槽全部直读,**一个字都不要动**。模板自己给版式起过名时 `names:` 已经填好,读一遍确认表意即可。
80
+
81
+ 判断口径:
82
+
83
+ - **满屏图默认属背景族**——整幅替换底图的艺术图/摄影图就是背景(首页那张记 `role: cover`);「内容图不进包」只指内容区里的图表、截图、配图。
84
+ - **logo 宁缺勿错**——看图确认有品牌文字或标志图形才留;拿不准就把该条从 `manifest.yaml` 删掉,在 `gaps` 写一句,候选图留在 `media-out/`。
85
+ - **anchors 是事实不是结论**——草案里每条只报测到的数(覆盖率、计数、占比),没有「这套风格的特征是 X」这种断言。这一段在 design.md 里读起来像总纲,消费端会照它建全局样式,所以脚本不敢替你下结论:一条 1/8 覆盖率的元素被描述成「跨页不动」,消费端就会每页都摆它。看过重建图后,把真正是这套模板特征的那几条改写成设计要点,不是特征的直接删掉。
86
+ - **数值只改名不改值**——草案里的坐标/色值/字号来自普查;确需推导值(CJK 行高转译、投影尺度上抬)在 manifest 写 `derived:` 声明理由,机检认声明。
87
+ - **页型命名**——模板自带版式名时草案已填好;只有靠样张聚类的模板(`names` 里还是 TODO)才需要按 BRIEF 的 slot 原文起中文名。
88
+ - **页型角色**——`roles:` 段有 TODO 时,看 `layout-sheet.png` 上对应的代表页定 `cover|section|content|quote|closing|blank|custom`。草案只把客观事实摆在注释里(代表页页码、页数、文字块数、字号序列、图片数、有无满屏底图),不替你下结论:字号多大算章节页、文字块多少算密集页,每套模板的答案都不一样。
89
+ - **资产位置不要写成全局规则**——同一个 logo 常按页型换位换尺寸(封面一个位置一个尺寸、内容页另一个)。位置只存在于 `layouts.md` 各页型的 `slots`,正文里只说「按该页型的 slot 摆放,没有就不放」。
90
+ - **背景和版式要配对**——真实背景不是纯色底。看 `contact-sheet.png` 判断每张背景的视觉主体/禁放区,看 `layout-sheet.png` 判断文字与卡片落点;`background` 草案已按版式直读填好,你只需在 `bg_rules` 里逐张背景补 `text_safe`、`avoid`、`pairing_rule`,避免消费 Agent 把文字、图表、卡片、时间线、标题容器、正文容器或宽透明容器的外接矩形压到金字塔、人物、产品图、强光斑或深色区域上。
91
+ - 双主题只认 BRIEF 的 `themes`;单主题包不写 `theme` 字段。
92
+
93
+ 判断单里的**结构事实**(每个页型上方的注释)是判「这页该用绝对坐标还是流式」的依据:栅格几列、垂直间距序列(突变处即区带边界)、样张里每个文字槽的实际字数、命中哪个容器样式配方。文件头另有容器样式配方清单,带出现次数与跨页数——跨页多的是共性风格,只在一处出现的多半不是。
94
+
95
+ **页型给 `flow` 还是 `slots`,由你定**:内容长度会变的页(列表、表格、卡片组)用 `flow`,区带依次排、高度由内容决定,上面变高下面自动被推下去;构图固定的页(封面、章节页)用 `slots` 绝对坐标。草案两份都给了,删掉不要的那份——两份都留着打包会 FAIL,因为消费端不知道该按哪份渲染。
96
+
97
+ 普查是有损的。判断不了时可以直接翻 `<outdir>/ref/source/` —— PPTX 解压后的原文都在那里(`ppt/slides/slideN.xml`、`ppt/slideLayouts/`、`ppt/theme/`)。它只在中间产物里,不进交付包。
98
+
99
+ 要更多依据时用 `PYTHONDONTWRITEBYTECODE=1 python3 -B scripts/query.py <outdir> <子命令>`(`shapes` / `colors` / `fonts` / `text-scale` / `images` / `clusters` / `media` / `slides` / `layouts` / `recipes` / `grids` / `get <点路径>`)。读数一律走它,**不写解析脚本、不读 XML、不开浏览器**。
100
+
101
+ ## 3. 打包
102
+
103
+ ```bash
104
+ PYTHONDONTWRITEBYTECODE=1 python3 -B scripts/package.py <outdir> <outdir>/l-out <包输出目录> --force
105
+ ```
106
+
107
+ exit 0 即交付。FAIL 会指名道姓(TODO 未改 / 数值不可追溯 / 枚举误用 / 引用断链 / 体量超标),改判断单后**用同一个包目录重跑**(`--force` 就是为回修准备的),不要去改产物;体量 FAIL 走降级链(审计出包 → sidecar 化 → archetype 收缩)。
108
+
109
+ 跑之前先确认判断单里 `TODO` 已经全部改完(`grep -rn TODO <outdir>/l-out`)——`body.md` 最容易漏。改完直接跑 package.py,不用先 `ls` 确认目录。
110
+
111
+ ## 完成判据
112
+
113
+ - [ ] package.py exit 0
114
+ - [ ] design.md 的 Usage 能回答消费三问:封面底图是哪个文件?logo 每页放哪、用哪个文件?版式坐标去哪查?
115
+ - [ ] design.md / layouts.md 能回答背景安全三问:每张背景的可放文字区域在哪里?禁放区在哪里?每个页型必须配哪张背景?
116
+ - [ ] Agent Fast Path 写清 `assetRoot` / `assetPaths` 的不透明前缀协议,并禁止目录探索。
117
+ - [ ] 抽不出的都在 `gaps`,无编造
118
+
119
+ 配套 `v2-format-spec.md`(包形态与 schema)、`font-fallback.yaml`(商业字体降级表)只在你要偏离草案结构时才需要读——草案的字段结构与包一致,`package.py` 按它落盘。
120
+
121
+ ## Consume The Style Pack In A Deck
122
+
123
+ After `package.py` succeeds, the output package is for immediate model consumption.
124
+
125
+ Read `<pack_dir>/design.md` first, especially `## Usage`, `## Hard Rules`, colors, typography, components, assets, and safe-area. Then read `<pack_dir>/layouts.md`; its `canvas` and `slots[].box` are the geometry source for deck-stage sections.
126
+
127
+ When generating a deck:
128
+
129
+ 1. Call `copy_starter_component` with `kind: "deck-stage.js"`.
130
+ 2. Build `<deck-stage width="<canvas width>" height="<canvas height>">` using the `canvas` declared in `layouts.md` — source decks are not always 16:9, and a default-sized stage shifts every coordinate on the page. Each slide is one static `<section>`.
131
+ 3. Inline CSS variables from `design.md` into the HTML `<style>` block using a `--ppt-*` prefix.
132
+ 4. **位移动画用独立的 `translate` 属性**:`@keyframes fadeUp { from{opacity:0; translate:0 24px} to{opacity:1; translate:0 0} }`。`transform` 是单一属性,动画里碰它会覆盖掉元素原有的那条(`left:50%; transform:translateX(-50%)` 的居中就此丢失);`translate` / `rotate` / `scale` 各自独立,与已有 `transform` 叠加。
133
+ 5. Map `layouts.md` slots to absolute-positioned elements inside each section: `box` is `[x,y,w,h]`, and each slot also carries the template's own `size` / `weight` / `color` / `align` / `valign` — use them as-is instead of picking your own type scale. A slot with `asset` is a fixed image element (logo, mark): place that asset at that box on that archetype only. Do not reflow any of this as generic web grids.
134
+ 6. Copy `<pack_dir>/assets/` into the project, for example `assets/pptx-style/<pack-name>/`, and reference those copied files with relative URLs. The scratch `tmp/pptx-style-extract/...` path must never appear in the final HTML.
135
+ 7. Use the font stacks and fallback rules from `design.md`; do not install fonts or dependencies at runtime.
136
+ 8. Run the slide preflight checks: no resource failures, no section overflow, and sampled screenshots follow the package colors, typography, layouts, assets, and Hard Rules.
137
+
138
+ ## Export Consumer Attachments
139
+
140
+ When the style package is sent as a runtime attachment rather than mounted as a directory, export a consumer artifact that makes the fast path visible to the model:
141
+
142
+ ```bash
143
+ PYTHONDONTWRITEBYTECODE=1 python3 -B scripts/export_consumer_zip.py <pack_dir> <out.zip> --work-dir <consumer_dir>
144
+ PYTHONDONTWRITEBYTECODE=1 python3 -B scripts/export_consumer_md.py <pack_dir> <out.md>
145
+ ```
146
+
147
+ The consumer zip starts with a text prefix containing Agent Fast Path, `design.md`, and a bounded `layouts.md` excerpt. The markdown exporter inlines `design.md` / `layouts.md` for flows that should avoid archive preprocessing altogether.
@@ -0,0 +1,129 @@
1
+ # 商业字体降级映射表(随 skill 分发,E5:初始 20+ 族)
2
+ #
3
+ # 消费方:L4 字体角色分配。直读本文件文本即可,不依赖 yaml 库。
4
+ # 命中 families[].match 中任一名字(含碎片化变体)→ 降级链写进 fontFamily 栈:
5
+ # 原始名留栈首,fallback 依序追加,末位永远可加系统兜底
6
+ # `"PingFang SC", "Microsoft YaHei", sans-serif`。
7
+ # 查无对应 → 按 dsm-v1-spec.md 的气质候选清单选近似体 + 记 gaps,不编造。
8
+ # 匹配纪律:先做字体名归一化聚类(中文名/拉丁名、weight 后缀剥离、31 字符截断),
9
+ # 再拿聚类后的 family 与 match 逐条比对(大小写不敏感、忽略空格/连字符)。
10
+
11
+ version: 2
12
+
13
+ # fallback 用到的 web 字体探测状态(镜像 https://miaoda.feishu.cn/fonts/css2)。
14
+ # verified: true = 该镜像已 curl 验证返回 @font-face(2026-08-06)。
15
+ # 状态过期不影响正确性:L4 对 verified 为 false 或存疑的字体按 dsm-v1-spec 字体条款
16
+ # 重新 curl 验证后再用,加载不到降到下一档。
17
+ web-fonts:
18
+ "Noto Sans SC": {verified: true}
19
+ "Noto Serif SC": {verified: true}
20
+ "ZCOOL XiaoWei": {verified: true}
21
+ "ZCOOL QingKe HuangYou": {verified: true}
22
+ "Ma Shan Zheng": {verified: true}
23
+ "Inter": {verified: true}
24
+ "Montserrat": {verified: true}
25
+ "Barlow": {verified: true}
26
+ "Jost": {verified: true}
27
+ "Nunito Sans": {verified: true}
28
+ "Roboto Condensed": {verified: true}
29
+ "Arial": {verified: system} # 系统字体,不走镜像
30
+
31
+ families:
32
+ # ---- 方正系 ----
33
+ - family: 方正兰亭黑
34
+ match: [方正兰亭黑Pro_GB18030, FZLanTingHeiPro, FZLanTingHeiPro_GB18030, FZLTHProS-R--GB1-0, FZLTHProS, 方正兰亭黑]
35
+ category: sans
36
+ fallback: ["Noto Sans SC"]
37
+ - family: 方正兰亭圆
38
+ match: [方正兰亭圆, FZLanTingYuan, FZLTYuanS]
39
+ category: rounded
40
+ fallback: ["ZCOOL XiaoWei", "Noto Sans SC"]
41
+ - family: 方正准圆
42
+ match: [方正准圆, FZZhunYuan, FZY3JW]
43
+ category: rounded
44
+ fallback: ["ZCOOL XiaoWei", "Noto Sans SC"]
45
+ - family: 方正书宋/宋体系
46
+ match: [方正书宋, FZShuSong, 方正宋体, FZSongS]
47
+ category: serif
48
+ fallback: ["Noto Serif SC"]
49
+
50
+ # ---- 汉仪系 ----
51
+ - family: 汉仪旗黑
52
+ match: [汉仪旗黑, HYQiHei, HYQiHeiX]
53
+ category: sans
54
+ fallback: ["Noto Sans SC"]
55
+ - family: 汉仪文黑
56
+ match: [汉仪文黑, HYWenHei]
57
+ category: sans
58
+ fallback: ["Noto Sans SC"]
59
+ - family: 汉仪菱心体
60
+ match: [汉仪菱心体, HYLingXin]
61
+ category: display
62
+ fallback: ["ZCOOL QingKe HuangYou", "Noto Sans SC"]
63
+ - family: 汉仪粗黑
64
+ match: [汉仪粗黑, HYCuHei]
65
+ category: display
66
+ fallback: ["Noto Sans SC"]
67
+ weight-hint: 900
68
+
69
+ # ---- 系统/厂商中文 ----
70
+ - family: 苹方
71
+ match: [苹方, PingFang SC, PingFangSC, 苹方-简]
72
+ category: sans
73
+ fallback: ["Noto Sans SC"]
74
+ - family: 微软雅黑
75
+ match: [微软雅黑, Microsoft YaHei, MicrosoftYaHei, 微软雅黑 UI]
76
+ category: sans
77
+ fallback: ["Noto Sans SC"]
78
+ - family: 等线
79
+ match: [等线, DengXian, 等线 Light, DengXian Light]
80
+ category: sans
81
+ fallback: ["Noto Sans SC"]
82
+ - family: 华文黑体
83
+ match: [华文黑体, STHeiti, 华文细黑, STXihei]
84
+ category: sans
85
+ fallback: ["Noto Sans SC"]
86
+ - family: 华文宋体/楷体
87
+ match: [华文宋体, STSong, 华文楷体, STKaiti, 楷体, KaiTi]
88
+ category: serif
89
+ fallback: ["Noto Serif SC"] # 手写楷气质另可选 Ma Shan Zheng,按场景判断
90
+ - family: 思源黑体
91
+ match: [思源黑体, Source Han Sans, Source Han Sans SC, SourceHanSansSC, 思源黑体 CN]
92
+ category: sans
93
+ fallback: ["Noto Sans SC"] # 同源设计,无损替换
94
+ - family: 思源宋体
95
+ match: [思源宋体, Source Han Serif, Source Han Serif SC, SourceHanSerifSC]
96
+ category: serif
97
+ fallback: ["Noto Serif SC"] # 同源设计,无损替换
98
+
99
+ # ---- 互联网厂商定制体 ----
100
+ - family: 阿里巴巴普惠体
101
+ match: [阿里巴巴普惠体, Alibaba PuHuiTi, AlibabaPuHuiTi]
102
+ category: sans
103
+ fallback: ["Noto Sans SC"]
104
+ - family: 字节跳动定制体
105
+ match: [Byte Sans, ByteDance Sans, Douyin Sans]
106
+ category: sans
107
+ fallback: ["Noto Sans SC"]
108
+ - family: 小米/OPPO/荣耀定制体
109
+ match: [MiSans, OPPO Sans, HarmonyOS Sans, HONOR Sans]
110
+ category: sans
111
+ fallback: ["Noto Sans SC"]
112
+
113
+ # ---- 拉丁商业体 ----
114
+ - family: Helvetica Neue
115
+ match: [Helvetica Neue, HelveticaNeue, Helvetica Neue Medium, Helvetica]
116
+ category: sans-latin
117
+ fallback: ["Inter", "Arial"]
118
+ - family: Gotham / Proxima Nova
119
+ match: [Gotham, Proxima Nova, ProximaNova]
120
+ category: sans-latin
121
+ fallback: ["Montserrat", "Inter"]
122
+ - family: DIN
123
+ match: [DIN, DIN Pro, DIN Next, FF DIN]
124
+ category: sans-latin
125
+ fallback: ["Barlow", "Roboto Condensed"]
126
+ - family: Futura / Avenir
127
+ match: [Futura, Avenir, Avenir Next]
128
+ category: sans-latin
129
+ fallback: ["Jost", "Nunito Sans"]