mosage 0.1.0 → 0.8.0
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/LICENSE +1 -0
- package/README.md +16 -217
- package/bin.js +2 -0
- package/dist/build-C7NW_3Pk.js +14 -0
- package/dist/check-CP4873Wx.js +41 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +228 -0
- package/dist/config-DPm1BBAb.js +2619 -0
- package/dist/config-TlTe7Ona.d.ts +24 -0
- package/dist/context-BqsdSrAQ.js +1084 -0
- package/dist/dev-Biz42qlu.js +17 -0
- package/dist/diagram-xlVDekYk.js +763 -0
- package/dist/export-Bi6nuxjT.js +31 -0
- package/dist/import-D2jNB07F.js +25 -0
- package/dist/index.d.ts +455 -0
- package/dist/index.js +693 -0
- package/dist/init-Bbtj2pxF.js +262 -0
- package/dist/preview-CLm51aRt.js +19 -0
- package/dist/sdk-DjpX6mCv.js +51 -0
- package/dist/vite/index.d.ts +25 -0
- package/dist/vite/index.js +2 -0
- package/env.d.ts +83 -0
- package/package.json +84 -64
- package/skills/apply-comments/SKILL.md +43 -56
- package/skills/create-doc/SKILL.md +106 -0
- package/skills/create-theme/SKILL.md +184 -0
- package/skills/current-doc/SKILL.md +120 -0
- package/skills/doc-authoring/SKILL.md +434 -0
- package/skills/doc-authoring/references/assets.md +47 -0
- package/skills/doc-authoring/references/design-system.md +81 -0
- package/skills/doc-authoring/references/long-form.md +131 -0
- package/skills/doc-authoring/references/pagination.md +118 -0
- package/skills/doc-authoring/references/tables-and-charts.md +161 -0
- package/src/app/app.tsx +42 -0
- package/src/app/components/data-table.tsx +196 -0
- package/src/app/components/design-panel/design-panel.tsx +318 -0
- package/src/app/components/design-panel/design-provider.tsx +121 -0
- package/src/app/components/design-panel/use-design.ts +85 -0
- package/src/app/components/diagram.tsx +76 -0
- package/src/app/components/doc-assets.tsx +129 -0
- package/src/app/components/doc-search.tsx +248 -0
- package/src/app/components/doc-sidebar.tsx +162 -0
- package/src/app/components/flow-page.tsx +93 -0
- package/src/app/components/footnote.tsx +204 -0
- package/src/app/components/image-placeholder.tsx +50 -0
- package/src/app/components/inspector/inspector.tsx +518 -0
- package/src/app/components/numbering.tsx +224 -0
- package/src/app/components/page-frame.tsx +70 -0
- package/src/app/components/sidebar/folder-item.tsx +212 -0
- package/src/app/components/sidebar/icon-picker.tsx +99 -0
- package/src/app/components/sidebar/sidebar.tsx +252 -0
- package/src/app/components/table-of-contents.tsx +93 -0
- package/src/app/components/theme-toggle.tsx +50 -0
- package/src/app/components/themes/markdown.tsx +249 -0
- package/src/app/components/themes/theme-preview.tsx +74 -0
- package/src/app/components/ui/menu.tsx +143 -0
- package/src/app/index.html +12 -0
- package/src/app/lib/agent-bridge.ts +140 -0
- package/src/app/lib/assets.ts +151 -0
- package/src/app/lib/design-presets.ts +109 -0
- package/src/app/lib/design.ts +88 -0
- package/src/app/lib/diagnostics.ts +282 -0
- package/src/app/lib/doc-preview.tsx +29 -0
- package/src/app/lib/docs.ts +26 -0
- package/src/app/lib/docx/extract.ts +1623 -0
- package/src/app/lib/docx/fonts.test.ts +136 -0
- package/src/app/lib/docx/fonts.ts +166 -0
- package/src/app/lib/docx/media.ts +102 -0
- package/src/app/lib/docx/model.ts +206 -0
- package/src/app/lib/docx/paragraph.test.ts +92 -0
- package/src/app/lib/docx/paragraph.ts +107 -0
- package/src/app/lib/docx/props.ts +187 -0
- package/src/app/lib/docx/styles.ts +306 -0
- package/src/app/lib/docx/units.ts +35 -0
- package/src/app/lib/docx/write.test.ts +507 -0
- package/src/app/lib/docx/write.ts +581 -0
- package/src/app/lib/docx/xml.ts +39 -0
- package/src/app/lib/export-docx.ts +289 -0
- package/src/app/lib/export-dom.ts +318 -0
- package/src/app/lib/export-html.ts +156 -0
- package/src/app/lib/export-image.ts +70 -0
- package/src/app/lib/export-pdf.ts +165 -0
- package/src/app/lib/flow-measure.test.ts +31 -0
- package/src/app/lib/flow-measure.ts +183 -0
- package/src/app/lib/flow.test.ts +110 -0
- package/src/app/lib/flow.ts +136 -0
- package/src/app/lib/folders.ts +192 -0
- package/src/app/lib/footnotes.test.tsx +102 -0
- package/src/app/lib/footnotes.ts +94 -0
- package/src/app/lib/inspector/fiber.ts +99 -0
- package/src/app/lib/labels.test.ts +18 -0
- package/src/app/lib/labels.ts +181 -0
- package/src/app/lib/outline.ts +118 -0
- package/src/app/lib/page-context.tsx +43 -0
- package/src/app/lib/page-range.test.ts +95 -0
- package/src/app/lib/page-range.ts +90 -0
- package/src/app/lib/print-ready.ts +69 -0
- package/src/app/lib/rasterize.ts +173 -0
- package/src/app/lib/scan.ts +26 -0
- package/src/app/lib/sdk.test.ts +32 -0
- package/src/app/lib/sdk.ts +115 -0
- package/src/app/lib/themes.ts +31 -0
- package/src/app/lib/use-doc-module.ts +53 -0
- package/src/app/lib/use-doc-pages.ts +147 -0
- package/src/app/lib/utils.ts +6 -0
- package/src/app/lib/view-mode.test.ts +91 -0
- package/src/app/lib/view-mode.ts +104 -0
- package/src/app/main.tsx +14 -0
- package/src/app/routes/assets.tsx +257 -0
- package/src/app/routes/doc.tsx +877 -0
- package/src/app/routes/home-shell.tsx +203 -0
- package/src/app/routes/home.tsx +269 -0
- package/src/app/routes/themes.tsx +121 -0
- package/src/app/styles.css +97 -0
- package/src/app/virtual.d.ts +30 -0
- package/template/AGENTS.md +27 -0
- package/template/README.md +39 -0
- package/template/docs/getting-started/index.tsx +230 -0
- package/template/mosage.config.ts +5 -0
- package/template/package.json +24 -0
- package/template/tsconfig.json +17 -0
- package/README.en.md +0 -57
- package/dist/cli.js +0 -4545
- package/dist/web/assets/index-Czg2WeHe.js +0 -182
- package/dist/web/assets/index-DKAyt92W.css +0 -1
- package/dist/web/index.html +0 -15
- package/skills/current-position/SKILL.md +0 -65
- package/skills/kickoff/SKILL.md +0 -105
- package/skills/mosage-reference/SKILL.md +0 -164
- package/skills/outline/SKILL.md +0 -79
- package/skills/review/SKILL.md +0 -64
- package/skills/write-chapter/SKILL.md +0 -58
- package/template/book/STYLE.md +0 -6
- package/template/book/assets/.gitkeep +0 -0
- package/template/book/book.yaml +0 -42
- package/template/book/brief.md +0 -6
- package/template/book/chapters/.gitkeep +0 -0
- package/template/book/notes/README.md +0 -7
- package/template/project/AGENTS.md +0 -82
- package/template/project/CLAUDE.md +0 -1
- package/template/project/README.md +0 -48
- package/template/project/books/.gitkeep +0 -0
- package/template/project/gitignore +0 -5
- package/template/project/mosage.yaml +0 -23
- package/template/project/notes/README.md +0 -8
- package/template/project/package.json +0 -14
|
@@ -1,87 +1,74 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: apply-comments
|
|
3
|
-
description:
|
|
3
|
+
description: Use this skill when the user asks to apply, process, or clear the comments they left in the MoSage inspector — phrases like "apply the comments", "apply my edits", "I left notes on the document", "process the markers", "/apply-comments". It finds every `@doc-comment` marker under `docs/`, makes the edit each one asks for, then removes the marker. Do NOT use for authoring new documents — that is `create-doc`.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Apply inspector comments
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
The dev UI's **Inspect** mode lets the user click any element on a page and leave a note. Each note is written into the document source as a marker:
|
|
9
9
|
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
```tsx
|
|
11
|
+
<p style={p}>
|
|
12
|
+
{/* @doc-comment id="c-4591fd61" ts="2026-08-15T15:40:52.644Z" text="<base64url>" */}
|
|
13
|
+
從 FastMCP 開發、容器化…
|
|
14
|
+
</p>
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
- 標記下方緊接的那個區塊就是留言的對象。
|
|
17
|
+
The marker is always the **first child of the element the note is about** — that is your anchor. `text` is base64url-encoded JSON: `{"note": "...", "hint": "p"}`.
|
|
19
18
|
|
|
20
|
-
## 1
|
|
19
|
+
## Step 1 — Find the pending comments
|
|
21
20
|
|
|
22
21
|
```bash
|
|
23
|
-
|
|
24
|
-
grep -rn "mosage:comment" books/<書>/chapters/
|
|
22
|
+
grep -rn "@doc-comment" docs/
|
|
25
23
|
```
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
If the dev server is running you can read them decoded instead, which is easier:
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- 依 `at` 由舊到新處理 —— 後面的留言可能修正前面的。
|
|
33
|
-
- 先讀 `brief.md`、`STYLE.md`,修改要符合風格。
|
|
27
|
+
```bash
|
|
28
|
+
curl -s "http://localhost:5273/__comments?docId=<id>"
|
|
29
|
+
```
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
That returns `{ comments: [{ id, line, ts, note, hint }] }`. If neither turns anything up, tell the user there are no pending comments and stop.
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
## Step 2 — Read each one in context
|
|
38
34
|
|
|
39
|
-
|
|
35
|
+
For every marker, read the surrounding element — not just the marked line. A note like *"make this shorter"* is meaningless without the paragraph it sits in. Open the file with `Read` around the marker's line (±40 lines is usually enough) so you can see the element, its styles, and its neighbours.
|
|
40
36
|
|
|
41
|
-
|
|
37
|
+
Group comments by document, and handle them **oldest `ts` first** — later notes may refine earlier ones.
|
|
42
38
|
|
|
43
|
-
|
|
44
|
-
<!-- mosage:suggest by=ai note="回應留言:改得口語,加上咖啡店的例子"
|
|
45
|
-
改寫後的**完整段落**(整段,不是只有改的那一句)。
|
|
46
|
-
-->
|
|
47
|
-
這是原本的那一段……
|
|
48
|
-
```
|
|
39
|
+
## Step 3 — Make the edit
|
|
49
40
|
|
|
50
|
-
-
|
|
51
|
-
- 要取代**連續多個區塊**(例如把兩段合併、重寫一整個清單加一段)→ 加上 `span=2`(取代下方 2 個區塊),內容寫出全部新文字,區塊之間空一行。
|
|
52
|
-
- 要**插入新段落**而不取代任何東西 → `span=0`,內容會插在下方區塊之前。
|
|
53
|
-
- `note` 用一句話說明你改了什麼、為什麼;作者會在介面上看到新舊對照,按「接受」或「拒絕」。
|
|
54
|
-
- `id` 可以省略(系統會自動產生)。
|
|
41
|
+
Apply what the note asks for, following the **`doc-authoring`** skill: it owns the type scale, the flow/vertical-budget rules, and the design tokens. In particular:
|
|
55
42
|
|
|
56
|
-
|
|
43
|
+
- Edit the element the marker is anchored to. Never reformat the whole file.
|
|
44
|
+
- A note about wording changes the text; a note about weight, color, or size changes the inline style — prefer `var(--od-*)` tokens over new hard-coded values.
|
|
45
|
+
- If the change makes a fixed page overflow, split the page or move the content into the `flow()` section (`references/pagination.md`).
|
|
46
|
+
- If a note is ambiguous ("fix this"), do the smallest reasonable interpretation and say what you assumed at hand-off. Don't guess at a large rewrite.
|
|
47
|
+
- If a note asks for something the framework can't do (per-page orientation, a splitting table), say so in the hand-off and leave the marker in place.
|
|
57
48
|
|
|
58
|
-
|
|
49
|
+
## Step 4 — Remove the marker
|
|
59
50
|
|
|
60
|
-
|
|
51
|
+
Delete the marker line for every comment you actually applied. Leave markers you deliberately skipped, and say which ones and why.
|
|
61
52
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
-->
|
|
67
|
-
```
|
|
68
|
-
- **留言要求全書一致的修改**(「全書統一用『使用者』」)→ 找出所有相關位置,每個受影響的區塊各提一個修改建議(suggest 模式)或直接修改(direct 模式)。
|
|
69
|
-
- **無法處理的要求**(例如需要作者提供的資料)→ 保留原留言,並在回報中說明原因。
|
|
70
|
-
|
|
71
|
-
## 4. 移除已處理的留言標記
|
|
53
|
+
```bash
|
|
54
|
+
# with the dev server running
|
|
55
|
+
curl -s -X DELETE "http://localhost:5273/__comments?docId=<id>&id=<comment-id>"
|
|
56
|
+
```
|
|
72
57
|
|
|
73
|
-
|
|
74
|
-
在 suggest 模式下,你已經用修改建議標記取代了它。**沒處理的留言要保留。**
|
|
58
|
+
Or delete the `{/* @doc-comment … */}` line directly with `Edit`. Removing it by hand is fine — the marker is a plain JSX comment.
|
|
75
59
|
|
|
76
|
-
|
|
60
|
+
## Step 5 — Verify
|
|
77
61
|
|
|
78
|
-
|
|
62
|
+
- No `@doc-comment` marker remains for an applied note: `grep -rn "@doc-comment" docs/`.
|
|
63
|
+
- The document still compiles: it hot-reloads in the browser; check the terminal for a Vite error.
|
|
64
|
+
- Run the "Self-review before finishing" checklist in `doc-authoring` for any page you touched.
|
|
79
65
|
|
|
80
|
-
|
|
66
|
+
## Step 6 — Hand off
|
|
81
67
|
|
|
82
|
-
|
|
83
|
-
- 跳過的留言與原因
|
|
68
|
+
Tell the user, in one short list:
|
|
84
69
|
|
|
85
|
-
|
|
70
|
+
- What you changed, one line per comment.
|
|
71
|
+
- Anything you skipped and why.
|
|
72
|
+
- Any assumption you made on an ambiguous note.
|
|
86
73
|
|
|
87
|
-
|
|
74
|
+
Do not restate the whole document.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-doc
|
|
3
|
+
description: Use this skill when the user wants to create, draft, author, or generate a new document, report, whitepaper, proposal, memo, or spec in this MoSage repo. Triggers on phrases like "write a report about X", "draft a proposal", "make a whitepaper", "create a document", "write up the Q3 results", or when the user asks to add content under `docs/`. Do NOT use for editing the framework itself — only for authoring content inside `docs/<id>/`.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Create a document in MoSage
|
|
7
|
+
|
|
8
|
+
This skill owns the **workflow** for drafting a new document. The technical reference — file contract, page canvas, print type scale, vertical budget, tables, TOC — lives in the **`doc-authoring`** skill. Read it before writing code; don't duplicate its rules here.
|
|
9
|
+
|
|
10
|
+
You only write files under `docs/<id>/`. Never modify `package.json`, `mosage.config.ts`, or existing documents.
|
|
11
|
+
|
|
12
|
+
**If the user already has the content written as Markdown, don't retype it into JSX.** `mosage import <file.md> --id <id>` produces a real document — `flow()` body, cover, contents, local images copied into the document's assets — which you then refine. Steps 0–2 still apply for the parts the import cannot know (theme, page size, visual direction).
|
|
13
|
+
|
|
14
|
+
## Step 0 — Pick a theme
|
|
15
|
+
|
|
16
|
+
List files under `themes/`. If any theme markdown exists (anything other than `README.md`), call `AskUserQuestion` with each theme id as an option plus a final **"no theme — design from scratch"** option. (`AskUserQuestion` holds at most 4 options — with 4+ themes, offer the 3 most relevant plus "no theme"; the auto-added "Other" lets the user name an omitted one.)
|
|
17
|
+
|
|
18
|
+
- If the user picks a theme: read `themes/<id>.md` end-to-end. Its palette, typography, page setup, and paste-ready components are now authoritative — copy them into the document, and set `meta.theme: '<id>'` in `index.tsx`. Skip the **visual direction** question in Step 2 (the theme already commits to one) and restate the theme name so the user can correct course. Page size comes from the theme's frontmatter unless the user overrides it.
|
|
19
|
+
- If the user picks "no theme", or `themes/` has no theme files: continue unchanged.
|
|
20
|
+
|
|
21
|
+
## Step 1 — Gather the substance first
|
|
22
|
+
|
|
23
|
+
A document is judged on content, not layout. Before anything else, establish:
|
|
24
|
+
|
|
25
|
+
- **Topic and purpose** — what decision or action should this document produce?
|
|
26
|
+
- **Audience** — executives (lead with the recommendation), engineers (lead with the mechanism), clients (lead with the outcome and the price).
|
|
27
|
+
- **Source material** — does the user have data, a draft, notes, a repo, an existing doc? Ask for it. **Never fabricate figures, quotes, citations, or customer names.**
|
|
28
|
+
|
|
29
|
+
If the request is thin ("write me a report"), make a **separate** `AskUserQuestion` call for topic, audience, and source material before the style questions below. If the topic is already clear, restate your reading of it in the next call so the user can correct course.
|
|
30
|
+
|
|
31
|
+
## Step 2 — Clarify the shape (MUST ask before writing code)
|
|
32
|
+
|
|
33
|
+
Ask these in a single `AskUserQuestion` call (multi-question form). Skip a question only when the user's message already answers it unambiguously — and restate the assumption if you skip.
|
|
34
|
+
|
|
35
|
+
1. **Document type** — propose 3 concrete types that fit *this* topic, each with what it implies structurally. Not bare labels:
|
|
36
|
+
- *"our Q3 infrastructure numbers"* → **internal review** (summary, metrics, incidents, actions) · **exec brief** (2 pages, recommendation-first) · **post-incident deep dive** (timeline, root cause, remediation)
|
|
37
|
+
- *"our new product for enterprise buyers"* → **whitepaper** (problem, approach, evidence, references) · **sales proposal** (scope, deliverables, timeline, price) · **one-pager** (positioning + proof + CTA)
|
|
38
|
+
Mark the best fit "(Recommended)".
|
|
39
|
+
2. **Length** — offer brackets: 2–4 pages (brief), 5–10 (standard report), 11–25 (deep dive). The auto-added "Other" covers custom counts.
|
|
40
|
+
3. **Page size** — A4 portrait (default) · A4 landscape (data-heavy, wide tables) · B4 or A3 (plans, posters, very wide tables). The only sizes are A4, B4 and A3, each portrait or landscape. Skip if the user already said.
|
|
41
|
+
4. **Visual direction** — 3 options tailored to the audience, each naming a palette + typographic cue: e.g. **corporate neutral** (near-white, single blue accent, sans throughout) · **editorial serif** (serif headings, generous leading, hairline rules) · **technical mono-accent** (mono labels, dense tables, monochrome + one signal color).
|
|
42
|
+
|
|
43
|
+
Ask about brand colors, a logo, or required sections only if still unclear afterwards.
|
|
44
|
+
|
|
45
|
+
## Step 3 — Pick a doc id
|
|
46
|
+
|
|
47
|
+
**kebab-case**, short, descriptive: `q3-infra-review`, `acme-proposal-2026`, `auth-migration-rfc`. Check `docs/` for collisions.
|
|
48
|
+
|
|
49
|
+
## Step 4 — Outline before code
|
|
50
|
+
|
|
51
|
+
Write the page plan first — one line per page, with its role. Typical structures:
|
|
52
|
+
|
|
53
|
+
| Type | Page plan |
|
|
54
|
+
| --- | --- |
|
|
55
|
+
| Report | Cover · Contents · Executive summary · Method · Findings (n pages) · Risks · Recommendations · Appendix |
|
|
56
|
+
| Whitepaper | Cover · Abstract · Problem · Approach · Evidence · Comparison · Conclusion · References |
|
|
57
|
+
| Proposal | Cover · Summary · Scope · Deliverables · Timeline · Pricing · Terms · Next steps |
|
|
58
|
+
| RFC / spec | Summary · Motivation · Design · Alternatives · Migration · Open questions |
|
|
59
|
+
| Memo | Header block · Context · Recommendation · Rationale · Next steps |
|
|
60
|
+
|
|
61
|
+
Rules for the plan:
|
|
62
|
+
|
|
63
|
+
- **Page 1 is the cover**; if the doc is over ~6 pages, **page 2 is `<TableOfContents />`**. Both are fixed pages; everything after them belongs in one `flow()` section so the framework paginates the body.
|
|
64
|
+
- The executive summary must stand alone — a reader who reads only that page should know the conclusion and the ask.
|
|
65
|
+
- One section per page unless a section is genuinely two paragraphs long.
|
|
66
|
+
- Plan the body as a **sequence of sections**, not as a page count — `flow()` decides how many pages that becomes. Only estimate the vertical budget for the fixed pages (cover, contents, dividers); see `doc-authoring` → `references/pagination.md`.
|
|
67
|
+
|
|
68
|
+
Show the user the page plan and the estimated page count before writing the file if the document is over ~8 pages — restructuring a 20-page doc after the fact is expensive.
|
|
69
|
+
|
|
70
|
+
## Step 5 — Commit to a visual direction
|
|
71
|
+
|
|
72
|
+
Declare a top-level `export const design: DesignSystem` and consume `var(--od-*)` everywhere. Print constraints (white background, ≥13px body, one accent) are in `references/design-system.md` — read it before choosing the palette. If a theme was picked in Step 0, copy its `design` const verbatim instead of inventing one.
|
|
73
|
+
|
|
74
|
+
Keep the const a plain object literal: the dev UI's **Design panel** parses and rewrites it, and a spread or a value read from another constant makes the document untweakable (see "Writing for the Design panel" in `doc-authoring`).
|
|
75
|
+
|
|
76
|
+
Define the shared page shell, heading styles, and the running footer **once** as local constants/components at the top of `index.tsx`, then reuse them on every page. Copy-pasted page styling is how documents drift.
|
|
77
|
+
|
|
78
|
+
## Step 6 — Write `docs/<id>/index.tsx`
|
|
79
|
+
|
|
80
|
+
Read **`doc-authoring`** first — file contract, canvas, type scale, headings/outline, TOC, page numbers, and a starter template are all there.
|
|
81
|
+
|
|
82
|
+
While writing:
|
|
83
|
+
|
|
84
|
+
- Real `<h1>/<h2>/<h3>` for every section title, so the outline and TOC populate.
|
|
85
|
+
- `<TableOfContents />` for the contents page. Never hand-write one.
|
|
86
|
+
- `useDocPageNumber()` / `useDocPageCount()` for the footer. Never hardcode.
|
|
87
|
+
- Put body content in one `flow(<>…</>, { footer: Footer })` section; mark captions `data-od-keep-with-previous`. Only run budget math for fixed pages.
|
|
88
|
+
- Where the user must supply data, leave `<ImagePlaceholder hint="…">` or an explicit `TODO:` in the copy — never invent numbers.
|
|
89
|
+
|
|
90
|
+
## Step 7 — Self-review
|
|
91
|
+
|
|
92
|
+
**Run `mosage check <id>` first.** You cannot see the sheets you produced; it renders them at true page size and reports clipped content, blank pages, stranded headings, and unreadable type, each with a source location. Fix every error before moving on.
|
|
93
|
+
|
|
94
|
+
Then run the checklist in `doc-authoring` ("Self-review before finishing"), and re-read the prose once as a reader: does the summary state the conclusion? Does every claim have a source?
|
|
95
|
+
|
|
96
|
+
## Step 8 — Hand off
|
|
97
|
+
|
|
98
|
+
Tell the user:
|
|
99
|
+
|
|
100
|
+
- The doc id and file path.
|
|
101
|
+
- That the dev server hot-reloads — open `http://localhost:5273/d/<id>` (or refresh the home page).
|
|
102
|
+
- **Every placeholder and `TODO:` you left**, and what data each one needs.
|
|
103
|
+
- That "Export PDF" in the toolbar prints at the true page size, and "HTML" downloads a self-contained copy — or `mosage export <id>` for the same files without a browser.
|
|
104
|
+
- That the **Design** button live-tweaks the palette and type scale and writes the result back to the source, and that images they want to drop in go through the **Assets** page.
|
|
105
|
+
|
|
106
|
+
Don't run the dev server yourself unless asked.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-theme
|
|
3
|
+
description: Use this skill when the user wants to create, draft, author, or extract a document theme in this MoSage repo — a reusable house style for reports, proposals, or memos. Triggers on phrases like "create a theme", "make a company template", "extract a theme from <doc>", "match our brand guidelines". Produces two paired files under `themes/` — `<id>.md` (palette, typography, page setup, paste-ready Title/Footer/Table components) and `<id>.demo.tsx` (a runnable two-page demo the Themes gallery previews). Do NOT use for editing real documents — only for authoring the theme bundle.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Create a document theme
|
|
7
|
+
|
|
8
|
+
A **theme bundle** under `themes/` is two paired files describing a reusable house style:
|
|
9
|
+
|
|
10
|
+
1. `themes/<id>.md` — agent-facing documentation: palette, typography, page setup, paste-ready components. This is what `create-doc` reads when the author picks the theme.
|
|
11
|
+
2. `themes/<id>.demo.tsx` — a runnable two-page mini-document (a normal document module: `export default DocPage[]`) that shows the theme in use. The Themes gallery renders it as the live preview.
|
|
12
|
+
|
|
13
|
+
Both files share the same stem so the runtime pairs them automatically.
|
|
14
|
+
|
|
15
|
+
A theme is **distinct from a document's `design` const**:
|
|
16
|
+
|
|
17
|
+
| | What it is | Who reads it |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| `themes/<id>.md` | Authoring-time direction, copied into a real document | `create-doc`, you |
|
|
20
|
+
| `themes/<id>.demo.tsx` | A preview, not a real document (never appears in the documents list) | The Themes gallery |
|
|
21
|
+
| `export const design` in `docs/<id>/index.tsx` | Runtime tokens the Design panel can live-tweak and write back | The runtime |
|
|
22
|
+
|
|
23
|
+
You only write `themes/<id>.md` and `themes/<id>.demo.tsx`. Never modify real documents or config. Read the **`doc-authoring`** skill first — the page canvas, print type scale, and vertical budget it defines are what your overrides are stated against.
|
|
24
|
+
|
|
25
|
+
## Step 1 — Identify the input source
|
|
26
|
+
|
|
27
|
+
A theme can come from any combination of:
|
|
28
|
+
|
|
29
|
+
- **Brand material** — a style guide PDF, brand colors, a letterhead, existing reports (paths or URLs).
|
|
30
|
+
- **Free-text description** — prose describing palette, fonts, and feel.
|
|
31
|
+
- **An existing document** — `docs/<id>/index.tsx` whose look should be lifted into a reusable theme.
|
|
32
|
+
|
|
33
|
+
If the user's message already names the inputs, proceed. Otherwise call `AskUserQuestion` (multi-select) and ask follow-ups (paths, doc id, prose) only as needed.
|
|
34
|
+
|
|
35
|
+
## Step 2 — Gather raw inputs
|
|
36
|
+
|
|
37
|
+
- **Images / PDFs**: read each path with `Read` (it accepts images and PDFs). Note hex colors, heading/body faces and weights, margin rhythm, rule weights, table styling, and any recurring chrome (letterhead, footer rule, page-number position).
|
|
38
|
+
- **Text**: extract explicit tokens (hex codes, font names, "20mm margins") and implicit tone ("conservative", "editorial", "technical"). Resolve vague language into concrete numbers before writing.
|
|
39
|
+
- **Existing document**: read `docs/<id>/index.tsx` and pull the `design` const, the shared `page`/`h1`/`h2` style objects, the running `Footer`, table cell components, and the callout style.
|
|
40
|
+
|
|
41
|
+
When inputs disagree (brand deck says navy, the sample report is black), ask which wins.
|
|
42
|
+
|
|
43
|
+
## Step 3 — Pick a theme id
|
|
44
|
+
|
|
45
|
+
**kebab-case**, short, descriptive: `acme-corporate`, `editorial-serif`, `technical-brief`, `board-memo`. Check `themes/` for collisions.
|
|
46
|
+
|
|
47
|
+
## Step 4 — Write `themes/<id>.md`
|
|
48
|
+
|
|
49
|
+
Keep this exact section order; adapt the bodies.
|
|
50
|
+
|
|
51
|
+
````markdown
|
|
52
|
+
---
|
|
53
|
+
name: <Human title, e.g. "Acme Corporate">
|
|
54
|
+
description: <one-line elevator pitch>
|
|
55
|
+
pageSize: <A4 | B4 | A3>
|
|
56
|
+
mode: <light | dark — light for anything that prints>
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
# <Theme name>
|
|
60
|
+
|
|
61
|
+
## When to use
|
|
62
|
+
|
|
63
|
+
<Two sentences: which document types this fits, and which it doesn't.>
|
|
64
|
+
|
|
65
|
+
## Palette
|
|
66
|
+
|
|
67
|
+
| Role | Value | Notes |
|
|
68
|
+
| ------ | --------- | --------------------------------------- |
|
|
69
|
+
| bg | `#ffffff` | sheet background — keep near-white |
|
|
70
|
+
| text | `#16181d` | body copy |
|
|
71
|
+
| muted | `#6b7280` | captions, footers, secondary cells |
|
|
72
|
+
| accent | `#1d4ed8` | section numbers, rules, chart series |
|
|
73
|
+
| rule | `#e5e7eb` | table borders, hairlines, dot leaders |
|
|
74
|
+
|
|
75
|
+
Extra colors outside the `DesignSystem` shape (status green/amber/red, chart series) go in a
|
|
76
|
+
"Supporting colors" list below the table.
|
|
77
|
+
|
|
78
|
+
## Typography
|
|
79
|
+
|
|
80
|
+
- Heading font: `<stack>` — weight <n>.
|
|
81
|
+
- Body font: `<stack>` — weight 400.
|
|
82
|
+
- Mono font: `<stack>` — tables of code/IDs only.
|
|
83
|
+
- Webfont import (omit for system stacks): `<stylesheet URL>` — load per `references/design-system.md` in `doc-authoring`.
|
|
84
|
+
- Type scale (px at 96dpi): title <n> · h1 <n> · h2 <n> · h3 <n> · body <n> · caption <n>.
|
|
85
|
+
|
|
86
|
+
## Page setup
|
|
87
|
+
|
|
88
|
+
- Page size: A4 portrait (794 × 1123 px).
|
|
89
|
+
- Margin: <n> px on all sides (<n> mm).
|
|
90
|
+
- Leading: <n>.
|
|
91
|
+
- Running footer: <what it shows, where it sits>.
|
|
92
|
+
- Cover: <centered / bottom-aligned, what it carries>.
|
|
93
|
+
|
|
94
|
+
## Design const
|
|
95
|
+
|
|
96
|
+
Paste-ready — this is what a document using the theme declares:
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
export const design: DesignSystem = {
|
|
100
|
+
palette: { bg: '…', text: '…', muted: '…', accent: '…', rule: '…' },
|
|
101
|
+
fonts: { heading: '…', body: '…', mono: '…' },
|
|
102
|
+
typeScale: { title: 44, h1: 28, h2: 20, h3: 16, body: 14, caption: 10 },
|
|
103
|
+
margin: 76,
|
|
104
|
+
leading: 1.55,
|
|
105
|
+
radius: 6,
|
|
106
|
+
};
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Fixed components
|
|
110
|
+
|
|
111
|
+
Paste-ready. Copy verbatim into a document using this theme.
|
|
112
|
+
|
|
113
|
+
### Page shell + headings
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
const page = { /* … */ } as const;
|
|
117
|
+
const h1 = { /* … */ } as const;
|
|
118
|
+
const h2 = { /* … */ } as const;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Running footer
|
|
122
|
+
|
|
123
|
+
Read the page number from `useDocPageNumber()` / `useDocPageCount()` — never hardcode it.
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
const Footer = () => { /* … */ };
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Table
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
const Th = ({ children }: { children: React.ReactNode }) => /* … */;
|
|
133
|
+
const Td = ({ children }: { children: React.ReactNode }) => /* … */;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Include a callout and a stat component when the theme calls for them.
|
|
137
|
+
|
|
138
|
+
## Rules
|
|
139
|
+
|
|
140
|
+
- <3–6 bullets a document must follow to stay on-theme: what never appears, how sections are numbered, whether the cover carries a logo, table style, figure captions.>
|
|
141
|
+
````
|
|
142
|
+
|
|
143
|
+
## Step 5 — Write `themes/<id>.demo.tsx`
|
|
144
|
+
|
|
145
|
+
A normal document module — **two pages**: a cover and one content page that exercises the theme's headings, body copy, a table, and the running footer.
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
import { type DesignSystem, type DocPage, useDocPageCount, useDocPageNumber } from 'mosage';
|
|
149
|
+
|
|
150
|
+
export const design: DesignSystem = { /* the same const as in the .md */ };
|
|
151
|
+
|
|
152
|
+
const Cover: DocPage = () => ( /* … */ );
|
|
153
|
+
const Content: DocPage = () => ( /* … */ );
|
|
154
|
+
|
|
155
|
+
export default [Cover, Content] satisfies DocPage[];
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Rules for the demo:
|
|
159
|
+
|
|
160
|
+
- **No `meta` export** — the demo is not a real document and must not carry `createdAt` or a title that implies it is.
|
|
161
|
+
- Two pages, no more. The gallery renders the first; the theme detail page renders both.
|
|
162
|
+
- Use placeholder copy that shows the type scale honestly (a real heading, a real paragraph, a real 4-row table) — not lorem ipsum blocks that hide how the theme handles wrapping.
|
|
163
|
+
- Respect the vertical budget from `doc-authoring` → `references/pagination.md`. A demo that overflows teaches the wrong lesson.
|
|
164
|
+
- Keep it self-contained: no asset imports, no webfont the `.md` didn't declare.
|
|
165
|
+
|
|
166
|
+
## Step 6 — Self-review
|
|
167
|
+
|
|
168
|
+
- [ ] Both files exist and share the same stem.
|
|
169
|
+
- [ ] Frontmatter has `name`, `description`, `pageSize`, `mode`.
|
|
170
|
+
- [ ] The `design` const in the `.md` and in the demo are identical.
|
|
171
|
+
- [ ] The palette background is white or near-white (see `references/design-system.md` — dark documents print badly).
|
|
172
|
+
- [ ] Body type ≥ 13px; caption ≥ 9px.
|
|
173
|
+
- [ ] The footer pulls page numbers from the hooks.
|
|
174
|
+
- [ ] Every "paste-ready" component actually compiles as written — no `…` left in the code blocks.
|
|
175
|
+
- [ ] The demo fits its pages.
|
|
176
|
+
- [ ] Nothing outside `themes/` was written.
|
|
177
|
+
|
|
178
|
+
## Step 7 — Hand off
|
|
179
|
+
|
|
180
|
+
Tell the user:
|
|
181
|
+
|
|
182
|
+
- The theme id and both file paths.
|
|
183
|
+
- That it shows up under **Themes** in the dev UI (`http://localhost:5273/themes/<id>`).
|
|
184
|
+
- That new documents can adopt it by setting `meta.theme: '<id>'`, which adds the back-link chip — and that `create-doc` will now offer it as a choice.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: current-doc
|
|
3
|
+
description: Resolve which document, page, and (optionally) selected element the user is currently viewing in the mosage dev server. Consult this whenever the user references "this page", "this document", "this element", "the page I'm on", "the report I'm looking at", or any deictic reference to document content without naming it. Re-read `node_modules/.mosage/current.json` at the start of every such turn — the user navigates between turns, so a value you read earlier in the conversation is almost certainly stale.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Where is the user right now?
|
|
7
|
+
|
|
8
|
+
When the user says "fix this page", "tighten this heading", or "the report I'm looking at", they almost never name the document id, page number, or element — they mean wherever they are in the dev viewer. Before asking "which document?" or "which element?", check the file the dev server writes on every navigation and inspector pick.
|
|
9
|
+
|
|
10
|
+
## Re-read on every deictic turn — never reuse a prior read
|
|
11
|
+
|
|
12
|
+
`current.json` is a live cursor, not a fact about the conversation. The user moves between documents, pages, and elements freely between your turns — including while you were doing other work. **Read the file fresh at the start of every new turn that uses a deictic reference**, even if:
|
|
13
|
+
|
|
14
|
+
- you already read it earlier in this same conversation,
|
|
15
|
+
- you just finished editing the document it pointed to,
|
|
16
|
+
- the user's new message sounds like a continuation ("now make it bigger", "also fix this one", "keep going").
|
|
17
|
+
|
|
18
|
+
A "continue editing" follow-up is exactly the case where the user has likely just scrolled to a different page or picked a different element. Trusting your last read here will silently edit the wrong sheet. Re-read, compare `docId` / `pageIndex` / `selection` against what you used last time, and act on the new values.
|
|
19
|
+
|
|
20
|
+
## How to read it
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
node_modules/.mosage/current.json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Path is relative to the project root (the user's `cwd`, the directory that contains `docs/` and `package.json`). Use the `Read` tool. The file is JSON.
|
|
27
|
+
|
|
28
|
+
## What you get
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"docId": "q3-review",
|
|
33
|
+
"pageIndex": 2,
|
|
34
|
+
"pageNumber": 3,
|
|
35
|
+
"totalPages": 8,
|
|
36
|
+
"docTitle": "Q3 Review",
|
|
37
|
+
"pagePath": "docs/q3-review/index.tsx",
|
|
38
|
+
"selection": {
|
|
39
|
+
"line": 42,
|
|
40
|
+
"column": 6,
|
|
41
|
+
"tagName": "h2",
|
|
42
|
+
"text": "Availability"
|
|
43
|
+
},
|
|
44
|
+
"updatedAt": "2026-08-17T14:32:11.123Z"
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- `docId` — folder name under `docs/`. Use as-is for any `/__docs/<id>/...` API or as the URL segment (`/d/<docId>`).
|
|
49
|
+
- `pageIndex` — 0-based **rendered** page index.
|
|
50
|
+
- `pageNumber` — 1-based, for talking to the user ("page 3 of 8").
|
|
51
|
+
- `totalPages` — how many sheets the document currently renders to.
|
|
52
|
+
- `pagePath` — relative path to the document source. Hand straight to `Read` / `Edit`.
|
|
53
|
+
- `selection` — `null` if nothing is selected. Otherwise, the JSX element the user picked in the inspector overlay:
|
|
54
|
+
- `line` (1-indexed) and `column` (0-indexed) point to the JSX opening tag inside `pagePath`. This is the canonical handle — match against the source line, not the rendered DOM.
|
|
55
|
+
- `tagName` is the rendered DOM tag, lowercased (`"h1"`, `"p"`, `"td"`).
|
|
56
|
+
- `text` is a trimmed snippet (≤120 chars) of the element's `textContent`, useful to confirm you are looking at the right node.
|
|
57
|
+
- Selection auto-clears whenever the user moves to a different document or page.
|
|
58
|
+
- `updatedAt` — ISO timestamp of the last navigation or selection change. Use it to detect staleness.
|
|
59
|
+
|
|
60
|
+
## Rendered pages are not entries in the default export
|
|
61
|
+
|
|
62
|
+
This is the one thing that differs from a slide deck, and getting it wrong means editing the wrong thing.
|
|
63
|
+
|
|
64
|
+
`export default [Cover, Contents, flow(<>…</>)]` has three *entries*, but may render to twelve *sheets* — the framework measures a `flow()` section and packs it across as many pages as it needs. So:
|
|
65
|
+
|
|
66
|
+
- **`pageIndex` indexes rendered sheets, not the array.** Do not use it to subscript the default export.
|
|
67
|
+
- To find what to edit, prefer `selection` (it points at real source coordinates), then the page's visible text, then the surrounding heading.
|
|
68
|
+
- If the user is on a flow page and there is no selection, identify the content by what they can see — read the source and match the prose — rather than counting array entries.
|
|
69
|
+
- A fixed `DocPage` component *is* one sheet, so for documents made only of fixed pages the index does line up. Confirm with `pagePath` before relying on that.
|
|
70
|
+
|
|
71
|
+
## When to use this
|
|
72
|
+
|
|
73
|
+
- The user references the current document/page deictically: "this", "here", "the page I'm on", "what I'm looking at".
|
|
74
|
+
- The user references a specific element: "this heading", "this table", "tighten this", "make this smaller". If `selection` is non-null, that's the element they mean.
|
|
75
|
+
- Before asking "which document?" or "which page?" as a clarifying question — check this file first.
|
|
76
|
+
- Before guessing from `git log`, recently-edited files, or the newest folder under `docs/`.
|
|
77
|
+
|
|
78
|
+
## When NOT to use this
|
|
79
|
+
|
|
80
|
+
- The user names a document explicitly ("edit `q3-review`") — use that name directly.
|
|
81
|
+
- The `apply-comments` workflow already finds its own targets via `@doc-comment` markers; it does not need this skill.
|
|
82
|
+
- For listing or discovering documents — read `docs/` directly.
|
|
83
|
+
|
|
84
|
+
## Staleness — verify before acting
|
|
85
|
+
|
|
86
|
+
`updatedAt` is the last time the user navigated. Treat it like a cache:
|
|
87
|
+
|
|
88
|
+
- **Fresh (under ~5 minutes old)**: trust it. Open `pagePath`, do the work.
|
|
89
|
+
- **Older than ~5 minutes**: confirm with the user before editing. The dev server may not be running; the user may have switched contexts.
|
|
90
|
+
- **Hours/days old**: ignore it. Ask which document they mean.
|
|
91
|
+
|
|
92
|
+
A *newer* `updatedAt` than the one you saw last turn is the normal signal that the user has moved — switch to the new `docId` / `pageIndex` / `selection` without asking.
|
|
93
|
+
|
|
94
|
+
## When the file is missing
|
|
95
|
+
|
|
96
|
+
- The dev server has not been opened on a document yet, or has never run. A static build never writes it.
|
|
97
|
+
- Don't create the file or guess. Ask which document they mean, or suggest they open it in the dev server first.
|
|
98
|
+
|
|
99
|
+
## Example — page-level reference
|
|
100
|
+
|
|
101
|
+
User: "tighten the spacing on this page"
|
|
102
|
+
|
|
103
|
+
1. Read `node_modules/.mosage/current.json`.
|
|
104
|
+
2. Check `updatedAt` is recent.
|
|
105
|
+
3. Read `pagePath` (e.g. `docs/q3-review/index.tsx`).
|
|
106
|
+
4. Work out what is on `pageNumber` — by the selection, or by matching visible content, remembering that a flow section spans many sheets.
|
|
107
|
+
5. Consult the `doc-authoring` skill for the spacing and vertical-budget rules, then edit in place.
|
|
108
|
+
|
|
109
|
+
If `current.json` is missing or stale, ask: "Which document and page should I tighten? The dev server hasn't published a current page recently."
|
|
110
|
+
|
|
111
|
+
## Example — element-level reference
|
|
112
|
+
|
|
113
|
+
User: "make this bigger"
|
|
114
|
+
|
|
115
|
+
1. Read `node_modules/.mosage/current.json`.
|
|
116
|
+
2. If `selection` is non-null, that is the element. Read `pagePath`, jump to `selection.line`, and find the JSX opening tag near that line/column. Confirm against `selection.text` and `tagName`.
|
|
117
|
+
3. Consult `doc-authoring` for the print type scale before editing — a size that looks fine on screen can print below the legibility floor.
|
|
118
|
+
4. Edit the JSX node in place.
|
|
119
|
+
|
|
120
|
+
If `selection` is null, fall back to the page-level flow above — and consider asking "which element?", since the user used a deictic but hasn't picked one in the inspector.
|