@namewta/speculo 0.1.13 → 0.1.15
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": "@namewta/speculo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "Speculo — specification-driven development framework assets, with a CLI to install and update them across AI coding tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"node": "22.22.3"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@types/node": "^
|
|
51
|
+
"@types/node": "^26.0.0",
|
|
52
52
|
"typescript": "^5.8.3"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
@@ -26,11 +26,17 @@ keywords: [archive, 归档, 清理]
|
|
|
26
26
|
|
|
27
27
|
## 执行步骤
|
|
28
28
|
|
|
29
|
-
1.
|
|
29
|
+
1. **预扫描:** 列出 `speculo/.speculo/<cat>/`(内置分类至少包括 `dev` 与 `doc`)下所有符合 `YYYY-MM-DD-<kebab-name>` 格式的 change 目录。对每个目录检查 `.status.json` 是否存在:
|
|
30
|
+
- 存在且 `change_status: completed` → 加入待归档候选。
|
|
31
|
+
- 存在但 `change_status` 为其他值 → 跳过(非完成状态)。
|
|
32
|
+
- **不存在 `.status.json`** → 标记为 `broken-change: missing .status.json`,**不归档、不删除、不移动**,在清单中单独列出并跳过。
|
|
30
33
|
2. 排除已经位于 `speculo/.speculo/archive/` 下的目录;若目标归档路径已存在,标记为冲突并停止,不覆盖。
|
|
31
|
-
3.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
3. 列出完整清单(分三组):
|
|
35
|
+
- **待归档:** 源路径、目标路径、当前分类、`updated_at`、最后 phase、是否仍在 `<cat>-status.json active[]`。
|
|
36
|
+
- **broken-change:** 缺少 `.status.json` 的 change 目录路径。
|
|
37
|
+
- **冲突:** 目标路径已存在的 change。
|
|
38
|
+
4. 向用户展示清单并等待明确确认。没有确认时只输出计划,不移动目录、不改索引。对于 `broken-change`,提示用户需先通过对应 workflow 入口(`dev/00-INDEX.md` 或 `doc/00-INDEX.md`)补建 `.status.json`,或将 `change_status` 手动置为 `completed` 后再归档。
|
|
39
|
+
5. 用户确认后逐项执行(仅对待归档项):
|
|
34
40
|
- 创建 `speculo/.speculo/archive/<cat>/<YYYY-MM>/`
|
|
35
41
|
- 移动 change 目录到 `speculo/.speculo/archive/<cat>/<YYYY-MM>/<change-name>/`
|
|
36
42
|
- 从对应 `speculo/.speculo/<cat>-status.json` 的 `active[]` 删除该 change
|
|
@@ -51,6 +57,9 @@ keywords: [archive, 归档, 清理]
|
|
|
51
57
|
## 归档清单
|
|
52
58
|
[TODO: 列出本次归档的所有 change,格式 "<source-path> → <dest-path>"]
|
|
53
59
|
|
|
60
|
+
## 跳过清单
|
|
61
|
+
[TODO: 列出被跳过的 broken-change(缺少 .status.json)和冲突项]
|
|
62
|
+
|
|
54
63
|
## 用户确认记录
|
|
55
64
|
[TODO: 记录用户确认的原始内容]
|
|
56
65
|
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: officecli
|
|
3
|
+
description: Create, analyze, proofread, and modify Office documents (.docx, .xlsx, .pptx) using the officecli CLI tool. Use when the user wants to create, inspect, check formatting, find issues, add charts, or modify Office documents.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# officecli
|
|
7
|
+
|
|
8
|
+
AI-friendly CLI for .docx, .xlsx, .pptx. Single binary, no dependencies, no Office installation needed.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
If `officecli` is not installed:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# macOS / Linux
|
|
16
|
+
curl -fsSL https://d.officecli.ai/install.sh | bash
|
|
17
|
+
|
|
18
|
+
# Windows (PowerShell)
|
|
19
|
+
irm https://d.officecli.ai/install.ps1 | iex
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Verify with `officecli --version`. If still not found after install, open a new terminal.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Strategy
|
|
27
|
+
|
|
28
|
+
**L1 (read) → L2 (DOM edit) → L3 (raw XML)**. Always prefer higher layers. Add `--json` for structured output.
|
|
29
|
+
|
|
30
|
+
**Before doc work, check Specialized Skills** (bottom of this file). Fundraising decks, academic papers, financial models, dashboards, and Morph animations need their own skill loaded first — `load_skill` once, then proceed.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Help System (IMPORTANT)
|
|
35
|
+
|
|
36
|
+
**When unsure about property names, value formats, or command syntax, ALWAYS run help instead of guessing.** One help query beats guess-fail-retry loops.
|
|
37
|
+
|
|
38
|
+
`officecli help` ≡ `officecli --help`, and `officecli <cmd> --help` ≡ `officecli help <cmd>` — same content.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
officecli help # All commands + global options + schema entry points
|
|
42
|
+
officecli help docx # List all docx elements
|
|
43
|
+
officecli help docx paragraph # Full schema: properties, aliases, examples, readbacks
|
|
44
|
+
officecli help docx set paragraph # Verb-filtered: only props usable with `set`
|
|
45
|
+
officecli help docx paragraph --json # Structured schema (machine-readable)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Format aliases: `word`→`docx`, `excel`→`xlsx`, `ppt`/`powerpoint`→`pptx`. Verbs: `add`, `set`, `get`, `query`, `remove`. MCP exposes the same schema via `{"command":"help","format":"docx","type":"paragraph"}`.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Performance: Resident Mode
|
|
53
|
+
|
|
54
|
+
**Every command auto-starts a resident on first access** (60s idle timeout) — file-lock conflicts are automatically avoided. Explicit `open`/`close` is still recommended for longer sessions (12min idle):
|
|
55
|
+
```bash
|
|
56
|
+
officecli open report.docx # explicitly keep in memory
|
|
57
|
+
officecli set report.docx ... # no file I/O overhead
|
|
58
|
+
officecli close report.docx # save and release
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Opt out of auto-start: `OFFICECLI_NO_AUTO_RESIDENT=1`.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
**PPT:**
|
|
68
|
+
```bash
|
|
69
|
+
officecli create slides.pptx
|
|
70
|
+
officecli add slides.pptx / --type slide --prop title="Q4 Report" --prop background=1A1A2E
|
|
71
|
+
officecli add slides.pptx '/slide[1]' --type shape --prop text="Revenue grew 25%" --prop x=2cm --prop y=5cm --prop font=Arial --prop size=24 --prop color=FFFFFF
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Word:**
|
|
75
|
+
```bash
|
|
76
|
+
officecli create report.docx
|
|
77
|
+
officecli add report.docx /body --type paragraph --prop text="Executive Summary" --prop style=Heading1
|
|
78
|
+
officecli add report.docx /body --type paragraph --prop text="Revenue increased by 25% year-over-year."
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Excel:**
|
|
82
|
+
```bash
|
|
83
|
+
officecli create data.xlsx
|
|
84
|
+
officecli set data.xlsx /Sheet1/A1 --prop value="Name" --prop bold=true
|
|
85
|
+
officecli set data.xlsx /Sheet1/A2 --prop value="Alice"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## L1: Create, Read & Inspect
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
officecli create <file> # Create blank .docx/.xlsx/.pptx (type from extension)
|
|
94
|
+
officecli view <file> <mode> # outline | stats | issues | text | annotated | html
|
|
95
|
+
officecli get <file> <path> --depth N # Get a node and its children [--json]
|
|
96
|
+
officecli query <file> <selector> # CSS-like query
|
|
97
|
+
officecli validate <file> # Validate against OpenXML schema
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### view modes
|
|
101
|
+
|
|
102
|
+
| Mode | Description | Useful flags |
|
|
103
|
+
|------|-------------|-------------|
|
|
104
|
+
| `outline` | Document structure | |
|
|
105
|
+
| `stats` | Statistics (pages, words, shapes) | |
|
|
106
|
+
| `issues` | Formatting/content/structure problems | `--type format\|content\|structure`, `--limit N` |
|
|
107
|
+
| `text` | Plain text extraction | `--start N --end N`, `--max-lines N` |
|
|
108
|
+
| `annotated` | Text with formatting annotations | |
|
|
109
|
+
| `html` | Static HTML snapshot — same renderer as `watch`, no server needed | `--browser`, `--page N` (docx), `--start N --end N` (pptx) |
|
|
110
|
+
| `screenshot` / `svg` / `pdf` / `forms` | PNG via headless browser / SVG (pptx slide) / PDF via exporter plugin / form-fields JSON via format-handler plugin | `-o`, `--screenshot-width/-height`, pptx `--grid N` |
|
|
111
|
+
|
|
112
|
+
Use `view html` for one-shot snapshots (CI artifacts, archival, diffing); use `watch` when you need live refresh or browser-side click-to-select.
|
|
113
|
+
|
|
114
|
+
### get
|
|
115
|
+
|
|
116
|
+
Any XML path via element localName. Use `--depth N` to expand children. Add `--json` for structured output. Default text output is grep-friendly: `path (type) "text" key=val key=val ...`
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
officecli get report.docx '/body/p[3]' --depth 2 --json
|
|
120
|
+
officecli get slides.pptx '/slide[1]' --depth 1 # list all shapes on slide 1
|
|
121
|
+
officecli get data.xlsx '/Sheet1/B2' --json
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Stable ID Addressing
|
|
125
|
+
|
|
126
|
+
Elements with stable IDs return `@attr=value` paths instead of positional indices. Prefer these in multi-step workflows — positional indices shift on insert/delete, stable IDs do not.
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
/slide[1]/shape[@id=550950021] # PPT shape
|
|
130
|
+
/slide[1]/table[@id=1388430425]/tr[1]/tc[2] # PPT table
|
|
131
|
+
/body/p[@paraId=1A2B3C4D] # Word paragraph
|
|
132
|
+
/comments/comment[@commentId=1] # Word comment
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
PPT also accepts `@name=` (e.g. `shape[@name=Title 1]`), with morph `!!` prefix awareness. Elements without stable IDs (slide, run, tr/tc, row) fall back to positional indices.
|
|
136
|
+
|
|
137
|
+
### query
|
|
138
|
+
|
|
139
|
+
CSS-like selectors: `[attr=value]`, `[attr!=value]`, `[attr~=text]`, `[attr>=value]`, `[attr<=value]`, `:contains("text")`, `:empty`, `:has(formula)`, `:no-alt`. Boolean `and`/`or` supported across `query`/`set`/`remove`: `cell[value>5000 or value<100]`, `cell[(type=Number or type=Date) and value>0]`. Excel row-by-column-name: `Sheet1!row[Salary>5000]`. `set` accepts selectors and Excel-native paths (parity with `get`/`query`). Bare unscoped selectors rejected on `set`/`remove`.
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
officecli query report.docx 'paragraph[style=Normal] > run[font!=Arial]'
|
|
143
|
+
officecli query slides.pptx 'shape[fill=FF0000]'
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Watch & Interactive Selection
|
|
149
|
+
|
|
150
|
+
Live HTML preview that auto-refreshes on every file change. Browsers can click / shift-click / box-drag to select shapes; the CLI can read the current browser selection and act on it.
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
officecli watch <file> [--port N] # Start preview server (default port 26315)
|
|
154
|
+
officecli unwatch <file> # Stop
|
|
155
|
+
officecli goto <file> <path> # Scroll watching browser(s) to element (docx: p / table / tr / tc)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Open the printed `http://localhost:N` URL. Click to select; shift/cmd/ctrl+click to multi-select; drag from empty space to box-select. PPT/Word use blue outline; Excel uses native-style green selection (double-click cell to edit inline; drag a chart to reposition).
|
|
159
|
+
|
|
160
|
+
### `get <file> selected` — read what the user clicked
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
officecli get <file> selected [--json]
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Returns DocumentNodes for whatever is currently selected. Empty result if nothing selected. Exit code != 0 if no watch is running.
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
# User clicks shapes in the browser, then asks "make these red"
|
|
170
|
+
PATHS=$(officecli get deck.pptx selected --json | jq -r '.data.Results[].path')
|
|
171
|
+
for p in $PATHS; do officecli set deck.pptx "$p" --prop fill=FF0000; done
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Key properties
|
|
175
|
+
|
|
176
|
+
- **Selection survives file edits.** Paths use stable `@id=` form.
|
|
177
|
+
- **All connected browsers share one selection.** Last-write-wins.
|
|
178
|
+
- **Same-file single-watch.** A given file can have only one watch process at a time.
|
|
179
|
+
- **Group shapes select as a whole.** Drilling into individual children of a group is not supported in v1.
|
|
180
|
+
- **Coverage:** `.pptx` shapes/pictures/tables/charts/connectors/groups; `.docx` top-level paragraphs and tables. Inherited layout/master decorations and Word nested elements (table cells, run-level) are not addressable. **`.xlsx` does not emit `data-path`** — `mark`/`selection` on xlsx always resolve `stale=true` (v2 candidate).
|
|
181
|
+
|
|
182
|
+
### Marks — edit proposals waiting for review
|
|
183
|
+
|
|
184
|
+
Use `mark` when changes need human review BEFORE they hit the file. Marks live in the watch process only; a separate `set` pipeline applies accepted ones. For one-shot changes use `set` directly; for permanent file annotations use `add --type comment` (Word native).
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
officecli mark <file> <path> [--prop find=... color=... note=... tofix=... regex=true] [--json]
|
|
188
|
+
officecli unmark <file> [--path <p> | --all] [--json]
|
|
189
|
+
officecli get-marks <file> [--json]
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Props: `find` (literal or regex when `regex=true`; raw form `find='r"[abc]"'`), `color` (hex / `rgb(...)` / 22 named whitelist), `note`, `tofix` (drives apply pipeline). **Path** must be `data-path` format from watch HTML — see subskills for full pipeline.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## L2: DOM Operations
|
|
197
|
+
|
|
198
|
+
### set — modify properties
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
officecli set <file> <path> --prop key=value [--prop ...]
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Any XML attribute is settable** via element path (found via `get --depth N`) — even attributes not currently present. Without `find=`, `set` applies format to the entire element.
|
|
205
|
+
|
|
206
|
+
**Value formats:**
|
|
207
|
+
|
|
208
|
+
| Type | Format | Examples |
|
|
209
|
+
|------|--------|---------|
|
|
210
|
+
| Colors | Hex (with/without `#`), named, RGB, theme | `FF0000`, `#FF0000`, `red`, `rgb(255,0,0)`, `accent1`..`accent6` |
|
|
211
|
+
| Spacing | Unit-qualified | `12pt`, `0.5cm`, `1.5x`, `150%` |
|
|
212
|
+
| Dimensions | EMU or suffixed | `914400`, `2.54cm`, `1in`, `72pt`, `96px` |
|
|
213
|
+
|
|
214
|
+
**Dotted-attr aliases** — `font.<attr>` forms accepted on shape/run/paragraph/table/row/cell/section/styles, e.g. `--prop font.color=red --prop font.bold=true --prop font.size=14pt`. Run `officecli help <fmt> <element>` for the full list.
|
|
215
|
+
|
|
216
|
+
### find — format or replace matched text
|
|
217
|
+
|
|
218
|
+
Use top-level `--find` / `--replace` on `set` (and `--find` on `query`). Legacy `--prop find=X` still works but emits a hint.
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# Format matched text (auto-splits runs)
|
|
222
|
+
officecli set doc.docx '/body/p[1]' --find weather --prop bold=true --prop color=red
|
|
223
|
+
|
|
224
|
+
# Regex matching (regex= still a prop flag)
|
|
225
|
+
officecli set doc.docx '/body/p[1]' --find '\d+%' --prop regex=true --prop color=red
|
|
226
|
+
|
|
227
|
+
# Replace text (use `/` for whole-document scope)
|
|
228
|
+
officecli set doc.docx / --find draft --replace final
|
|
229
|
+
|
|
230
|
+
# docx: tracked Find&Replace
|
|
231
|
+
officecli set doc.docx / --find draft --replace final --prop revision.author=Alice
|
|
232
|
+
|
|
233
|
+
# PPT — same syntax, different paths
|
|
234
|
+
officecli set slides.pptx / --find draft --replace final
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Path controls search scope:** `/` = whole document, `/body/p[1]` or `/slide[N]/shape[M]` = specific element, `/header[1]` / `/footer[1]` = headers/footers.
|
|
238
|
+
|
|
239
|
+
**Notes:**
|
|
240
|
+
- Case-sensitive by default. Case-insensitive: `--prop 'find=(?i)error' --prop regex=true`
|
|
241
|
+
- Matches work across run boundaries
|
|
242
|
+
- No match = silent success. `--json` includes `"matched": N`
|
|
243
|
+
- **Excel:** only `find` + `replace` supported (no find + format props)
|
|
244
|
+
|
|
245
|
+
### add — add elements or clone
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
officecli add <file> <parent> --type <type> [--prop ...]
|
|
249
|
+
officecli add <file> <parent> --type <type> --after <path> [--prop ...] # insert after anchor
|
|
250
|
+
officecli add <file> <parent> --type <type> --before <path> [--prop ...] # insert before anchor
|
|
251
|
+
officecli add <file> <parent> --type <type> --index N [--prop ...] # 0-based position (legacy)
|
|
252
|
+
officecli add <file> <parent> --from <path> # clone existing element
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
`--after`, `--before`, `--index` are mutually exclusive. No position flag = append to end.
|
|
256
|
+
|
|
257
|
+
**Element types (with aliases):**
|
|
258
|
+
|
|
259
|
+
| Format | Types |
|
|
260
|
+
|--------|-------|
|
|
261
|
+
| **pptx** | slide (incl. hidden), shape (font.latin/ea/cs, direction=rtl, underline.color, highlight=COLOR (Add/Set/Get/HTML preview), effective.X+effective.X.src; arrow alias for rightArrow; slideMaster/slideLayout typed add/set/remove), picture (SVG, brightness/contrast/glow/shadow, rotation, link, tooltip), chart (direction=rtl, pieOfPie, barOfPie, axisLine/gridline per-attr setters, animation+chartBuild=byCategory|bySeries, line dropLines/hiLowLines/upDownBars, anchor=x,y,w,h shorthand), table (cell direction=rtl, fill/background, built-in PowerPoint style catalogue, /col[C] get + swap/copyFrom, row/col Move/CopyFrom), row (tr), connector (from/to accept @name=, startshape/endshape SetByPath), group (link, tooltip, deep walk by get/query/add/remove), video/audio (loop, autoStart alias), equation, notes (direction=rtl, lang), comment (legacy + modern p188 threaded round-trip), animation (15 emphasis + 16 exit presets, multi-effect chains, motion-path presets, repeat/restart/autoReverse, chart animations), transition (12 p15 presets + morph/p14), paragraph (para), run, zoom, ole (preview=, full dump round-trip via add-part+raw-set), placeholder (phType=...), model3d (rotation=ax,ay,az; full dump round-trip), smartart (dump round-trip via add-part). |
|
|
262
|
+
| **docx** | paragraph (direction/font.latin/ea/cs, bold.cs/italic.cs/size.cs, lang.latin/ea/cs, wordWrap, framePr.\*, tabs shorthand), run (lang slots, direction, underline.color, position half-pts, **revision.type=ins\|del\|format\|moveFrom\|moveTo + revision.action=accept\|reject** with .author/.date — `/revision[@author=X]` selector for filtered accept/reject), table (direction=rtl, hMerge, **virtual column ops**: add/remove/move/copyfrom on /body/tbl[N]/col), row (tr), cell (td), image, header/footer (direction), section (pageNumFmt full enum, direction=rtl, rtlGutter, pgBorders=box), bookmark, comment, footnote, endnote, formfield, sdt, chart, equation, field (28 types), hyperlink, style (direction, indents, pbdr, lineSpacing on Add/Set), toc, watermark, break, ole, **num/abstractNum/lvl**, **tab**, **textbox/shape** (full Add+Get; geometry, fill, line, wrap, alt, anchor, **rotation, verticalText (eaVert/vert/vert270/wordArt\*), gradient, shadow, opacity**), embedded **OLE round-trip on dump→batch**. docDefaults.rtl, autoHyphenation, `get /` exposes locale + /comments /footnotes /endnotes. `create --minimal` for raw OOXML scaffolding. |
|
|
263
|
+
| **xlsx** | sheet (visible/hidden/veryHidden, print margins, printTitleRows/Cols, rightToLeft sheetView, cascade-aware rename), row (c{N}= cell-content shorthand; add accepts --from /Sheet/col[L]; formula-ref rewrite on insert), col (formula-ref rewrite, named-range follow on move), cell (type=richtext+runs, merge=range/sweep, direction=rtl, phonetic; **--shift left\|up on remove, shift=right\|down on add** — Excel UI dialog parity; formula auto-detect; OFFSET/INDIRECT in calc), chart (per-axis RTL/title, anchor=x,y,w,h, pareto), image (SVG), comment (direction=rtl), table (listobject), namedrange (definedname, volatile, `[@name=X]`; formula-body inlined at parse), pivottable (cache CoW + cross-pivot sharing, labelFilter, topN, fillDownLabels, calculatedField), sparkline, validation, autofilter, shape, textbox, CF (databar/colorscale/iconset/formulacf/cellIs/topN/aboveAverage), ole, csv. Query supports `merge`/`mergedrange`. Workbook: password. Shape selector enumerates leaves inside grpSp. |
|
|
264
|
+
|
|
265
|
+
### Pivot tables (xlsx)
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
officecli add data.xlsx /Sheet1 --type pivottable \
|
|
269
|
+
--prop source="Sheet1!A1:E100" --prop rows=Region,Category \
|
|
270
|
+
--prop cols=Year --prop values="Sales:sum,Qty:count" \
|
|
271
|
+
--prop grandTotals=rows --prop subtotals=off --prop sort=asc
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Key props: `rows`, `cols`, `values` (Field:func[:showDataAs]), `filters`, `source`, `position`, `layout` (compact/outline/tabular), `repeatLabels`, `blankRows`, `aggregate`, `showDataAs` (percent_of_total/row/col, running_total), `grandTotals`, `subtotals`, `sort`. Aggregators: sum, count, average, max, min, product, stdDev, stdDevp, var, varp, countNums. Date columns auto-group. Run `officecli help xlsx pivottable` for full schema.
|
|
275
|
+
|
|
276
|
+
### Document-level properties (all formats)
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
officecli set doc.docx / --prop docDefaults.font=Arial --prop docDefaults.fontSize=11pt
|
|
280
|
+
officecli set doc.docx / --prop protection=forms --prop evenAndOddHeaders=true
|
|
281
|
+
officecli set data.xlsx / --prop calc.mode=manual --prop calc.refMode=r1c1
|
|
282
|
+
officecli set slides.pptx / --prop defaultFont=Arial --prop show.loop=true --prop print.what=handouts
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Run `officecli help <format> /` for all document-level properties (docDefaults, docGrid, CJK spacing, calc, print, show, theme, extended).
|
|
286
|
+
|
|
287
|
+
### Sort (xlsx)
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
officecli set data.xlsx /Sheet1 --prop sort="C desc" --prop sortHeader=true
|
|
291
|
+
officecli set data.xlsx '/Sheet1/A1:D100' --prop sort="A asc" --prop sortHeader=true
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Format: `COL DIR[, COL DIR ...]`. Rejects ranges with merged cells or formulas. Sidecar metadata (hyperlinks, comments, conditional formatting, drawings) follows rows automatically.
|
|
295
|
+
|
|
296
|
+
### Text-anchored insert (`--after find:X` / `--before find:X`)
|
|
297
|
+
|
|
298
|
+
Locate an insertion point by text match within a paragraph. Inline types (run, picture, hyperlink) insert within the paragraph; block types (table, paragraph) auto-split it. PPT only supports inline.
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
# Word: inline run after matched text
|
|
302
|
+
officecli add doc.docx '/body/p[1]' --type run --after find:weather --prop text=" (sunny)"
|
|
303
|
+
|
|
304
|
+
# Word: block table after matched text (auto-splits paragraph)
|
|
305
|
+
officecli add doc.docx '/body/p[1]' --type table --after "find:First sentence." --prop rows=2 --prop cols=2
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Clone
|
|
309
|
+
|
|
310
|
+
`officecli add <file> / --from '/slide[1]'` — copies with all cross-part relationships.
|
|
311
|
+
|
|
312
|
+
### move, swap, remove
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
officecli move <file> <path> [--to <parent>] [--index N] [--after <path>] [--before <path>]
|
|
316
|
+
officecli swap <file> <path1> <path2>
|
|
317
|
+
officecli remove <file> '/body/p[4]'
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
When using `--after` or `--before`, `--to` can be omitted — the target container is inferred from the anchor.
|
|
321
|
+
|
|
322
|
+
### batch — multiple operations in one save cycle
|
|
323
|
+
|
|
324
|
+
Continues on error by default (returns exit 1 if any item fails). Use `--stop-on-error` to abort on the first failure. `--force` is the docx-protection bypass.
|
|
325
|
+
|
|
326
|
+
`officecli dump <file> [<path>]` emits a replayable batch JSON for round-trip — `.docx` (full coverage) and `.pptx` (text/tables/pictures/charts/notes/theme + OLE/3D/video/audio/SmartArt/morph/p15 transitions via raw-set passthrough). Path defaults to `/` (whole document); pass a subtree path (`/body`, `/body/p[N]`, `/body/tbl[N]`, `/theme`, `/settings`, `/numbering`, `/styles`) to scope the dump. `officecli refresh <file.docx>` recalculates TOC page numbers / PAGE / cross-references after replay (Word backend on Windows; headless-HTML fallback elsewhere). `officecli plugins list` extends support to `.doc`, `.hwpx`, `.pdf` export.
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
echo '[
|
|
330
|
+
{"command":"set","path":"/Sheet1/A1","props":{"value":"Name","bold":"true"}},
|
|
331
|
+
{"command":"set","path":"/Sheet1/B1","props":{"value":"Score","bold":"true"}}
|
|
332
|
+
]' | officecli batch data.xlsx --json
|
|
333
|
+
|
|
334
|
+
officecli batch data.xlsx --commands '[{"op":"set","path":"/Sheet1/A1","props":{"value":"Done"}}]' --json
|
|
335
|
+
officecli batch data.xlsx --input updates.json --force --json
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Supports: `add`, `set`, `get`, `query`, `remove`, `move`, `swap`, `view`, `raw`, `raw-set`, `validate`. Fields: `command` (or `op`), `path`, `parent`, `type`, `from`, `to`, `index`, `after`, `before`, `props`, `selector`, `mode`, `depth`, `part`, `xpath`, `action`, `xml`.
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## L3: Raw XML
|
|
343
|
+
|
|
344
|
+
Use when L2 cannot express what you need. No xmlns declarations needed — prefixes auto-registered.
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
officecli raw <file> <part> # view raw XML
|
|
348
|
+
officecli raw-set <file> <part> --xpath "..." --action replace --xml '<w:p>...</w:p>'
|
|
349
|
+
officecli add-part <file> <parent> # create new document part (returns rId)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
`raw-set` actions: `append`, `prepend`, `insertbefore`, `insertafter`, `replace`, `remove`, `setattr`. Run `officecli help <format> raw` for available parts.
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Common Pitfalls
|
|
357
|
+
|
|
358
|
+
| Pitfall | Correct Approach |
|
|
359
|
+
|---------|-----------------|
|
|
360
|
+
| `--name "foo"` | Use `--prop name="foo"` — all attributes go through `--prop` |
|
|
361
|
+
| Unquoted `[N]` paths in zsh/bash | Always quote: `'/slide[1]'` or `"/slide[1]"` (shell glob-expands brackets) |
|
|
362
|
+
| PPT `shape[1]` for content | `shape[1]` is typically the title placeholder. Use `shape[2]+` for content shapes |
|
|
363
|
+
| `/shape[myname]` | Name indexing not supported. Use numeric index or `@name=` (PPT only) |
|
|
364
|
+
| Guessing property names | Run `officecli help <format> <element>` to see exact names |
|
|
365
|
+
| Modifying an open file | Close the file in PowerPoint/WPS first |
|
|
366
|
+
| `\n` in shell strings | Use `\\n` for newlines in `--prop text="..."` |
|
|
367
|
+
| `$` in shell text | `--prop text="$15M"` strips `$15`. Use single quotes: `--prop text='$15M'`, or heredoc batch |
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Specialized Skills
|
|
372
|
+
|
|
373
|
+
`officecli load_skill <name>` — output is a SKILL.md, follow its rules.
|
|
374
|
+
|
|
375
|
+
**Loading rule**:
|
|
376
|
+
- Pick the most specific match in "When to use"; if none fits, load the format default (`word` / `pptx` / `excel`).
|
|
377
|
+
- Scenes already contain the format default's rules — load **one** skill per artifact, never stack.
|
|
378
|
+
- Loaded rules persist across turns; don't re-load each reply.
|
|
379
|
+
- Two distinct artifacts → two separate loads.
|
|
380
|
+
|
|
381
|
+
### Word (.docx)
|
|
382
|
+
|
|
383
|
+
| Name | When to use |
|
|
384
|
+
|------|-------------|
|
|
385
|
+
| `word` | Reports, letters, memos, proposals, generic documents |
|
|
386
|
+
| `academic-paper` | Journal / conference / thesis: APA / Chicago / IEEE / MLA citations, equations, SEQ + PAGEREF cross-refs, multi-column journal layout, bibliography. NOT for business reports or letters (route those to `word`) |
|
|
387
|
+
|
|
388
|
+
### PowerPoint (.pptx)
|
|
389
|
+
|
|
390
|
+
| Name | When to use |
|
|
391
|
+
|------|-------------|
|
|
392
|
+
| `pptx` | Generic decks: board reviews, sales decks, all-hands, product launches |
|
|
393
|
+
| `pitch-deck` | **Fundraising only** — seed / Series A-C / SAFE / convertible / strategic raise. NOT for sales / product / board decks (route those to `pptx`) |
|
|
394
|
+
| `morph-ppt` | Cinematic Morph-animated presentations. NOT for static decks (route those to `pptx`) |
|
|
395
|
+
| `morph-ppt-3d` | 3D Morph: GLB models, camera moves, depth. NOT for 2D-only Morph (route those to `morph-ppt`) |
|
|
396
|
+
|
|
397
|
+
### Excel (.xlsx)
|
|
398
|
+
|
|
399
|
+
| Name | When to use |
|
|
400
|
+
|------|-------------|
|
|
401
|
+
| `excel` | Generic workbooks, formulas, pivots, trackers |
|
|
402
|
+
| `financial-model` | Financial models, scenarios, projections. NOT for general data analysis (route those to `excel`) |
|
|
403
|
+
| `data-dashboard` | CSV/tabular data → KPI / analytics / executive dashboards with charts and sparklines. NOT for raw data tracking (route those to `excel`) |
|
|
404
|
+
|
|
405
|
+
Example: a fundraising deck task → `officecli load_skill pitch-deck` → use the printed rules.
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Notes
|
|
410
|
+
|
|
411
|
+
- Paths are **1-based** (XPath convention): `'/body/p[3]'` = third paragraph
|
|
412
|
+
- `--index` is **0-based** (array convention): `--index 0` = first position
|
|
413
|
+
- **Excel exception**: for `add --type row` and `add --type col`, `--index N` is **1-based** (matches OOXML RowIndex / column letter index). `--index 5` inserts at row 5 / column 5.
|
|
414
|
+
- After modifications, verify with `validate` and/or `view issues`
|
|
415
|
+
- **When unsure**, run `officecli help <format> <element>` instead of guessing
|
|
@@ -32,7 +32,11 @@ keywords: [dev, 开发, workflow, index, 状态]
|
|
|
32
32
|
1. 若用户未指定 change,扫描 `speculo/.speculo/dev-status.json` 和 `speculo/.speculo/dev/*/.status.json`,列出 active changes。
|
|
33
33
|
- **命名校验**:扫描时仅处理符合 `YYYY-MM-DD-<kebab-name>` 格式的目录。不符合的目录标记为 `malformed`,单独列出路径并提示用户修复或手动清理,不自动删除或重命名。
|
|
34
34
|
2. 若只有一个 active change,默认继续该 change;若有多个 active change,要求用户选择。
|
|
35
|
-
3. 若没有 active change,按用户意图创建新的 change
|
|
35
|
+
3. 若没有 active change,按用户意图创建新的 change。**以下三步为原子操作,不可跳过,前一步失败时停止后续并报告:**
|
|
36
|
+
- **3a. 创建 change 目录** —— `speculo/.speculo/dev/<YYYY-MM-DD>-<kebab-name>/`(使用当前日期,`<kebab-name>` 从用户意图提取,不超过 5 个词)。
|
|
37
|
+
- **3b. 写入 `.status.json`** —— 在 change 目录下创建 `.status.json`,按 `docs/persistence-contract.md` §2.2 最小初始化模板填入所有必填字段(`name`、`category: "dev"`、`change_status: "active"`、`created_at`、`updated_at`、`current_phase: "00-init"`、`phase_history`)。
|
|
38
|
+
- **3c. 更新 `dev-status.json`** —— 读取 `speculo/.speculo/dev-status.json`,在 `active[]` 中追加该 change 的索引条目(`name`、`current_phase: "00-init"`、`updated_at`),写回文件。
|
|
39
|
+
- 以上三步全部成功后,方可继续推荐入口。
|
|
36
40
|
4. 推荐入口时优先使用用户显式别名;没有别名时按执行模式推荐。
|
|
37
41
|
5. 执行任何 workflow 前,读取该 workflow 入口文件、阶段文件、模板和被调用 skill wrapper。
|
|
38
42
|
6. **Worktree 隔离(可选,默认 off)**:仅当用户**显式请求**隔离时,新 change 在 `dev/01` 的 Phase 0 经 `../../skills/worktree-isolation/SKILL.md` 建立隔离分支 `speculo/dev/<change>` 与 `.worktree/<change>/` 工作树,并把 `base_branch`、`change_branch` 记入 `.status.json`。扫描 active changes 时,对 `worktree_enabled` 为真者可结合 `git worktree list` 核对工作树是否存在。
|
|
@@ -29,7 +29,11 @@ keywords: [doc, writing, article, fragments, edit, 文档, 写作]
|
|
|
29
29
|
1. 若用户未指定 change,扫描 `speculo/.speculo/doc-status.json` 和 `speculo/.speculo/doc/*/.status.json`,列出 active changes。
|
|
30
30
|
- **命名校验**:扫描时仅处理符合 `YYYY-MM-DD-<kebab-name>` 格式的目录。不符合的目录标记为 `malformed`,单独列出路径并提示用户修复或手动清理,不自动删除或重命名。
|
|
31
31
|
2. 若只有一个 active change,默认继续该 change;若有多个 active change,要求用户选择。
|
|
32
|
-
3. 若没有 active change,按用户意图创建新的 doc change
|
|
32
|
+
3. 若没有 active change,按用户意图创建新的 doc change。**以下三步为原子操作,不可跳过,前一步失败时停止后续并报告:**
|
|
33
|
+
- **3a. 创建 change 目录** —— `speculo/.speculo/doc/<YYYY-MM-DD>-<kebab-name>/`(使用当前日期,`<kebab-name>` 从用户意图提取,不超过 5 个词)。
|
|
34
|
+
- **3b. 写入 `.status.json`** —— 在 change 目录下创建 `.status.json`,按 `docs/persistence-contract.md` §2.2 最小初始化模板填入所有必填字段(`name`、`category: "doc"`、`change_status: "active"`、`created_at`、`updated_at`、`current_phase: "00-init"`、`phase_history`)。
|
|
35
|
+
- **3c. 更新 `doc-status.json`** —— 读取 `speculo/.speculo/doc-status.json`,在 `active[]` 中追加该 change 的索引条目(`name`、`current_phase: "00-init"`、`updated_at`),写回文件。
|
|
36
|
+
- 以上三步全部成功后,方可继续推荐入口。
|
|
33
37
|
4. 推荐入口时优先使用用户显式别名;没有别名时按用户意图推荐一个横向 workflow。
|
|
34
38
|
5. 执行任何 workflow 前,读取该 workflow 入口文件、阶段文件和模板。
|
|
35
39
|
|