skilldrop-cli 1.1.3 → 1.3.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/README.md +1 -1
- package/catalogue.json +7 -8
- package/model-routing.json +0 -16
- package/package.json +1 -1
- package/packs/ai-engineering/loops/adopt/LOOP.md +120 -0
- package/packs/ai-engineering/loops/adopt/evals/eval_queries.json +10 -0
- package/packs/ai-engineering/loops/adopt/evals/evals.json +69 -0
- package/packs/ai-engineering/loops/adopt/evals/files/adopt-first-wave-to-sign-off/ai-ideas.md +15 -0
- package/packs/ai-engineering/loops/adopt/evals/files/adopt-first-wave-to-sign-off/org-context.md +27 -0
- package/packs/ai-engineering/loops/adopt/evals/files/adopt-first-wave-to-sign-off/staff-survey.csv +11 -0
- package/packs/ai-engineering/loops/adopt/evals/files/adopt-sponsor-slice-blocked-by-client-data/ai-ideas.md +13 -0
- package/packs/ai-engineering/loops/adopt/evals/files/adopt-sponsor-slice-blocked-by-client-data/firm-context.md +23 -0
- package/packs/ai-engineering/loops/adopt/loop.json +53 -0
- package/packs/ai-engineering/loops/ship-agent/LOOP.md +128 -0
- package/packs/ai-engineering/loops/ship-agent/evals/eval_queries.json +10 -0
- package/packs/ai-engineering/loops/ship-agent/evals/evals.json +70 -0
- package/packs/ai-engineering/loops/ship-agent/evals/files/ship-agent-auto-reply-exfil-open/agent-brief.md +33 -0
- package/packs/ai-engineering/loops/ship-agent/evals/files/ship-agent-changelog-config-reopens-path/agent-brief.md +33 -0
- package/packs/ai-engineering/loops/ship-agent/evals/files/ship-agent-changelog-config-reopens-path/claude-settings.json +25 -0
- package/packs/ai-engineering/loops/ship-agent/evals/files/ship-agent-changelog-config-reopens-path/sample-merged-prs.md +30 -0
- package/packs/ai-engineering/loops/ship-agent/loop.json +53 -0
- package/packs/ai-engineering/skills/ai-usage-report/examples/weekly-engineering-team.md +1 -1
- package/packs/ai-engineering/skills/ai-usage-report/templates/usage-event-schema.md +2 -2
- package/packs/converters/pack.json +3 -14
- package/packs/converters/skills/file-to-markdown/SKILL.md +28 -11
- package/packs/converters/skills/file-to-markdown/evals/evals.json +30 -0
- package/packs/converters/skills/file-to-markdown/evals/files/5/supplier_agreement_v3.docx +0 -0
- package/packs/converters/skills/file-to-markdown/evals/files/6/numbers.xlsx +0 -0
- package/packs/converters/skills/file-to-markdown/evals/files/6/offsite_q3.pptx +0 -0
- package/packs/converters/skills/file-to-markdown/examples/inputs/acme-brief.docx +0 -0
- package/packs/converters/skills/file-to-markdown/examples/inputs/northwind-roadmap.pptx +0 -0
- package/packs/converters/skills/file-to-markdown/examples/mixed-inputs.md +24 -16
- package/packs/converters/skills/file-to-markdown/manifest.json +2 -3
- package/packs/converters/skills/file-to-markdown/scripts/to_markdown.py +103 -10
- package/packs/converters/skills/md-to-confluence/SKILL.md +2 -2
- package/packs/converters/skills/md-to-confluence/manifest.json +2 -9
- package/packs/converters/skills/md-to-docx/SKILL.md +3 -4
- package/packs/converters/skills/md-to-docx/evals/evals.json +1 -1
- package/packs/converters/skills/md-to-docx/evals/files/1/brand/brand.json +1 -1
- package/packs/converters/skills/md-to-docx/manifest.json +4 -11
- package/packs/converters/skills/md-to-docx/reference.md +1 -1
- package/packs/converters/skills/md-to-docx/scripts/md_to_docx.py +1 -1
- package/packs/converters/skills/md-to-pptx/SKILL.md +3 -5
- package/packs/converters/skills/md-to-pptx/manifest.json +3 -16
- package/packs/converters/skills/md-to-pptx/scripts/md_to_pptx.py +1 -1
- package/packs/converters/skills/md-to-xlsx/SKILL.md +1 -1
- package/packs/converters/skills/md-to-xlsx/manifest.json +2 -2
- package/packs/core/skills/brief-intake/SKILL.md +2 -2
- package/packs/core/skills/brief-intake/manifest.json +2 -2
- package/packs/core/skills/brief-intake/templates/brief-deck.md +3 -3
- package/packs/core/skills/doc-critique/rubrics/deck.md +1 -1
- package/packs/design/pack.json +11 -21
- package/packs/design/skills/brand-kit/SKILL.md +6 -8
- package/packs/design/skills/brand-kit/manifest.json +3 -17
- package/packs/design/skills/brand-kit/templates/brand.json +1 -1
- package/packs/experience-design/loops/clarify/LOOP.md +114 -0
- package/packs/experience-design/loops/clarify/evals/eval_queries.json +10 -0
- package/packs/experience-design/loops/clarify/evals/evals.json +68 -0
- package/packs/experience-design/loops/clarify/evals/files/clarify-garden-waste-no-complaint-data/form-fields.csv +12 -0
- package/packs/experience-design/loops/clarify/evals/files/clarify-garden-waste-no-complaint-data/garden-waste-page.md +29 -0
- package/packs/experience-design/loops/clarify/evals/files/clarify-parking-permit-with-call-data/backoffice-notes.md +14 -0
- package/packs/experience-design/loops/clarify/evals/files/clarify-parking-permit-with-call-data/calls-q3.csv +8 -0
- package/packs/experience-design/loops/clarify/evals/files/clarify-parking-permit-with-call-data/form-fields.csv +12 -0
- package/packs/experience-design/loops/clarify/evals/files/clarify-parking-permit-with-call-data/permit-page.md +27 -0
- package/packs/experience-design/loops/clarify/loop.json +35 -0
- package/packs/infra-as-code/loops/provision/LOOP.md +128 -0
- package/packs/infra-as-code/loops/provision/evals/eval_queries.json +9 -0
- package/packs/infra-as-code/loops/provision/evals/evals.json +67 -0
- package/packs/infra-as-code/loops/provision/evals/files/provision-rds-no-plan-yet/.terraform.lock.hcl.fixture +24 -0
- package/packs/infra-as-code/loops/provision/evals/files/provision-rds-no-plan-yet/network.md +36 -0
- package/packs/infra-as-code/loops/provision/evals/files/provision-replica-plan-replaces-primary/main.tf +74 -0
- package/packs/infra-as-code/loops/provision/evals/files/provision-replica-plan-replaces-primary/plan.json +901 -0
- package/packs/infra-as-code/loops/provision/evals/files/provision-replica-plan-replaces-primary/variables.tf +47 -0
- package/packs/infra-as-code/loops/provision/loop.json +41 -0
- package/packs/solution-architect/skills/interactive-diagram/SKILL.md +1 -1
- package/packs/solution-architect/skills/interactive-diagram/manifest.json +1 -2
- package/packs/stakeholder-comms/skills/audience-profile/SKILL.md +3 -3
- package/packs/stakeholder-comms/skills/audience-profile/manifest.json +2 -2
- package/packs/stakeholder-comms/skills/audience-profile/reference.md +1 -1
- package/packs/converters/skills/md-to-html/SKILL.md +0 -108
- package/packs/converters/skills/md-to-html/evals/eval_queries.json +0 -34
- package/packs/converters/skills/md-to-html/evals/evals.json +0 -44
- package/packs/converters/skills/md-to-html/evals/files/1/brand/brand.json +0 -80
- package/packs/converters/skills/md-to-html/evals/files/1/brand/logo-white.png +0 -0
- package/packs/converters/skills/md-to-html/evals/files/1/brand/logo.png +0 -0
- package/packs/converters/skills/md-to-html/evals/files/1/brand/mark.png +0 -0
- package/packs/converters/skills/md-to-html/evals/files/1/docs/q3-review.md +0 -35
- package/packs/converters/skills/md-to-html/evals/files/1/img/dashboard.png +0 -0
- package/packs/converters/skills/md-to-html/evals/files/2/brand.json +0 -13
- package/packs/converters/skills/md-to-html/evals/files/2/img/kick-net.png +0 -0
- package/packs/converters/skills/md-to-html/evals/files/2/river-survey-guide.md +0 -53
- package/packs/converters/skills/md-to-html/evals/files/3/nanas-lentil-soup.md +0 -21
- package/packs/converters/skills/md-to-html/evals/files/3/pot.png +0 -0
- package/packs/converters/skills/md-to-html/examples/inputs/chart.svg +0 -8
- package/packs/converters/skills/md-to-html/examples/inputs/ops-review.md +0 -48
- package/packs/converters/skills/md-to-html/examples/ops-review.md +0 -83
- package/packs/converters/skills/md-to-html/manifest.json +0 -43
- package/packs/converters/skills/md-to-html/reference.md +0 -70
- package/packs/converters/skills/md-to-html/scripts/md_to_html.py +0 -662
- package/packs/converters/skills/mermaid-render/SKILL.md +0 -117
- package/packs/converters/skills/mermaid-render/evals/eval_queries.json +0 -30
- package/packs/converters/skills/mermaid-render/evals/evals.json +0 -43
- package/packs/converters/skills/mermaid-render/evals/files/1/docs/contoso-orders.md +0 -23
- package/packs/converters/skills/mermaid-render/evals/files/2/dispensing-diagrams.md +0 -39
- package/packs/converters/skills/mermaid-render/examples/broken-diagrams.md +0 -147
- package/packs/converters/skills/mermaid-render/examples/inputs/broken-flowchart.mmd +0 -8
- package/packs/converters/skills/mermaid-render/examples/inputs/broken-sequence.mmd +0 -11
- package/packs/converters/skills/mermaid-render/examples/inputs/checkout-flow.mmd +0 -9
- package/packs/converters/skills/mermaid-render/examples/inputs/design-notes.md +0 -35
- package/packs/converters/skills/mermaid-render/examples/inputs/fixed-flowchart.mmd +0 -9
- package/packs/converters/skills/mermaid-render/examples/inputs/typo.mmd +0 -2
- package/packs/converters/skills/mermaid-render/manifest.json +0 -50
- package/packs/converters/skills/mermaid-render/reference.md +0 -70
- package/packs/converters/skills/mermaid-render/scripts/render_mermaid.py +0 -487
- package/packs/design/skills/deck-builder/SKILL.md +0 -209
- package/packs/design/skills/deck-builder/evals/eval_queries.json +0 -14
- package/packs/design/skills/deck-builder/evals/evals.json +0 -67
- package/packs/design/skills/deck-builder/evals/files/4/ashby-vale-board-notes.md +0 -36
- package/packs/design/skills/deck-builder/examples/exec-board-update.md +0 -108
- package/packs/design/skills/deck-builder/examples/templated-brand-deck.md +0 -148
- package/packs/design/skills/deck-builder/manifest.json +0 -18
- package/packs/design/skills/deck-builder/reference.md +0 -180
- package/packs/design/skills/deck-builder/requirements.txt +0 -3
- package/packs/design/skills/deck-builder/scripts/build_deck.py +0 -1144
- package/packs/design/skills/deck-builder/templates/deck-spec.json +0 -168
- package/packs/design/skills/deck-builder/templates/palettes.json +0 -59
- package/packs/design/skills/marketing-flyer/SKILL.md +0 -113
- package/packs/design/skills/marketing-flyer/evals/eval_queries.json +0 -30
- package/packs/design/skills/marketing-flyer/evals/evals.json +0 -45
- package/packs/design/skills/marketing-flyer/evals/files/1/brand/brand.json +0 -80
- package/packs/design/skills/marketing-flyer/evals/files/1/brand/logo-white.png +0 -0
- package/packs/design/skills/marketing-flyer/evals/files/1/brand/logo.png +0 -0
- package/packs/design/skills/marketing-flyer/evals/files/1/brand/mark.png +0 -0
- package/packs/design/skills/marketing-flyer/evals/files/2/brand.json +0 -14
- package/packs/design/skills/marketing-flyer/evals/files/2/larchfield-logo.svg +0 -4
- package/packs/design/skills/marketing-flyer/evals/files/2/manager-email.txt +0 -6
- package/packs/design/skills/marketing-flyer/evals/files/2/open-day-brief.md +0 -15
- package/packs/design/skills/marketing-flyer/examples/community-health-fair.md +0 -68
- package/packs/design/skills/marketing-flyer/manifest.json +0 -40
- package/packs/design/skills/marketing-flyer/reference.md +0 -54
- package/packs/design/skills/marketing-flyer/scripts/build_flyer.py +0 -332
- package/packs/design/skills/marketing-flyer/templates/flyer-spec.json +0 -26
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
Stdlib only, Python 3.9+. Handles .docx, .pptx, .xlsx, .html/.htm, .csv/.tsv,
|
|
5
5
|
.json, .txt/.md, .eml and Outlook .msg email, and .pdf (through `pdftotext` when it is installed). A PDF page with no
|
|
6
6
|
text layer (a scan) is read by OCR when `tesseract` and `pdftoppm` are installed.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
Embedded .docx and .pptx images are saved beside the output and linked, and tracked
|
|
8
|
+
changes come through as pending ({++added++}, {--removed--}). Everything else the
|
|
9
|
+
conversion could not carry (charts, comments, formulas) is counted and reported on
|
|
10
|
+
stderr, so nobody mistakes the Markdown for the whole document.
|
|
10
11
|
|
|
11
12
|
Usage:
|
|
12
13
|
python3 to_markdown.py report.docx -o report.md
|
|
@@ -20,6 +21,7 @@ import argparse
|
|
|
20
21
|
import csv
|
|
21
22
|
import io
|
|
22
23
|
import json
|
|
24
|
+
import os
|
|
23
25
|
import re
|
|
24
26
|
import shutil
|
|
25
27
|
import subprocess
|
|
@@ -31,6 +33,7 @@ from collections import OrderedDict
|
|
|
31
33
|
from datetime import datetime, timedelta
|
|
32
34
|
from html.parser import HTMLParser
|
|
33
35
|
from pathlib import Path
|
|
36
|
+
from urllib.parse import quote
|
|
34
37
|
from xml.etree import ElementTree as ET
|
|
35
38
|
|
|
36
39
|
W = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
|
|
@@ -103,16 +106,52 @@ def wrap(text, bold, italic):
|
|
|
103
106
|
return lead + core + trail
|
|
104
107
|
|
|
105
108
|
|
|
109
|
+
class Raw(str):
|
|
110
|
+
"""Markdown written as is: an image link, or a tracked-change marker. Never escaped, never
|
|
111
|
+
merged with the text around it."""
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
# Where embedded images are saved: a folder beside the output file, set by main(). None when
|
|
115
|
+
# the Markdown goes to stdout, and then images are counted as dropped, as before.
|
|
116
|
+
MEDIA = {"dir": None, "link": None, "names": {}}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def save_media(z, member, alt, rep):
|
|
120
|
+
"""Copy one image out of an Office package beside the Markdown, and return the Markdown that
|
|
121
|
+
links it, or None when there is nowhere to save it or the part is missing."""
|
|
122
|
+
if not MEDIA["dir"] or member not in z.namelist():
|
|
123
|
+
rep.drop("images")
|
|
124
|
+
return None
|
|
125
|
+
name = MEDIA["names"].get(member)
|
|
126
|
+
if name is None:
|
|
127
|
+
base = re.sub(r"[^A-Za-z0-9._-]+", "-", member.rsplit("/", 1)[-1]) or "image"
|
|
128
|
+
name, k = base, 1
|
|
129
|
+
while name in MEDIA["names"].values():
|
|
130
|
+
stem, dot, ext = base.rpartition(".")
|
|
131
|
+
name = "%s-%d.%s" % (stem, k, ext) if dot else "%s-%d" % (base, k)
|
|
132
|
+
k += 1
|
|
133
|
+
os.makedirs(MEDIA["dir"], exist_ok=True)
|
|
134
|
+
with open(os.path.join(MEDIA["dir"], name), "wb") as fh:
|
|
135
|
+
fh.write(z.read(member))
|
|
136
|
+
MEDIA["names"][member] = name
|
|
137
|
+
rep.keep("images saved")
|
|
138
|
+
alt = re.sub(r"[\[\]\n]+", " ", alt or "").strip() or "image"
|
|
139
|
+
return Raw("" % (alt, MEDIA["link"], name))
|
|
140
|
+
|
|
141
|
+
|
|
106
142
|
def render_segments(segs):
|
|
107
143
|
"""segs: list of (text, bold, italic, href). Merge neighbours with equal formatting."""
|
|
108
144
|
merged = []
|
|
109
145
|
for t, b, i, h in segs:
|
|
110
|
-
if merged and merged[-1][1:] == (b, i, h):
|
|
146
|
+
if merged and merged[-1][1:] == (b, i, h) and not isinstance(t, Raw) and not isinstance(merged[-1][0], Raw):
|
|
111
147
|
merged[-1] = (merged[-1][0] + t, b, i, h)
|
|
112
148
|
else:
|
|
113
149
|
merged.append((t, b, i, h))
|
|
114
150
|
out = []
|
|
115
151
|
for t, b, i, h in merged:
|
|
152
|
+
if isinstance(t, Raw):
|
|
153
|
+
out.append(str(t))
|
|
154
|
+
continue
|
|
116
155
|
piece = wrap(md_escape(t), b, i)
|
|
117
156
|
if h:
|
|
118
157
|
piece = "[%s](%s)" % (piece.strip(), h.replace(" ", "%20").replace(")", "%29"))
|
|
@@ -156,9 +195,21 @@ def span_of(value, cap):
|
|
|
156
195
|
return min(int(v), cap) if v.isascii() and v.isdigit() and int(v) > 0 else 1
|
|
157
196
|
|
|
158
197
|
|
|
198
|
+
# Every package opened during a conversion, closed by main() when it ends: a nested function
|
|
199
|
+
# that keeps the ZipFile alive would otherwise hold the file open on Windows until garbage
|
|
200
|
+
# collection, so it couldn't be deleted or overwritten.
|
|
201
|
+
OPEN_ZIPS = []
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def close_zips():
|
|
205
|
+
while OPEN_ZIPS:
|
|
206
|
+
OPEN_ZIPS.pop().close()
|
|
207
|
+
|
|
208
|
+
|
|
159
209
|
def open_zip(path, kind):
|
|
160
210
|
try:
|
|
161
211
|
z = zipfile.ZipFile(str(path))
|
|
212
|
+
OPEN_ZIPS.append(z)
|
|
162
213
|
except zipfile.BadZipFile:
|
|
163
214
|
with open(str(path), "rb") as fh:
|
|
164
215
|
if fh.read(8) == b"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1":
|
|
@@ -256,7 +307,7 @@ def docx_to_md(path, rep):
|
|
|
256
307
|
field["instr"] += ch.text or ""
|
|
257
308
|
elif field["state"] == "instr":
|
|
258
309
|
continue
|
|
259
|
-
elif tag
|
|
310
|
+
elif tag in (W + "t", W + "delText"):
|
|
260
311
|
segs.append((ch.text or "", b, i, href or field["href"]))
|
|
261
312
|
elif tag == W + "tab":
|
|
262
313
|
segs.append((" ", False, False, None))
|
|
@@ -266,8 +317,16 @@ def docx_to_md(path, rep):
|
|
|
266
317
|
rep.drop("images")
|
|
267
318
|
elif tag == W + "drawing":
|
|
268
319
|
uris = [g.get("uri") or "" for g in ch.iter(A + "graphicData")]
|
|
269
|
-
|
|
270
|
-
|
|
320
|
+
blips = list(ch.iter(A + "blip"))
|
|
321
|
+
if blips:
|
|
322
|
+
rid = blips[0].get(R + "embed")
|
|
323
|
+
target = rels.get(rid, (None, "", ""))
|
|
324
|
+
alt = next((d.get("descr") or d.get("name") for d in ch.iter() if d.tag.endswith("}docPr")), "")
|
|
325
|
+
link = save_media(z, resolve("word", target[0]), alt, rep) if target[0] and target[2] != "External" else None
|
|
326
|
+
if link is None and not target[0]:
|
|
327
|
+
rep.drop("images")
|
|
328
|
+
elif link:
|
|
329
|
+
segs.append((link, False, False, None))
|
|
271
330
|
elif not any("chart" in u for u in uris): # charts are counted from word/charts
|
|
272
331
|
rep.drop("shapes/text boxes")
|
|
273
332
|
|
|
@@ -280,10 +339,17 @@ def docx_to_md(path, rep):
|
|
|
280
339
|
target = rels.get(rid, (None,))[0] if rid else None
|
|
281
340
|
walk(ch, target)
|
|
282
341
|
elif ch.tag == W + "ins":
|
|
283
|
-
|
|
342
|
+
# Pending, not accepted: shown in CriticMarkup so a reader sees it is a
|
|
343
|
+
# proposal, and nothing is silently settled.
|
|
344
|
+
rep.keep("tracked insertions shown as {++ ++}")
|
|
345
|
+
segs.append((Raw("{++"), False, False, None))
|
|
284
346
|
walk(ch, href)
|
|
347
|
+
segs.append((Raw("++}"), False, False, None))
|
|
285
348
|
elif ch.tag == W + "del":
|
|
286
|
-
rep.
|
|
349
|
+
rep.keep("tracked deletions shown as {-- --}")
|
|
350
|
+
segs.append((Raw("{--"), False, False, None))
|
|
351
|
+
walk(ch, href)
|
|
352
|
+
segs.append((Raw("--}"), False, False, None))
|
|
287
353
|
elif ch.tag in (W + "smartTag", W + "sdt", W + "sdtContent", W + "fldSimple"):
|
|
288
354
|
walk(ch, href)
|
|
289
355
|
walk(p, None)
|
|
@@ -571,7 +637,17 @@ def pptx_to_md(path, rep):
|
|
|
571
637
|
lines.append("")
|
|
572
638
|
lines.extend(got)
|
|
573
639
|
elif tag == P + "pic":
|
|
574
|
-
|
|
640
|
+
blip = next(iter(sp.iter(A + "blip")), None)
|
|
641
|
+
target = rels.get(blip.get(R + "embed"), (None, "", "")) if blip is not None else (None, "", "")
|
|
642
|
+
cnv = next((d for d in sp.iter() if d.tag.endswith("}cNvPr")), None)
|
|
643
|
+
alt = (cnv.get("descr") or cnv.get("name")) if cnv is not None else ""
|
|
644
|
+
link = save_media(z, resolve(base, target[0]), alt, rep) if target[0] and target[2] != "External" else None
|
|
645
|
+
if link:
|
|
646
|
+
if lines:
|
|
647
|
+
lines.append("")
|
|
648
|
+
lines.append(str(link))
|
|
649
|
+
elif not target[0]:
|
|
650
|
+
rep.drop("images")
|
|
575
651
|
elif tag == P + "graphicFrame":
|
|
576
652
|
tbl = sp.find(".//" + A + "tbl")
|
|
577
653
|
if tbl is not None:
|
|
@@ -1755,6 +1831,13 @@ LEGACY = {".doc": ".docx", ".ppt": ".pptx", ".xls": ".xlsx", ".rtf": ".docx", ".
|
|
|
1755
1831
|
|
|
1756
1832
|
|
|
1757
1833
|
def main(argv=None):
|
|
1834
|
+
try:
|
|
1835
|
+
return _main(argv)
|
|
1836
|
+
finally:
|
|
1837
|
+
close_zips() # on success, on an error exit, and on a damaged file alike
|
|
1838
|
+
|
|
1839
|
+
|
|
1840
|
+
def _main(argv=None):
|
|
1758
1841
|
ap = argparse.ArgumentParser(description="Convert a document to Markdown for another skill to read.")
|
|
1759
1842
|
ap.add_argument("input", help=".docx .pptx .xlsx .html .csv .tsv .json .txt .md .eml .msg .pdf")
|
|
1760
1843
|
ap.add_argument("-o", "--output", required=True, help="Markdown file to write, or - for stdout")
|
|
@@ -1772,6 +1855,13 @@ def main(argv=None):
|
|
|
1772
1855
|
sys.exit("error: input not found: %s" % a.input)
|
|
1773
1856
|
ext = path.suffix.lower()
|
|
1774
1857
|
rep = Report()
|
|
1858
|
+
# Embedded images go beside the Markdown, in <name>-images/; to stdout there is nowhere to
|
|
1859
|
+
# put them, so they are counted as dropped.
|
|
1860
|
+
if a.output != "-":
|
|
1861
|
+
stem = Path(a.output).stem
|
|
1862
|
+
MEDIA.update(dir=str(Path(a.output).parent / (stem + "-images")), link=quote(stem + "-images"), names={})
|
|
1863
|
+
else:
|
|
1864
|
+
MEDIA.update(dir=None, link=None, names={})
|
|
1775
1865
|
if ext in LEGACY:
|
|
1776
1866
|
sys.exit("error: %s files are not supported. Save or export it as %s and rerun%s."
|
|
1777
1867
|
% (ext, LEGACY[ext], " (on macOS: textutil -convert docx <file>)"
|
|
@@ -1797,6 +1887,9 @@ def main(argv=None):
|
|
|
1797
1887
|
|
|
1798
1888
|
if not md.strip():
|
|
1799
1889
|
rep.notes.append("the conversion produced no text")
|
|
1890
|
+
if any(k.startswith("tracked") for k in rep.kept):
|
|
1891
|
+
rep.notes.append("tracked changes are pending, not accepted: {++added++} and {--removed--} mark them. "
|
|
1892
|
+
"Accept or reject them in Word to settle the text")
|
|
1800
1893
|
if a.output == "-":
|
|
1801
1894
|
sys.stdout.write(md)
|
|
1802
1895
|
else:
|
|
@@ -37,7 +37,8 @@ sure nobody overwrites the wrong page. Runbooks often come from `runbook-generat
|
|
|
37
37
|
- **Two images with the same file name** (`before/screen.png`, `after/screen.png`) become one
|
|
38
38
|
attachment, so both show the same picture. Rename one (`screen-before.png`).
|
|
39
39
|
- **Footnotes are dropped.** Move the text into the sentence or a "Notes" section.
|
|
40
|
-
- **Mermaid shows as source.** Render it to PNG with
|
|
40
|
+
- **Mermaid shows as source.** Render it to PNG with the Mermaid CLI
|
|
41
|
+
(`npx -y @mermaid-js/mermaid-cli`) and embed the PNG.
|
|
41
42
|
- **A front-matter `title:` wins over the `#` heading** for a new page. An update keeps the
|
|
42
43
|
page's current title, so when the Markdown's title differs (`Deploy checklist v2 (draft)`),
|
|
43
44
|
say so and rename only if asked.
|
|
@@ -124,7 +125,6 @@ Markdown file to convert` and write nothing.
|
|
|
124
125
|
## When NOT to use this skill
|
|
125
126
|
|
|
126
127
|
- ❌ A Word file to edit with tracked changes; use `md-to-docx`
|
|
127
|
-
- ❌ A standalone web page or an HTML attachment for email; use `md-to-html`
|
|
128
128
|
- ❌ Jira epics and issues from a PRD; use `tracker-brief-sync`
|
|
129
129
|
- ❌ Writing the runbook itself; use `runbook-generator`, then convert
|
|
130
130
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "md-to-confluence",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Turn a Markdown runbook, design note or guide into a Confluence page: storage-format XHTML with real code blocks, tables, tasks, info and warning panels, images as attachments and an optional contents macro, a warning for everything dropped, and an optional publish that first shows which page it will create or overwrite and at what version, refuses stale or wrong-space overwrites, and takes credentials only from the environment. Use when the user says \"put this in Confluence\", \"publish this markdown to the wiki\", \"update the Confluence page with this\", \"convert to Confluence storage format\", or names a Confluence space for a Markdown file.",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": {
|
|
@@ -17,18 +17,11 @@
|
|
|
17
17
|
},
|
|
18
18
|
"related": [
|
|
19
19
|
"md-to-docx",
|
|
20
|
-
"md-to-html",
|
|
21
|
-
"mermaid-render",
|
|
22
20
|
"runbook-generator",
|
|
23
21
|
"tracker-brief-sync"
|
|
24
22
|
],
|
|
25
23
|
"handoff": [
|
|
26
|
-
|
|
27
|
-
"to": "mermaid-render",
|
|
28
|
-
"when": "the Markdown has Mermaid diagrams",
|
|
29
|
-
"purpose": "Render each diagram to PNG so it can go on the page as an attachment instead of showing as source code.",
|
|
30
|
-
"fallback": "If mermaid-render is absent, leave the diagram as a code block and tell the user it shows as text until someone adds an image or a diagram app."
|
|
31
|
-
}
|
|
24
|
+
|
|
32
25
|
],
|
|
33
26
|
"tags": [
|
|
34
27
|
"confluence",
|
|
@@ -31,8 +31,8 @@ from `guide-builder` or
|
|
|
31
31
|
Word's navigation pane.
|
|
32
32
|
- Raw HTML, footnotes and Mermaid blocks don't convert. Rewrite an HTML table as a pipe table,
|
|
33
33
|
move a footnote's text into the sentence or a "Notes" section, and render each diagram to PNG
|
|
34
|
-
with `mermaid-
|
|
35
|
-
|
|
34
|
+
with the Mermaid CLI (`npx -y @mermaid-js/mermaid-cli -i diagram.mmd -o diagram.png`; it needs Node.js), then embed the PNG as a Markdown image with
|
|
35
|
+
alt text.
|
|
36
36
|
- Lists nested deeper than two levels are flattened. Restructure them into a sub-heading
|
|
37
37
|
and a list.
|
|
38
38
|
- Image paths must be relative to the Markdown file and point at PNG or JPEG files.
|
|
@@ -106,8 +106,7 @@ or page size uses the defaults, with an `[assumption]` line at the top of your r
|
|
|
106
106
|
|
|
107
107
|
## When NOT to use this skill
|
|
108
108
|
|
|
109
|
-
- ❌ Slides; use `
|
|
110
|
-
- ❌ A web page or a file to open in a browser; use `md-to-html`
|
|
109
|
+
- ❌ Slides; use `md-to-pptx`
|
|
111
110
|
- ❌ The other direction, a Word file or PDF back to Markdown; use `file-to-markdown`
|
|
112
111
|
- ❌ Tables that need to be sorted, filtered or summed; use `md-to-xlsx`
|
|
113
112
|
- ❌ Writing the document itself; draft it first with `guide-builder` or the skill for that document, then convert
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"prompt": "Northwind Legal wants our vendor onboarding policy as a Word doc so they can track changes. It's in docs/vendor-onboarding.md: a # title, ## sections, a numbered approval process with sub-steps, a pipe table of approval limits ($5,000 / $50,000 / unlimited), a footnote citing the finance policy, and a Mermaid flowchart of the approval path. Use ./brand/brand.json and A4 paper.",
|
|
7
7
|
"assertions": [
|
|
8
8
|
"Runs md_to_docx.py with --brand ./brand/brand.json and --page a4, writing a .docx",
|
|
9
|
-
"Deals with the Mermaid flowchart before converting: renders it to PNG with
|
|
9
|
+
"Deals with the Mermaid flowchart before converting: renders it to PNG with the Mermaid CLI and embeds it, or says plainly that it stays as code",
|
|
10
10
|
"Moves the footnote's text into the body or a Notes section instead of letting it drop silently",
|
|
11
11
|
"Reports every WARN line the script printed, each with what was done about it",
|
|
12
12
|
"Keeps the approval limits ($5,000 / $50,000 / unlimited) and every other fact exactly as in the source",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "brand-kit output.
|
|
2
|
+
"$comment": "brand-kit output. md-to-docx and md-to-pptx read this file; any field left out is asked for or defaulted by them. Paths are relative to this file. Every value carries where it came from in `sources`.",
|
|
3
3
|
"name": "Northwind Health",
|
|
4
4
|
"tagline": "Care that comes to you",
|
|
5
5
|
"logo": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "md-to-docx",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Turn a Markdown draft into a Word document (.docx) that someone outside engineering can open, edit and track changes in, with real Heading styles so the navigation pane and table of contents work, live hyperlinks, numbered and bulleted lists, tables, code blocks, embedded images and optional brand fonts and colours, and a warning for everything that could not be carried over. Use when the user wants a Markdown file as a Word doc, says \"send this as a .docx\", \"convert to Word\", \"legal needs it in Word\", or \"make this editable for the client\".",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": {
|
|
@@ -13,22 +13,15 @@
|
|
|
13
13
|
},
|
|
14
14
|
"related": [
|
|
15
15
|
"brand-kit",
|
|
16
|
-
"deck-builder",
|
|
17
16
|
"file-to-markdown",
|
|
18
17
|
"guide-builder",
|
|
19
|
-
"md-to-html",
|
|
20
18
|
"md-to-xlsx",
|
|
21
|
-
"mermaid-render",
|
|
22
19
|
"output-hygiene",
|
|
23
|
-
"release-notes"
|
|
20
|
+
"release-notes",
|
|
21
|
+
"md-to-pptx"
|
|
24
22
|
],
|
|
25
23
|
"handoff": [
|
|
26
|
-
|
|
27
|
-
"to": "mermaid-render",
|
|
28
|
-
"when": "the Markdown contains Mermaid diagram blocks",
|
|
29
|
-
"purpose": "Render each diagram to PNG so it can be embedded in the Word file instead of appearing as code.",
|
|
30
|
-
"fallback": "If mermaid-render is absent, leave the block as code, tell the user the diagram did not convert, and suggest exporting it to PNG from mermaid.live."
|
|
31
|
-
},
|
|
24
|
+
|
|
32
25
|
{
|
|
33
26
|
"to": "output-hygiene",
|
|
34
27
|
"when": "the Markdown was written by an agent and is going to someone outside the team",
|
|
@@ -79,7 +79,7 @@ embedded: a reader without the font sees Word's substitute. Brand fonts that are
|
|
|
79
79
|
| Raw HTML blocks | No dependable mapping from arbitrary HTML to Word | Rewrite as Markdown; HTML tables as pipe tables |
|
|
80
80
|
| Inline HTML tags | Same | The text is kept; `<br>` becomes a line break |
|
|
81
81
|
| Footnotes `[^1]` | Word footnotes need a separate part and are rarely worth it in a converted draft | Fold the note into the sentence, or a "Notes" section |
|
|
82
|
-
| Mermaid blocks | Rendering needs a browser engine | Render to PNG with mermaid-
|
|
82
|
+
| Mermaid blocks | Rendering needs a browser engine | Render to PNG with the Mermaid CLI (`npx -y @mermaid-js/mermaid-cli`), then embed the image |
|
|
83
83
|
| Nesting past 2 levels | Flattened to keep the document readable | Split with a sub-heading |
|
|
84
84
|
| YAML front matter | Not content | Its `title:` is used as the document title |
|
|
85
85
|
|
|
@@ -210,7 +210,7 @@ def parse_blocks(lines, base_line, refs):
|
|
|
210
210
|
start = ln
|
|
211
211
|
while i < n:
|
|
212
212
|
l2 = expand_tabs(lines[i])
|
|
213
|
-
s2 = l2.lstrip(
|
|
213
|
+
s2 = l2.lstrip() # the same whitespace the test above strips, or a line led by \v never advances
|
|
214
214
|
if s2.startswith(">"):
|
|
215
215
|
s2 = s2[1:]
|
|
216
216
|
if s2.startswith(" "):
|
|
@@ -9,7 +9,7 @@ This skill turns a Markdown document into a `.pptx` mechanically: the headings d
|
|
|
9
9
|
slides and the words stay the user's own. A stdlib Python script writes the PowerPoint file,
|
|
10
10
|
checks it, and prints an outline of the slides. The agent's job is the part around it: get the
|
|
11
11
|
Markdown into a shape that converts well, run the script, read what it reports, and tell the
|
|
12
|
-
user what changed.
|
|
12
|
+
user what changed. Planning what slides should
|
|
13
13
|
say is `slide-outliner`.
|
|
14
14
|
|
|
15
15
|
## How to respond
|
|
@@ -35,8 +35,8 @@ say is `slide-outliner`.
|
|
|
35
35
|
`Notes:` paragraph stays on the slide as text. Convert those paragraphs into comments only
|
|
36
36
|
when the user said they are speaker notes ("the Notes: bits are what I'll say").
|
|
37
37
|
- **What doesn't convert:** rewrite an HTML table as a pipe table, fold a footnote's text into
|
|
38
|
-
its sentence, and render a Mermaid block to PNG with
|
|
39
|
-
mermaid-cli), then embed it as an image. Remote images are not fetched. Ask for a local copy,
|
|
38
|
+
its sentence, and render a Mermaid block to PNG with the Mermaid CLI
|
|
39
|
+
(`npx -y @mermaid-js/mermaid-cli`; it needs Node.js), then embed it as an image. Remote images are not fetched. Ask for a local copy,
|
|
40
40
|
or leave the alt text and say so.
|
|
41
41
|
- **Facts are untouched.** Same numbers, names, dates and order. Don't renumber a list that
|
|
42
42
|
skips a number. Report it (step 4).
|
|
@@ -127,10 +127,8 @@ treating `Notes:` paragraphs as slide text is an `[assumption]` stated at the to
|
|
|
127
127
|
|
|
128
128
|
## When NOT to use this skill
|
|
129
129
|
|
|
130
|
-
- ❌ Designing a persuasive deck for an audience, with charts, layouts and a narrative; use `deck-builder`
|
|
131
130
|
- ❌ Planning what each slide should say before any document exists; use `slide-outliner`
|
|
132
131
|
- ❌ A Word document to edit and track changes in; use `md-to-docx`
|
|
133
|
-
- ❌ A web page or a file to open in a browser; use `md-to-html`
|
|
134
132
|
- ❌ A `.pptx` back to Markdown; use `file-to-markdown`
|
|
135
133
|
|
|
136
134
|
## Anti-patterns to avoid
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "md-to-pptx",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Turn an existing Markdown document (a status report, runbook, review or notes) into a PowerPoint deck (.pptx) that opens without a repair prompt, with nothing to install. Each heading becomes a slide, lists keep their nesting, tables become real PowerPoint tables, images are embedded, and comments become speaker notes. A section too long for one slide is split onto \"continued\" slides instead of shrinking the text, and the reply names every split, everything dropped, and any speaker note that would go out with the file. Use when the user says \"turn this markdown into slides\", \"make this report a PowerPoint\", \"convert the .md to pptx\", \"I need this as a deck for Thursday\", or \"export these notes to PowerPoint\".",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": {
|
|
@@ -13,26 +13,13 @@
|
|
|
13
13
|
},
|
|
14
14
|
"related": [
|
|
15
15
|
"brand-kit",
|
|
16
|
-
"deck-builder",
|
|
17
16
|
"file-to-markdown",
|
|
18
17
|
"md-to-docx",
|
|
19
|
-
"md-to-html",
|
|
20
|
-
"mermaid-render",
|
|
21
18
|
"slide-outliner"
|
|
22
19
|
],
|
|
23
20
|
"handoff": [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"when": "the Markdown contains Mermaid diagram blocks",
|
|
27
|
-
"purpose": "Render each diagram to PNG so it is embedded on its slide instead of appearing as code.",
|
|
28
|
-
"fallback": "If mermaid-render is absent, leave the block as code, tell the user the diagram did not convert, and suggest exporting it to PNG from mermaid.live."
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"to": "deck-builder",
|
|
32
|
-
"when": "the user wants the deck redesigned for an audience (charts, layouts, a narrative) rather than converted as written",
|
|
33
|
-
"purpose": "Design a persuasive deck from the content instead of mapping headings to slides.",
|
|
34
|
-
"fallback": "If deck-builder is absent, deliver the converted deck and say in one line that it follows the document's structure and has not been redesigned."
|
|
35
|
-
}
|
|
21
|
+
|
|
22
|
+
|
|
36
23
|
],
|
|
37
24
|
"tags": [
|
|
38
25
|
"powerpoint",
|
|
@@ -249,7 +249,7 @@ def parse_blocks(lines, base_line, refs):
|
|
|
249
249
|
start = ln
|
|
250
250
|
while i < n:
|
|
251
251
|
l2 = expand_tabs(lines[i])
|
|
252
|
-
s2 = l2.lstrip(
|
|
252
|
+
s2 = l2.lstrip() # the same whitespace the test above strips, or a line led by \v never advances
|
|
253
253
|
if s2.startswith(">"):
|
|
254
254
|
s2 = s2[1:]
|
|
255
255
|
if s2.startswith(" "):
|
|
@@ -107,7 +107,7 @@ JSON strings stay text except ISO dates, because whoever produced the JSON chose
|
|
|
107
107
|
|
|
108
108
|
- ❌ A document with a few tables in it, to be read rather than calculated; use `md-to-docx`
|
|
109
109
|
- ❌ An Excel file back to Markdown or CSV; use `file-to-markdown`
|
|
110
|
-
- ❌
|
|
110
|
+
- ❌ A slide of numbers for a meeting; put the table in the Markdown and use `md-to-pptx`
|
|
111
111
|
- ❌ Building a financial model with formulas, scenarios and linked sheets. This converts data; it doesn't design models.
|
|
112
112
|
|
|
113
113
|
## Anti-patterns to avoid
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: brief-intake
|
|
3
|
-
description: Turn raw mess — a Slack thread, meeting transcript, Jira ticket, half-written Notion page, email chain, or paragraph of free-form context — into a structured brief that the downstream skill (adr-generator, design-doc, runbook-generator, exec-summary,
|
|
3
|
+
description: Turn raw mess — a Slack thread, meeting transcript, Jira ticket, half-written Notion page, email chain, or paragraph of free-form context — into a structured brief that the downstream skill (adr-generator, design-doc, runbook-generator, exec-summary, slide-outliner) can consume without further intake. Use whenever the user has unstructured source material and is about to invoke another skilldrop skill, or when a draft is missing the load-bearing context the next step will need.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# brief-intake
|
|
@@ -18,7 +18,7 @@ You help the user (or the next skill in the chain) absorb raw unstructured input
|
|
|
18
18
|
| `runbook-generator` | "runbook", "on-call doc", "operational doc", "prod-readiness" |
|
|
19
19
|
| _(tech comparison)_ | "compare X vs Y", "vendor selection", "tech selection" |
|
|
20
20
|
| `exec-summary` | "exec summary", "1-pager for the VP", "board update" |
|
|
21
|
-
| `
|
|
21
|
+
| `slide-outliner` | "deck", "slides", "presentation", "pitch", "review meeting" |
|
|
22
22
|
| `decision-log` | "decisions and action items", "follow-ups from the meeting" |
|
|
23
23
|
| _(generic)_ | None of the above — emit the generic brief and let the user pick later |
|
|
24
24
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brief-intake",
|
|
3
3
|
"version": "0.1.2",
|
|
4
|
-
"description": "Turn raw mess — a Slack thread, meeting transcript, Jira ticket, half-written Notion page, email chain, or paragraph of free-form context — into a structured brief that the downstream skill (adr-generator, design-doc, runbook-generator, exec-summary,
|
|
4
|
+
"description": "Turn raw mess — a Slack thread, meeting transcript, Jira ticket, half-written Notion page, email chain, or paragraph of free-form context — into a structured brief that the downstream skill (adr-generator, design-doc, runbook-generator, exec-summary, slide-outliner) can consume without further intake. Use whenever the user has unstructured source material and is about to invoke another skilldrop skill, or when a draft is missing the load-bearing context the next step will need.",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": { "npm": [], "pip": [] },
|
|
7
7
|
"env": { "required": [], "optional": [] },
|
|
8
|
-
"related": ["adr-generator", "decision-log", "
|
|
8
|
+
"related": ["adr-generator", "decision-log", "design-doc", "exec-summary", "runbook-generator", "slide-outliner"],
|
|
9
9
|
"tags": ["intake", "brief", "extraction", "preprocessing", "pipeline"],
|
|
10
10
|
"model": { "tier": "standard", "rationale": "Extraction + [explicit]/[implied]/[inferred] tagging. The tagging needs care — above haiku, below opus." }
|
|
11
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Brief: Deck
|
|
2
2
|
|
|
3
|
-
> Target downstream skills: `slide-outliner`
|
|
3
|
+
> Target downstream skills: `slide-outliner` (and `audience-profile` for the structural rules)
|
|
4
4
|
|
|
5
5
|
## Topic / working title
|
|
6
6
|
{One line} [explicit|implied|inferred|missing]
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
---
|
|
40
40
|
|
|
41
41
|
## 🚩 Missing for downstream
|
|
42
|
-
- {e.g. "Audience not specified —
|
|
43
|
-
- {e.g. "No palette — deck
|
|
42
|
+
- {e.g. "Audience not specified — the outline can't be sized"}
|
|
43
|
+
- {e.g. "No brand or palette — the deck will use the default look"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Rubric: Slide Deck / Outline
|
|
2
2
|
|
|
3
|
-
Mirrors `slide-outliner`
|
|
3
|
+
Mirrors the `slide-outliner` quality bar. Apply to either a finished deck (read titles + speaker notes) or an outline.
|
|
4
4
|
|
|
5
5
|
## Blockers
|
|
6
6
|
- **Audience is explicit or obvious from the deck.** Same content for execs vs engineers is a different deck — if you can't tell which one this is, that's the blocker.
|
package/packs/design/pack.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "On-brand visual work: capture a brand once
|
|
2
|
+
"description": "On-brand visual work: capture a brand once as a brand.json the Word and PowerPoint converters apply, and plan a deck slide by slide for its audience.",
|
|
3
3
|
"display_name": "Design",
|
|
4
|
-
"keywords": ["brand", "deck", "
|
|
4
|
+
"keywords": ["brand", "deck", "outline", "presentation", "logo"],
|
|
5
5
|
"links": {
|
|
6
6
|
"documentation": "https://sananthanarayan.github.io/skilldrop/packs/design/"
|
|
7
7
|
},
|
|
@@ -13,18 +13,18 @@
|
|
|
13
13
|
"first-value": {
|
|
14
14
|
"audience-posture": "non-technical",
|
|
15
15
|
"prerequisites": ["Your logo as a PNG file, and your brand colours if you know them"],
|
|
16
|
-
"starter-task": "Capture your brand once, then
|
|
17
|
-
"starter-prompt": "Set up our brand kit from this logo (./brand/logo.png) and these colours: #0E5A46, #F2A541. Then
|
|
18
|
-
"verification": "brand-kit writes brand.json and a one-page BRAND.md with contrast checked, and
|
|
19
|
-
"recovery": "If
|
|
16
|
+
"starter-task": "Capture your brand once, then outline a deck for it",
|
|
17
|
+
"starter-prompt": "Set up our brand kit from this logo (./brand/logo.png) and these colours: #0E5A46, #F2A541. Then outline a five-slide deck from ./notes/q3-update.md for Thursday's team meeting.",
|
|
18
|
+
"verification": "brand-kit writes brand.json and a one-page BRAND.md with contrast checked, and slide-outliner returns a slide-by-slide outline with takeaway titles and speaker notes, sized to the time.",
|
|
19
|
+
"recovery": "If brand-kit does not activate, ask for it by name (\"use brand-kit\"). To turn the outline into a .pptx in your brand, the converters pack's md-to-pptx takes the same brand.json with --brand."
|
|
20
20
|
},
|
|
21
21
|
"requires": ["core"],
|
|
22
22
|
"journey": {
|
|
23
|
-
"when": "You need a deck or
|
|
23
|
+
"when": "You need a deck or document in your own branding and do not want to answer the brand questions every time.",
|
|
24
24
|
"you_bring": [
|
|
25
25
|
"your logo as a PNG, and a white version if you have one",
|
|
26
26
|
"brand colours, fonts or a PowerPoint template, if you know them",
|
|
27
|
-
"the content: the doc or points for the deck
|
|
27
|
+
"the content: the doc or points for the deck",
|
|
28
28
|
"the audience and how long you have to present"
|
|
29
29
|
],
|
|
30
30
|
"steps": [
|
|
@@ -38,23 +38,13 @@
|
|
|
38
38
|
"you_do": "Give it the content, the audience and the time slot.",
|
|
39
39
|
"you_get": "A slide-by-slide outline with takeaway titles, key points, speaker notes, backup slides for likely questions, and a slide-count check against the time."
|
|
40
40
|
},
|
|
41
|
-
{
|
|
42
|
-
"skill": "deck-builder",
|
|
43
|
-
"you_do": "Hand it the outline, the audience and your brand.json.",
|
|
44
|
-
"you_get": "An editable .pptx in your brand, with charts, tables and images where the content calls for them."
|
|
45
|
-
},
|
|
46
41
|
{
|
|
47
42
|
"skill": "doc-critique",
|
|
48
|
-
"you_do": "Run it on the
|
|
43
|
+
"you_do": "Run it on the outline against the deck rubric.",
|
|
49
44
|
"you_get": "A verdict and severity-tagged findings with a fix for each.",
|
|
50
|
-
"decide": "
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"skill": "marketing-flyer",
|
|
54
|
-
"you_do": "If you also need a flyer, give it the event facts and the same brand.json.",
|
|
55
|
-
"you_get": "A print-ready flyer.html with one call to action and only the facts you gave it, which you can save to PDF."
|
|
45
|
+
"decide": "Build the deck from the outline, apply the changes, or rework it."
|
|
56
46
|
}
|
|
57
47
|
],
|
|
58
|
-
"you_end_with": "A reusable brand kit
|
|
48
|
+
"you_end_with": "A reusable brand kit and a reviewed outline, ready to become an on-brand .pptx with md-to-pptx from the converters pack."
|
|
59
49
|
}
|
|
60
50
|
}
|
|
@@ -7,9 +7,8 @@ description: Capture a brand once as a reusable brand.json — logo files (and a
|
|
|
7
7
|
|
|
8
8
|
You turn whatever the user has about their brand (logo files, a guidelines PDF, a website, a
|
|
9
9
|
few hex codes, "we use green") into one `brand.json` that other skills build from:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
nobody answers the same questions for every deck, and the deck and the flyer match.
|
|
10
|
+
the Word and PowerPoint converters, `md-to-docx` and `md-to-pptx`. Capturing the brand once means nobody answers the same questions for every deck,
|
|
11
|
+
and every document matches.
|
|
13
12
|
|
|
14
13
|
## How to respond
|
|
15
14
|
|
|
@@ -58,11 +57,10 @@ nobody answers the same questions for every deck, and the deck and the flyer mat
|
|
|
58
57
|
It fails on a malformed hex code, text-on-background contrast below 4.5:1, a missing logo
|
|
59
58
|
file or template. It warns when white text on the primary is hard to read, when the accent
|
|
60
59
|
is too light for text, when a logo is SVG or EPS, or when fonts aren't set. Fix the
|
|
61
|
-
failures. Report each warning with what it means for the deck or
|
|
60
|
+
failures. Report each warning with what it means for the deck or document.
|
|
62
61
|
|
|
63
|
-
6. **Hand off.** Tell the user the path to `brand.json
|
|
64
|
-
|
|
65
|
-
`brand` field.
|
|
62
|
+
6. **Hand off.** Tell the user the path to `brand.json`, and that the Word and PowerPoint
|
|
63
|
+
converters apply it with `--brand brand.json`.
|
|
66
64
|
|
|
67
65
|
**Non-interactive runs** (subagent, CI, headless): never invent a brand colour, font or logo.
|
|
68
66
|
Use only what the input supplies, tag derived colours `[inferred]`, and list missing fields
|
|
@@ -93,7 +91,7 @@ brand name and either a logo file or one brand colour`.
|
|
|
93
91
|
## When NOT to use this skill
|
|
94
92
|
|
|
95
93
|
- ❌ Designing a new brand from scratch: this captures a brand, it doesn't invent one
|
|
96
|
-
- ❌ Building the deck
|
|
94
|
+
- ❌ Building the deck itself; convert its Markdown with `md-to-pptx`
|
|
97
95
|
- ❌ A one-off document where the user only wants the default look
|
|
98
96
|
|
|
99
97
|
## Anti-patterns to avoid
|