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
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# modules/orders-db/variables.tf
|
|
2
|
+
|
|
3
|
+
variable "environment" {
|
|
4
|
+
type = string
|
|
5
|
+
description = "Environment name, e.g. staging or prod."
|
|
6
|
+
validation {
|
|
7
|
+
condition = contains(["staging", "prod"], var.environment)
|
|
8
|
+
error_message = "environment must be staging or prod."
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
variable "vpc_id" {
|
|
13
|
+
type = string
|
|
14
|
+
description = "VPC the database runs in."
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
variable "vpc_cidr" {
|
|
18
|
+
type = string
|
|
19
|
+
description = "CIDR of the VPC; the only range allowed to reach Postgres."
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
variable "subnet_ids" {
|
|
23
|
+
type = list(string)
|
|
24
|
+
description = "Private subnet IDs for the DB subnet group."
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
variable "instance_class" {
|
|
28
|
+
type = string
|
|
29
|
+
description = "Instance class for the primary."
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
variable "replica_instance_class" {
|
|
33
|
+
type = string
|
|
34
|
+
description = "Instance class for the reporting read replica."
|
|
35
|
+
default = "db.r7g.large"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
variable "kms_key_arn" {
|
|
39
|
+
type = string
|
|
40
|
+
description = "KMS key used to encrypt storage."
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
variable "tags" {
|
|
44
|
+
type = map(string)
|
|
45
|
+
description = "Tags merged onto every resource."
|
|
46
|
+
default = {}
|
|
47
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "RFC-0069. A described need to an apply a person approved. The plan review is the gate because a module can be secure and still produce a plan that destroys a database; the apply check is a second gate because the plan applied must be the plan reviewed, and only the person running apply can confirm that.",
|
|
3
|
+
"name": "provision",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Take an infrastructure change from a described need to a Terraform apply a person approved: a module with secure defaults, a review of the real plan that names every destroy, replace, widening and out-of-scope change, and a check right before apply that the plan being applied is the one reviewed, with a gate that sends the module back when the plan would destroy state or widen access unasked. Use when the user says \"write the terraform and check it before we apply\", \"provision this safely\", \"run the provision loop\", or wants new infrastructure from module to apply in one pass.",
|
|
6
|
+
"entrypoint": "LOOP.md",
|
|
7
|
+
"kind": "loop",
|
|
8
|
+
"cap": 3,
|
|
9
|
+
"stages": [
|
|
10
|
+
{
|
|
11
|
+
"id": "module",
|
|
12
|
+
"type": "generate",
|
|
13
|
+
"intent": "Write or change the module for the stated need, with typed variables, secure defaults and the intended scope written down as resource addresses.",
|
|
14
|
+
"skills": ["terraform-module"]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "plan",
|
|
18
|
+
"type": "verify",
|
|
19
|
+
"intent": "Review the real plan from a saved planfile against the stated scope: every destroy, replace, stateful change, access widening and drift.",
|
|
20
|
+
"skills": ["terraform-plan-review"],
|
|
21
|
+
"gate": {
|
|
22
|
+
"id": "G13",
|
|
23
|
+
"kind": "review",
|
|
24
|
+
"verdicts": ["PROCEED", "PROCEED WITH CONDITIONS", "REVISE", "RECONSIDER", "BLOCKED"],
|
|
25
|
+
"revise_to": "module"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "apply",
|
|
30
|
+
"type": "gate",
|
|
31
|
+
"intent": "Right before apply, confirm the planfile being applied is the one reviewed, with the same resource changes, and the person running apply approves it.",
|
|
32
|
+
"skills": ["terraform-plan-review"],
|
|
33
|
+
"gate": {
|
|
34
|
+
"id": "G13.1",
|
|
35
|
+
"kind": "human",
|
|
36
|
+
"verdicts": ["PROCEED", "REVISE", "BLOCKED"],
|
|
37
|
+
"revise_to": "plan"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -144,7 +144,7 @@ don't cite them in the first place, and read the page before it leaves the team.
|
|
|
144
144
|
|
|
145
145
|
- ❌ A Mermaid, PlantUML or C4 diagram to paste into a doc — use `architecture-diagrams`
|
|
146
146
|
- ❌ An as-is architecture write-up in C4 levels from infrastructure files — use `reverse-architecture`
|
|
147
|
-
- ❌ Fixing or rendering an existing Mermaid diagram
|
|
147
|
+
- ❌ Fixing or rendering an existing Mermaid diagram; the agent does that well on its own, with `npx @mermaid-js/mermaid-cli` for images
|
|
148
148
|
- ❌ Charts of numbers, dashboards or metrics — this draws structure, not data
|
|
149
149
|
|
|
150
150
|
## Anti-patterns to avoid
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "interactive-diagram",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Turn a codebase, a system description, a process or a database schema into one self-contained interactive HTML diagram (architecture, workflow, data flow, lifecycle, ERD, sequence, class, tree, timeline or waterfall) where every box and arrow cites the file and line or the words it came from, anything inferred is drawn dashed as an assumption, and each cited line is checked against the repository before the page is written. Laid out automatically, opens offline with no CDN, and exports SVG, PNG and Mermaid. Use when the user asks to \"visualize\", \"map\" or \"make an interactive diagram of\" a repo, a request path, a pipeline, an approval process, a set of tables, an incident's events or a slow trace, or wants a diagram they can click through and share as one file.",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": {
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
},
|
|
14
14
|
"related": [
|
|
15
15
|
"architecture-diagrams",
|
|
16
|
-
"mermaid-render",
|
|
17
16
|
"reverse-architecture"
|
|
18
17
|
],
|
|
19
18
|
"tags": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: audience-profile
|
|
3
|
-
description: Translate an audience type (exec, board, technical, sales, investor, internal, partner, customer) into structural rules — slide count, density, tone, must-have sections, things to avoid. Reusable across
|
|
3
|
+
description: Translate an audience type (exec, board, technical, sales, investor, internal, partner, customer) into structural rules — slide count, density, tone, must-have sections, things to avoid. Reusable across slide-outliner and exec-summary. Use whenever a stakeholder communication deliverable is being designed for a specific audience.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# audience-profile
|
|
@@ -40,7 +40,7 @@ You help the user (or another skill) pick the right *shape* for a communication
|
|
|
40
40
|
|
|
41
41
|
3. **Be opinionated.** This skill exists to *make decisions* for the user. If they push back, fine — but don't hedge in the initial response. "Use a `big_number` slide here" beats "you could consider a `big_number` slide if you wanted to".
|
|
42
42
|
|
|
43
|
-
4. **Hand off cleanly.** When called from `
|
|
43
|
+
4. **Hand off cleanly.** When called from `slide-outliner` or `exec-summary`, the profile is *input* to that skill — don't try to build the artifact yourself.
|
|
44
44
|
|
|
45
45
|
## When to use this skill
|
|
46
46
|
|
|
@@ -69,6 +69,6 @@ You help the user (or another skill) pick the right *shape* for a communication
|
|
|
69
69
|
- ❌ **Profiling the most senior title in the room instead of the actual decision-maker.** If the VP is there to rubber-stamp what their staff engineer recommends, the staff engineer is the audience. Profile who the deliverable must *convince*, not who has the grandest title.
|
|
70
70
|
- ❌ **Defaulting a mixed room to the most technical archetype** because the deck "needs the detail". A non-technical attendee lost on slide 3 is lost for the whole meeting; resolve to the least-technical archetype and push depth to an appendix.
|
|
71
71
|
- ❌ **Hedged, generic output.** "Know your audience and keep it appropriately concise" is a fortune cookie, not a profile. Emit the numbers: slide count, bullet density, the must-have sections in order.
|
|
72
|
-
- ❌ **Building the artifact instead of the profile.** When called from `
|
|
72
|
+
- ❌ **Building the artifact instead of the profile.** When called from `slide-outliner` or `exec-summary`, returning slides instead of the ruleset — the profile is *input* to those skills, not a substitute for them.
|
|
73
73
|
- ❌ **Over-fitting to one named person's quirks** ("Dana hates animations") instead of the role. Profiles are reusable because they're keyed to the archetype; bake in one individual's preferences and the profile dies when Dana changes jobs. Note the personal quirk as a one-line override, keep the archetype intact.
|
|
74
74
|
- ❌ **Showing the machinery.** The reply and the artifact are for the person who asked. Don't mention this skill, its files, templates, caps or internal terms, or that the run is non-interactive. Name another skill once, at the end, as a suggested next step, never inside the artifact.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "audience-profile",
|
|
3
3
|
"version": "0.1.1",
|
|
4
|
-
"description": "Translate an audience type (exec, board, technical, sales, investor, internal, partner, customer) into structural rules — slide count, density, tone, must-have sections, things to avoid. Reusable across
|
|
4
|
+
"description": "Translate an audience type (exec, board, technical, sales, investor, internal, partner, customer) into structural rules — slide count, density, tone, must-have sections, things to avoid. Reusable across slide-outliner and exec-summary. Use whenever a stakeholder communication deliverable is being designed for a specific audience.",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": { "npm": [], "pip": [] },
|
|
7
7
|
"env": { "required": [], "optional": [] },
|
|
8
|
-
"related": ["
|
|
8
|
+
"related": ["slide-outliner", "exec-summary"],
|
|
9
9
|
"tags": ["audience", "stakeholder-communication", "reference"],
|
|
10
10
|
"model": { "tier": "light", "rationale": "Maps fixed audience archetypes to structural rules. Lookup against a rubric, not synthesis." }
|
|
11
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Audience archetype matrix
|
|
2
2
|
|
|
3
|
-
Eight archetypes covering the common stakeholder-communication situations an architect runs into. Each has rules dense enough to drive concrete structural choices in `
|
|
3
|
+
Eight archetypes covering the common stakeholder-communication situations an architect runs into. Each has rules dense enough to drive concrete structural choices in `slide-outliner` or `exec-summary`.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: md-to-html
|
|
3
|
-
description: Turn a Markdown draft into one self-contained, print-friendly HTML file that survives being emailed or attached, with headings that have anchor links, tables, code, quotes, an optional table of contents, local images embedded, brand colours and fonts from a brand.json, Mermaid diagrams kept as text or drawn from a pinned CDN, and raw HTML escaped so nothing in the source runs. Use when the user wants Markdown "as a web page", "as an HTML file I can send", "something people can open in a browser and print", or says "convert this to HTML".
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# md-to-html
|
|
7
|
-
|
|
8
|
-
You turn a Markdown file into a single `.html` file that anyone can open in a browser, print
|
|
9
|
-
to PDF, or attach to an email, with nothing else to send alongside it. A stdlib script does the
|
|
10
|
-
conversion. Your job is to pick the options, run it, and tell the user exactly what the file
|
|
11
|
-
depends on (network for diagrams, remote images) and what it left out. Drafts often come from
|
|
12
|
-
`guide-builder`; the brand comes from `brand-kit`.
|
|
13
|
-
|
|
14
|
-
## How to respond
|
|
15
|
-
|
|
16
|
-
**Four rules come before the steps and outrank them:**
|
|
17
|
-
|
|
18
|
-
- **Answer what was asked, first.** Open with the answer, the decision or the artifact, in plain words. Scores, matrices, frameworks and tags come after it, and anything that doesn't change the answer is cut.
|
|
19
|
-
- **Use only what you were given.** Don't add facts, names, numbers, incidents, history, steps or sections the input doesn't contain. What you need and don't have is left out of the artifact and listed once at the end under "To confirm".
|
|
20
|
-
- **Deliver from what you have.** When the request gives you something to work on, state your assumptions in a line and produce the result. When it gives you nothing to work on, ask for it in one or two plain sentences and say what you will do once you have it.
|
|
21
|
-
- **Write for someone who has never heard of this skill.** No skill names, no paths or scripts from this folder, no internal terms, and nothing about how the run was set up. A next step is one plain sentence at the end that describes the work.
|
|
22
|
-
- **For this skill:** When the page is for email or offline reading, a diagram has to arrive as an embedded image and styles have to be inline. If you can't render a diagram, say so at the top of the reply, because the reader would otherwise see its source code.
|
|
23
|
-
|
|
24
|
-
1. **Ask once for what is missing, with defaults.** Take what the user already gave and offer
|
|
25
|
-
defaults so they can reply "go":
|
|
26
|
-
|
|
27
|
-
> Before I build the HTML, confirm these. Anything you skip uses the default:
|
|
28
|
-
> 1. **The Markdown file.** *No default.*
|
|
29
|
-
> 2. **Brand:** a `brand.json` from brand-kit. *Default: a neutral navy theme.*
|
|
30
|
-
> 3. **Table of contents:** *default on when the document has four or more `##` sections.*
|
|
31
|
-
> 4. **Mermaid diagrams:** keep as text, or draw them in the browser from a pinned CDN copy of
|
|
32
|
-
> Mermaid (the file then needs network when opened). *Default: keep as text.*
|
|
33
|
-
|
|
34
|
-
2. **Check the Markdown converts cleanly.** The script handles ATX headings (`#`), lists
|
|
35
|
-
(nested, task lists), GFM pipe tables, fenced and indented code, quotes, links and images.
|
|
36
|
-
Rewrite before converting:
|
|
37
|
-
- Setext headings (`Title` over `=====`) into `# Title`.
|
|
38
|
-
- Reference-style links (`[text][1]`) into inline links `[text](...)`.
|
|
39
|
-
- Footnotes (`[^1]`) into a "Notes" section with plain text.
|
|
40
|
-
|
|
41
|
-
Show the user what you changed.
|
|
42
|
-
|
|
43
|
-
3. **Diagrams.** For a file going to people offline or behind a strict proxy, render the
|
|
44
|
-
Mermaid to SVG first with `mermaid-render` and reference the SVGs as images. They get
|
|
45
|
-
embedded and need no network. Use `--mermaid cdn` only when readers will be online.
|
|
46
|
-
|
|
47
|
-
4. **Run the script.**
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
# Claude Code
|
|
51
|
-
python3 "${CLAUDE_SKILL_DIR}/scripts/md_to_html.py" draft.md -o draft.html --brand ./brand/brand.json --toc
|
|
52
|
-
# Other IDEs (from the skill folder)
|
|
53
|
-
python3 scripts/md_to_html.py draft.md -o draft.html --brand ./brand/brand.json --toc
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Options: `--mermaid cdn` draws diagrams with Mermaid 11.4.1 from jsDelivr (pinned, so the
|
|
57
|
-
drawing does not change under the reader); `--allow-html` passes raw HTML blocks through,
|
|
58
|
-
only for a source the user wrote themselves. Use `-` as the input to read stdin.
|
|
59
|
-
|
|
60
|
-
5. **Read every warning and report it in plain words.** The script prints counts (headings,
|
|
61
|
-
tables, code blocks, diagrams, images embedded, remote, missing) and a warning for each
|
|
62
|
-
remote image, missing image, unsafe link dropped, raw HTML escaped, and diagrams left as
|
|
63
|
-
text. Translate them: "the logo is linked from the web, so it won't show offline", not
|
|
64
|
-
"1 remote".
|
|
65
|
-
|
|
66
|
-
6. **Tell the user how to check it:** open the file, print-preview it (tables keep their
|
|
67
|
-
header row on each page, links print their address), and click two anchor links.
|
|
68
|
-
|
|
69
|
-
**Non-interactive runs** (subagent, CI, headless): no brand falls back to the neutral theme
|
|
70
|
-
with an `[assumption]` line in the reply; TOC and Mermaid use the defaults above. If there is
|
|
71
|
-
no Markdown input, emit `BLOCKED: need the Markdown file to convert` and write nothing.
|
|
72
|
-
|
|
73
|
-
## Useful references in this skill
|
|
74
|
-
|
|
75
|
-
- [`reference.md`](reference.md): what Markdown is supported, the brand.json fields read, print rules, and why raw HTML is escaped
|
|
76
|
-
- [`scripts/md_to_html.py`](scripts/md_to_html.py): the converter (stdlib only)
|
|
77
|
-
- [`examples/ops-review.md`](examples/ops-review.md): a status review with a table, code, an image and a Mermaid fence, converted with real output
|
|
78
|
-
|
|
79
|
-
## Quality bar
|
|
80
|
-
|
|
81
|
-
- **One file, nothing beside it.** Local images are embedded as data URIs. Any remote image is named to the user, because it breaks offline.
|
|
82
|
-
- **Nothing in the source runs.** Raw HTML is shown as text and `javascript:` links are dropped, unless the user asked for `--allow-html` on their own source.
|
|
83
|
-
- **Every heading has a stable anchor** (`#rollout-plan`) so people can link to a section in chat.
|
|
84
|
-
- **It prints well:** table headers repeat, code wraps instead of being cut off, links print their URL, headings don't sit alone at the bottom of a page.
|
|
85
|
-
- **The brand is the user's,** read from their `brand.json`; the neutral theme only when there is none, and said out loud.
|
|
86
|
-
- **Network dependence is stated.** If `--mermaid cdn` is on, the reply says the diagrams need network when opened.
|
|
87
|
-
|
|
88
|
-
## When to use this skill
|
|
89
|
-
|
|
90
|
-
- ✅ A Markdown report, guide or review that people outside the repo will open in a browser
|
|
91
|
-
- ✅ A file to attach to an email or upload to an intranet that has no Markdown renderer
|
|
92
|
-
- ✅ A printable version of a Markdown doc, in the company's colours and fonts
|
|
93
|
-
|
|
94
|
-
## When NOT to use this skill
|
|
95
|
-
|
|
96
|
-
- ❌ The reader needs to edit and track changes in Word; use `md-to-docx`
|
|
97
|
-
- ❌ The content is a table someone will sort and filter; use `md-to-xlsx`
|
|
98
|
-
- ❌ A designed one-page flyer or poster; use `marketing-flyer`
|
|
99
|
-
- ❌ Only diagrams, as SVG or PNG files; use `mermaid-render`
|
|
100
|
-
- ❌ Writing the document in the first place; use `guide-builder` or the relevant generator, then convert
|
|
101
|
-
|
|
102
|
-
## Anti-patterns to avoid
|
|
103
|
-
|
|
104
|
-
- ❌ **Linking images from the user's disk** (`<img src="/Users/...">`). Always build with the script, which embeds them.
|
|
105
|
-
- ❌ **Turning on `--allow-html` for pasted content** from an email or a web page. That is how a `<script>` ends up in a file the whole team opens.
|
|
106
|
-
- ❌ **Sending a `--mermaid cdn` file to a client** without saying it needs network. Render to SVG with `mermaid-render` instead.
|
|
107
|
-
- ❌ **Hand-editing the CSS in the output** to change colours. Change `brand.json` and rebuild, so the next version matches.
|
|
108
|
-
- ❌ **Reporting "done" while warnings scrolled past.** A missing image is a hole in the document; name it.
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"query": "Turn this markdown report into an HTML page I can attach to an email",
|
|
4
|
-
"should_trigger": true
|
|
5
|
-
},
|
|
6
|
-
{
|
|
7
|
-
"query": "Convert README.md to a standalone html file with our brand colours",
|
|
8
|
-
"should_trigger": true
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"query": "I need a printable web version of design-notes.md with a table of contents",
|
|
12
|
-
"should_trigger": true
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"query": "md to html please, single file, images inlined",
|
|
16
|
-
"should_trigger": true
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"query": "Convert this markdown to a Word document legal can track changes in",
|
|
20
|
-
"should_trigger": false
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"query": "Turn the markdown table of vendors into an Excel sheet",
|
|
24
|
-
"should_trigger": false
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"query": "Render the Mermaid diagram in arch.mmd to an SVG",
|
|
28
|
-
"should_trigger": false
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"query": "Make a one-page flyer for the open day in our branding",
|
|
32
|
-
"should_trigger": false
|
|
33
|
-
}
|
|
34
|
-
]
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"skill_name": "md-to-html",
|
|
3
|
-
"evals": [
|
|
4
|
-
{
|
|
5
|
-
"id": 1,
|
|
6
|
-
"prompt": "Convert docs/q3-review.md to an HTML file I can email to the Northwind Health ops committee. Use ./brand/brand.json and add a contents box. It has a results table, a screenshot at img/dashboard.png and one Mermaid flowchart. Some people on the committee read email offline on the train.",
|
|
7
|
-
"assertions": [
|
|
8
|
-
"Runs md_to_html.py with --brand ./brand/brand.json and --toc, writing a single .html file",
|
|
9
|
-
"Does not use --mermaid cdn without saying the file then needs network; because readers are offline, offers to render the flowchart to SVG with mermaid-render or keeps it as text",
|
|
10
|
-
"Reports the image as embedded, or names it as missing if the script warned it was not found",
|
|
11
|
-
"Relays every warning the script printed in plain words, not just the counts",
|
|
12
|
-
"Does not pass --allow-html",
|
|
13
|
-
"Does not invent content, numbers or sections that are not in docs/q3-review.md",
|
|
14
|
-
"Tells the user to print-preview the file and check an anchor link"
|
|
15
|
-
]
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"id": 2,
|
|
19
|
-
"held_out": "2026-10-18",
|
|
20
|
-
"prompt": "Make river-survey-guide.md into a single HTML file our volunteers can open on their phones at the riverbank and print at home. Use brand.json. Most of our sites have no mobile signal at all. And please make sure the training video at the top plays.",
|
|
21
|
-
"assertions": [
|
|
22
|
-
"Writes one .html file, and the kick-net picture is embedded inside it (for example as a data URI) rather than linked to a separate image file",
|
|
23
|
-
"The script tag in the source does not run in the output (it is escaped or removed), and the user is told",
|
|
24
|
-
"It tells the user the training video cannot play without a signal and does not claim it will; it does not quietly keep a live video embed without saying so",
|
|
25
|
-
"The flowchart is not left depending on an internet connection without a word: it is drawn into the file, kept as readable text, or the user is told it needs a signal to display",
|
|
26
|
-
"It reports that img/stonefly.png is missing",
|
|
27
|
-
"The steps, timings (3 minutes, 1 minute) and the scoring table are carried over unchanged",
|
|
28
|
-
"It does not add guidance, safety advice or content that is not in river-survey-guide.md"
|
|
29
|
-
]
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"id": 3,
|
|
33
|
-
"held_out": "2026-10-18",
|
|
34
|
-
"prompt": "can you turn nanas-lentil-soup.md into a web page I can email my sister? one file please, she's not techy and won't download anything else",
|
|
35
|
-
"assertions": [
|
|
36
|
-
"Writes a single .html file that does not need any other file or internet connection to display (no external stylesheets, scripts or fonts)",
|
|
37
|
-
"All ingredients and quantities are exactly as given (1 onion, 2 carrots, 200g red lentils, 1.2 litres veg stock, 1 tsp cumin, half a lemon) and the four steps are in the original order",
|
|
38
|
-
"The photo (pot.png) is embedded in the HTML file itself, so it shows when the sister opens only that one file",
|
|
39
|
-
"It does not invent ingredients, steps, timings, servings or nutrition information",
|
|
40
|
-
"The reply is short, in plain words without technical jargon, and it delivers without asking questions first"
|
|
41
|
-
]
|
|
42
|
-
}
|
|
43
|
-
]
|
|
44
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$comment": "brand-kit output. deck-builder and marketing-flyer 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
|
-
"name": "Northwind Health",
|
|
4
|
-
"tagline": "Care that comes to you",
|
|
5
|
-
"logo": {
|
|
6
|
-
"primary": "logo.png",
|
|
7
|
-
"on_dark": "logo-white.png",
|
|
8
|
-
"mark": "mark.png",
|
|
9
|
-
"notes": "Keep clear space equal to the height of the N on every side. Never place the full-colour logo on the green."
|
|
10
|
-
},
|
|
11
|
-
"colors": {
|
|
12
|
-
"primary": "#0E5A46",
|
|
13
|
-
"secondary": "#3D7F6B",
|
|
14
|
-
"accent": "#F2A541",
|
|
15
|
-
"background": "#FFFFFF",
|
|
16
|
-
"text": "#1F2A28",
|
|
17
|
-
"extra": [
|
|
18
|
-
{
|
|
19
|
-
"name": "Mist",
|
|
20
|
-
"hex": "#E8F1EE",
|
|
21
|
-
"use": "panel backgrounds"
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
},
|
|
25
|
-
"fonts": {
|
|
26
|
-
"heading": {
|
|
27
|
-
"family": "Georgia",
|
|
28
|
-
"fallback": "serif",
|
|
29
|
-
"weight": 700
|
|
30
|
-
},
|
|
31
|
-
"body": {
|
|
32
|
-
"family": "Arial",
|
|
33
|
-
"fallback": "sans-serif",
|
|
34
|
-
"weight": 400
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
"voice": {
|
|
38
|
-
"tone": "Warm, plain, confident. Short sentences.",
|
|
39
|
-
"use": [
|
|
40
|
-
"members",
|
|
41
|
-
"care team",
|
|
42
|
-
"near you"
|
|
43
|
-
],
|
|
44
|
-
"avoid": [
|
|
45
|
-
"patients",
|
|
46
|
-
"cutting-edge",
|
|
47
|
-
"solutions"
|
|
48
|
-
]
|
|
49
|
-
},
|
|
50
|
-
"imagery": {
|
|
51
|
-
"style": "Real people in daylight, community settings, no stock handshakes.",
|
|
52
|
-
"do": [
|
|
53
|
-
"natural light",
|
|
54
|
-
"diverse ages"
|
|
55
|
-
],
|
|
56
|
-
"dont": [
|
|
57
|
-
"clinical close-ups",
|
|
58
|
-
"illustrated icons as hero images"
|
|
59
|
-
]
|
|
60
|
-
},
|
|
61
|
-
"templates": {
|
|
62
|
-
"pptx": "northwind-master.potx"
|
|
63
|
-
},
|
|
64
|
-
"contact": {
|
|
65
|
-
"website": "northwindhealth.example",
|
|
66
|
-
"email": "hello@northwindhealth.example",
|
|
67
|
-
"phone": "",
|
|
68
|
-
"address": ""
|
|
69
|
-
},
|
|
70
|
-
"legal": {
|
|
71
|
-
"footer": "\u00a9 2026 Northwind Health",
|
|
72
|
-
"disclaimer": ""
|
|
73
|
-
},
|
|
74
|
-
"sources": {
|
|
75
|
-
"colors": "brand guidelines PDF, page 4 [explicit]",
|
|
76
|
-
"fonts": "brand guidelines PDF, page 6 [explicit]",
|
|
77
|
-
"voice": "website About page [inferred]",
|
|
78
|
-
"logo": "files supplied by the user [explicit]"
|
|
79
|
-
}
|
|
80
|
-
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Northwind Health operations review, Q3
|
|
2
|
-
|
|
3
|
-
Prepared for the ops committee. Figures cover 1 July to 30 September.
|
|
4
|
-
|
|
5
|
-
## Summary
|
|
6
|
-
|
|
7
|
-
Appointment wait time fell and the no-show rate held steady. The call centre missed its answer-time target in August.
|
|
8
|
-
|
|
9
|
-
## Results
|
|
10
|
-
|
|
11
|
-
| Measure | Q2 | Q3 | Target |
|
|
12
|
-
|:--------|---:|---:|-------:|
|
|
13
|
-
| Median wait for an appointment (days) | 9 | 6 | 7 |
|
|
14
|
-
| No-show rate | 8.4% | 8.1% | 8.0% |
|
|
15
|
-
| Calls answered within 60 seconds | 82% | 76% | 80% |
|
|
16
|
-
| Member satisfaction (out of 5) | 4.2 | 4.4 | 4.3 |
|
|
17
|
-
|
|
18
|
-
## Dashboard
|
|
19
|
-
|
|
20
|
-

|
|
21
|
-
|
|
22
|
-
## How a referral moves
|
|
23
|
-
|
|
24
|
-
```mermaid
|
|
25
|
-
flowchart LR
|
|
26
|
-
A[Referral received] --> B{Complete?}
|
|
27
|
-
B -->|Yes| C[Booked]
|
|
28
|
-
B -->|No| D[Returned to referrer]
|
|
29
|
-
D --> A
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Next quarter
|
|
33
|
-
|
|
34
|
-
- Add two call-centre shifts on Mondays.
|
|
35
|
-
- Pilot text reminders at the Riverside clinic.
|
|
Binary file
|
|
Binary file
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# Ellerby Rivers Trust: Kick-Sample Survey Field Guide
|
|
2
|
-
|
|
3
|
-
<iframe src="https://video.example.com/embed/kick-sampling-training" width="560" height="315"></iframe>
|
|
4
|
-
|
|
5
|
-
<script>trackVisit('field-guide')</script>
|
|
6
|
-
|
|
7
|
-
This guide is for trained volunteers doing the monthly invertebrate survey at their adopted site. Keep it with your kit.
|
|
8
|
-
|
|
9
|
-
## Before you go
|
|
10
|
-
|
|
11
|
-
- Check the river level gauge on the noticeboard at your site. Do not sample if the water is above the red line.
|
|
12
|
-
- Tell your site buddy when you are going and when you expect to be back.
|
|
13
|
-
- Pack: kick net, white tray, ice-cube tray, magnifier, record sheet, pencil.
|
|
14
|
-
|
|
15
|
-
## Taking the sample
|
|
16
|
-
|
|
17
|
-
1. Stand downstream of the net and hold it upright on the riverbed.
|
|
18
|
-
2. Kick the gravel in front of the net for **3 minutes**, moving across the riffle.
|
|
19
|
-
3. Do a **1-minute** hand search of stones and weed.
|
|
20
|
-
4. Empty the net into the white tray with a little river water.
|
|
21
|
-
|
|
22
|
-

|
|
23
|
-
|
|
24
|
-
## Counting
|
|
25
|
-
|
|
26
|
-
Sort what you find into the ice-cube tray by group and count each group.
|
|
27
|
-
|
|
28
|
-
![Stonefly nymph close-up][stonefly]
|
|
29
|
-
|
|
30
|
-
| Group | Score if 1-9 found | Score if 10-99 found | Score if 100+ found |
|
|
31
|
-
|---|---|---|---|
|
|
32
|
-
| Stonefly nymphs | 1 | 2 | 3 |
|
|
33
|
-
| Mayfly nymphs (flat-bodied) | 1 | 2 | 3 |
|
|
34
|
-
| Caddis larvae (cased) | 1 | 2 | 3 |
|
|
35
|
-
| Freshwater shrimp | 1 | 2 | 3 |
|
|
36
|
-
|
|
37
|
-
Add up the scores for your site total.
|
|
38
|
-
|
|
39
|
-
## What to do with your score
|
|
40
|
-
|
|
41
|
-
```mermaid
|
|
42
|
-
flowchart TD
|
|
43
|
-
A[Site total worked out] --> B{Below your site's trigger level?}
|
|
44
|
-
B -->|No| C[Enter score on record sheet]
|
|
45
|
-
B -->|Yes| D[Repeat the sample straight away]
|
|
46
|
-
D --> E{Still below trigger?}
|
|
47
|
-
E -->|No| C
|
|
48
|
-
E -->|Yes| F[Phone the survey coordinator the same day]
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Return all animals to the river where you found them.
|
|
52
|
-
|
|
53
|
-
[stonefly]: img/stonefly.png
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Nana's lentil soup
|
|
2
|
-
|
|
3
|
-
serves 4 (or 2 v hungry people)
|
|
4
|
-
|
|
5
|
-
## you need
|
|
6
|
-
- 1 onion
|
|
7
|
-
- 2 carrots
|
|
8
|
-
- 200g red lentils
|
|
9
|
-
- 1.2 litres veg stock
|
|
10
|
-
- 1 tsp cumin
|
|
11
|
-
- half a lemon
|
|
12
|
-
|
|
13
|
-
## what to do
|
|
14
|
-
1. chop onion and carrots, soften in a bit of oil 10 mins
|
|
15
|
-
2. add cumin, stir 1 min
|
|
16
|
-
2. add lentils & stock, simmer 25 mins
|
|
17
|
-
4. blend half of it, squeeze in the lemon
|
|
18
|
-
|
|
19
|
-

|
|
20
|
-
|
|
21
|
-
*Nana always said it's better the next day*
|
|
Binary file
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="120" viewBox="0 0 320 120">
|
|
2
|
-
<rect width="320" height="120" fill="#ffffff"/>
|
|
3
|
-
<rect x="20" y="60" width="50" height="40" fill="#0E5A46"/>
|
|
4
|
-
<rect x="95" y="40" width="50" height="60" fill="#0E5A46"/>
|
|
5
|
-
<rect x="170" y="30" width="50" height="70" fill="#0E5A46"/>
|
|
6
|
-
<rect x="245" y="20" width="50" height="80" fill="#F2A541"/>
|
|
7
|
-
<text x="160" y="115" font-family="Arial" font-size="10" text-anchor="middle">Weekly active members, Q1 to Q4 (illustrative)</text>
|
|
8
|
-
</svg>
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# Northwind Health: Q3 platform review
|
|
2
|
-
|
|
3
|
-
Prepared for the **operations committee**. Figures are *placeholders* for this example.
|
|
4
|
-
|
|
5
|
-
## Summary
|
|
6
|
-
|
|
7
|
-
- Uptime held at the target for the quarter
|
|
8
|
-
- Two incidents, both under 30 minutes
|
|
9
|
-
- INC-101: login latency
|
|
10
|
-
- INC-102: delayed reminder emails
|
|
11
|
-
- [x] Migrate reminders to the new queue
|
|
12
|
-
- [ ] Retire the old scheduler
|
|
13
|
-
|
|
14
|
-
> Decision needed: approve the scheduler retirement for October.
|
|
15
|
-
|
|
16
|
-
## Numbers
|
|
17
|
-
|
|
18
|
-
| Metric | Q2 | Q3 | Change |
|
|
19
|
-
|:-------|---:|---:|:------:|
|
|
20
|
-
| Uptime | 99.90% | 99.95% | up |
|
|
21
|
-
| Incidents | 4 | 2 | down |
|
|
22
|
-
| `p95` login (ms) | 410 | 380 | down |
|
|
23
|
-
|
|
24
|
-

|
|
25
|
-
|
|
26
|
-
## How a reminder is sent
|
|
27
|
-
|
|
28
|
-
```mermaid
|
|
29
|
-
flowchart LR
|
|
30
|
-
Sched([Scheduler]) -->|enqueue| Q{{Reminder queue}}
|
|
31
|
-
Q --> W[Worker]
|
|
32
|
-
W -->|SMTP| Mail[(Mail relay)]
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
The worker retries with this rule:
|
|
36
|
-
|
|
37
|
-
```python
|
|
38
|
-
def backoff(attempt):
|
|
39
|
-
return min(2 ** attempt, 300) # seconds, capped at 5 minutes
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Notes
|
|
43
|
-
|
|
44
|
-
Raw HTML is shown as text, not run: <script>alert("hi")</script>
|
|
45
|
-
|
|
46
|
-
<div style="color:red">This block came from a pasted email.</div>
|
|
47
|
-
|
|
48
|
-
See the [runbook](https://northwindhealth.example/runbooks/reminders) for the retry rules.
|