diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 0d7f9a0..437f042 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -3,7 +3,7 @@ "owner": { "name": "plannotator" }, - "description": "Agent skills for elegant, self-contained HTML plans, diagrams, and artifacts.", + "description": "Focused skills for self-contained HTML artifacts, wireframes, interactive prototypes, plans, and diagrams.", "plugins": [ { "name": "plannotator-effective-html", @@ -11,11 +11,11 @@ "source": "github", "repo": "plannotator/effective-html" }, - "description": "HTML skills for pragmatic visual artifacts — html, html-diagram, and html-plan.", + "description": "Create HTML wireframes, styled mockups, interactive prototypes, plans, diagrams, and general standalone artifacts.", "homepage": "https://github.com/plannotator/effective-html", "repository": "https://github.com/plannotator/effective-html", "license": "MIT", - "keywords": ["html", "diagram", "plan", "svg", "artifacts", "skills"], + "keywords": ["html", "wireframe", "prototype", "prototyping", "diagram", "plan", "html-artifacts", "agent-skills", "claude-code", "codex"], "category": "productivity" } ] diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 9ea9960..8e7eba7 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -2,7 +2,9 @@ "name": "plannotator-effective-html", "skills": [ "./skills/html", + "./skills/html-wireframe", + "./skills/html-prototype", "./skills/html-diagram", "./skills/html-plan" ] -} \ No newline at end of file +} diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index da8ddf5..ee4ec99 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "plannotator-effective-html", - "version": "0.1.0", - "description": "HTML skills for pragmatic visual artifacts — html, html-diagram, and html-plan.", + "version": "0.3.0", + "description": "Focused skills for self-contained HTML artifacts, wireframes, interactive prototypes, plans, and diagrams.", "author": { "name": "plannotator", "url": "https://github.com/plannotator" @@ -9,19 +9,17 @@ "homepage": "https://github.com/plannotator/effective-html", "repository": "https://github.com/plannotator/effective-html", "license": "MIT", - "keywords": ["html", "diagram", "plan", "svg", "artifacts", "skills"], + "keywords": ["html", "wireframe", "prototype", "prototyping", "diagram", "plan", "html-artifacts", "agent-skills", "claude-code", "codex"], "skills": "./skills/", "interface": { "displayName": "Effective HTML", - "shortDescription": "Elegant, self-contained HTML plans, diagrams, and artifacts", - "longDescription": "Create polished, self-contained HTML artifacts, full-screen architecture diagrams, and pragmatic plan pages from local reference examples.", + "shortDescription": "HTML wireframes, prototypes, and artifacts", + "longDescription": "Create self-contained HTML artifacts whose direction follows the user's brief, project, and subject, with focused skills for low-fidelity wireframes, styled mockups, interactive prototypes, plans, diagrams, and general HTML work.", "developerName": "plannotator", "category": "Productivity", "capabilities": ["Write"], "defaultPrompt": [ - "Create an effective HTML plan.", - "Create an effective HTML diagram.", - "Create an effective HTML artifact." + "Use $html to choose the right Effective HTML workflow and create a self-contained artifact from this brief." ] } } diff --git a/README.md b/README.md index ca70600..b1b56a5 100644 --- a/README.md +++ b/README.md @@ -1,83 +1,127 @@ -## HTML skills for pragmatic visual artifacts +# Effective HTML +Five focused skills for creating useful, self-contained HTML artifacts, from low-fidelity wireframes to working interactive prototypes. +The collection is opinionated about clarity, accessibility, and verification. It is not tied to one palette, typography stack, component system, or diagram style. Each artifact follows the user's direction first, then the project's established language, then the subject itself. -https://github.com/user-attachments/assets/24306977-7f30-44c9-9bff-55f901d557b0 +## Choose a skill -_**Note:** The diagram was made by `Fable 5`, I will create more fable 5 artifacts and add them to the skill folder for smaller models to distill._ -[example demo](https://x.com/backnotprop/status/2065479594023829619?s=20) +| Skill | Use it for | +| --- | --- | +| [`html`](skills/html/SKILL.md) | Broad HTML requests, mixed artifacts, reports, explainers, presentations, landing pages, tools, and routing to a specialist | +| [`html-wireframe`](skills/html-wireframe/SKILL.md) | Low-fidelity layout directions that test content, hierarchy, navigation, flows, and responsive structure | +| [`html-prototype`](skills/html-prototype/SKILL.md) | Styled mockups and working prototypes with realistic states, interaction, keyboard support, and responsive behavior | +| [`html-plan`](skills/html-plan/SKILL.md) | Plans, roadmaps, rollouts, and implementation sequences that preserve source commitments | +| [`html-diagram`](skills/html-diagram/SKILL.md) | Architecture, sequence, process, state, hierarchy, timeline, and system diagrams | +A mockup is a noninteractive fidelity mode inside `html-prototype`. There is no separate `html-mockup` skill. -Focused skills for generating self-contained HTML deliverables with a strong visual bias: +## One brief, three stages -- `html`: an HTML file for whatever you're describing, in the effective HTML style -- `html-diagram`: architecture, stack, and systems understanding rendered as full-screen HTML diagrams with high-quality SVG -- `html-plan`: HTML plan pages in the effective HTML style +The [release-readiness example](examples/release-readiness/README.md) carries the same product brief through structure, visual fidelity, and interaction. Every stage is preserved as a standalone HTML file that opens without build tooling. -

- - like this? star Plannotator - -

-

-Render and annotate your HTML with Plannotator (optional): https://github.com/backnotprop/plannotator -

+| Wireframe | Mockup | Prototype | +| --- | --- | --- | +| [![Low-fidelity release wireframe](examples/release-readiness/screenshots/wireframe-desktop.png)](examples/release-readiness/wireframe.html) | [![Styled release mockup](examples/release-readiness/screenshots/mockup-desktop.png)](examples/release-readiness/mockup.html) | [![Interactive release prototype](examples/release-readiness/screenshots/prototype-desktop.png)](examples/release-readiness/prototype.html) | +| Decide what belongs on the screen and compare structural directions. | Judge hierarchy, visual language, and responsive composition. | Test the blocked-to-ready flow, feedback, recovery, and product boundary. | +Read the canonical Plannotator guide, [HTML wireframes and prototypes for coding agents](https://docs.plannotator.ai/learn/code-context/html-wireframes-and-prototypes-for-coding-agents), for the review questions that belong at each stage. ## Install +Install the collection: + ```bash npx skills add plannotator/effective-html ``` -List available skills first: +List or install individual skills: ```bash npx skills add plannotator/effective-html --list +npx skills add plannotator/effective-html --skill html-wireframe +npx skills add plannotator/effective-html --skill html-prototype ``` -Install a specific skill: +Invoke a skill directly: -```bash -npx skills add plannotator/effective-html --skill html-diagram -npx skills add plannotator/effective-html --skill html-plan +```text +Use $html-wireframe to explore three responsive layouts for this checkout brief. + +Use $html-prototype in mockup mode to apply our existing design system to the approved wireframe. + +Use $html-prototype to make the checkout flow work, including validation, loading, failure, success, keyboard, and mobile states. ``` -### As a Claude Code plugin +Only `$html` is eligible for implicit invocation. Call a specialist directly when you know the artifact type, or use `$html` to route a broad request. Each specialist remains independently usable when invoked directly. -This repo is also a [plugin marketplace](https://code.claude.com/docs/en/plugin-marketplaces). Add it and install: +### Claude Code plugin -``` +```text /plugin marketplace add plannotator/effective-html /plugin install plannotator-effective-html@effective-html ``` -### As a Codex plugin +### Codex plugin ```bash codex plugin marketplace add plannotator/effective-html codex plugin add plannotator-effective-html@effective-html ``` -
+## How the skills work + +The skills separate creative freedom from reliability: + +- Visual direction comes from the conversation, project, audience, and subject. +- Wireframes stay intentionally unfinished so reviewers focus on structure. +- Mockups add a visual system without pretending to test behavior. +- Prototypes implement one credible flow and its relevant states. +- Plans preserve source commitments. +- Diagrams choose a visual model and rendering method that fit the relationship being explained. +- Every artifact is responsive, accessible, self-contained, and verified in a browser. + +Detailed guidance lives only where it is needed. The broad `html` skill keeps shared references for creative direction, documents, interfaces, diagrams, charts, and data. The specialist skills remain concise and independently usable. + +## Repository shape + +```text +skills/ +├── html/ +│ ├── SKILL.md +│ ├── agents/openai.yaml +│ └── references/ +├── html-wireframe/ +├── html-prototype/ +├── html-plan/ +└── html-diagram/ + +examples/ +└── release-readiness/ + ├── brief.md + ├── states.md + ├── wireframe.html + ├── mockup.html + ├── prototype.html + └── screenshots/ +``` + +This project was inspired by Thariq Shihipar's [The unreasonable effectiveness of HTML](https://thariqs.github.io/html-effectiveness). +

- - share your HTML? use tot + + Star Plannotator on GitHub

-

-Create instant share links for your HTML files (optional): https://github.com/plannotator/tot
HTML from video: https://tot.page/0CW7xV96XMxnalrzwRl4eQ +Render and annotate local HTML with Plannotator.

-## Skills - -- `html` - Create an HTML file for whatever the user is describing, matching the effective HTML references. -- `html-diagram` - Build full-screen HTML architecture and stack diagrams with SVG-first presentation and minimal prose. -- `html-plan` - HTML plan pages in the effective HTML style. - -## Repository Shape - -Skills live under `skills//SKILL.md`. Each skill also bundles a copy of the `html-effectiveness` example corpus under `references/html-effectiveness/` so the examples stay local to the skill. - -Credit: this repo bundles and uses the `html-effectiveness` examples by Thariq Shihipar: https://thariqs.github.io/html-effectiveness +

+ + Share HTML with tot + +

+

+Create a shareable link for an HTML file with tot. +

diff --git a/examples/release-readiness/README.md b/examples/release-readiness/README.md new file mode 100644 index 0000000..ab028a6 --- /dev/null +++ b/examples/release-readiness/README.md @@ -0,0 +1,58 @@ +# Release readiness example + +This example takes one product brief through three review stages. Each stage is a separate, self-contained HTML file so it can be opened directly, copied, and changed without build tooling. + +## 1. Wireframe + +[Open the wireframe](wireframe.html) + +The wireframe keeps the visual treatment deliberately plain and compares three structural directions: + +- **Decision first** keeps the release verdict visible beside the checks. +- **Evidence ledger** favors dense comparison and auditability. +- **Guided gate** turns the decision into a step-by-step review. + +Decisions at this stage include content, grouping, navigation, task order, and mobile reflow. Color, typography, component styling, and animation remain open. + +| Decision first | Evidence ledger | Guided gate | +| --- | --- | --- | +| ![Decision-first wireframe](screenshots/wireframe-desktop.png) | ![Evidence-ledger wireframe](screenshots/wireframe-evidence-ledger-desktop.png) | ![Guided-gate wireframe](screenshots/wireframe-guided-gate-desktop.png) | + +## 2. Mockup + +[Open the mockup](mockup.html) + +The mockup develops the decision-first direction into a release-control workspace. It adds a product-specific visual hierarchy, responsive composition, readable state styling, and realistic evidence without adding product behavior. + +Decisions at this stage include type, spacing, color, contrast, visual density, and how the desktop composition collapses on mobile. Data flow, permissions, persistence, and transitions remain open. + +![Styled release-readiness mockup](screenshots/mockup-desktop.png) + +## 3. Prototype + +[Open the prototype](prototype.html) + +The prototype adds the smallest complete flow needed to test the decision: + +1. Review the failed iOS smoke test. +2. Record a passing rerun in a keyboard-accessible dialog. +3. See the release change from blocked to ready. +4. Request a production release and reach the explicit prototype boundary. + +The artifact includes loading, error, success, disabled, empty-notes, mobile, and reduced-motion states. It does not authenticate a user, save data, or start a real release. + +![Interactive release-readiness prototype](screenshots/prototype-desktop.png) + +See the [validation record](validation.md) for browser, interaction, accessibility, clean-invocation, and packaging checks. + +## Clone and adapt + +Copy the stage closest to the question you need to answer: + +```bash +cp examples/release-readiness/wireframe.html my-flow.html +cp examples/release-readiness/mockup.html my-mockup.html +cp examples/release-readiness/prototype.html my-prototype.html +``` + +Replace the brief, labels, data, and state model before changing the visual direction. A useful adaptation keeps the review question clear and removes controls that do not support it. diff --git a/examples/release-readiness/brief.md b/examples/release-readiness/brief.md new file mode 100644 index 0000000..ec96247 --- /dev/null +++ b/examples/release-readiness/brief.md @@ -0,0 +1,26 @@ +# Atlas Mobile 4.8 release-readiness brief + +## User and task + +A release manager must decide whether Atlas Mobile 4.8 can go to production. + +## Required information + +- Release candidate and commit +- Release owner +- Four required checks and their current state +- Evidence behind each check +- Open risks and reviewer notes +- Current release decision + +## Required behavior + +The page starts blocked because the iOS smoke test failed. A reviewer can record a passing rerun. The release state then changes from blocked to ready, and the production-release action becomes available. + +## Non-goals + +- Starting a real deployment +- Authentication or authorization +- Loading live build data +- Defining the production application's component architecture +- Final product copy for every failure and recovery state diff --git a/examples/release-readiness/mockup.html b/examples/release-readiness/mockup.html new file mode 100644 index 0000000..1213945 --- /dev/null +++ b/examples/release-readiness/mockup.html @@ -0,0 +1,831 @@ + + + + + + Atlas Mobile 4.8 release-readiness mockup + + + + +
Styled mockup · static visual review
+ +
+
+
+ + Atlas release desk +
+ +
+ Reviewing as Maya Chen + +
+
+ +
+
+
Release candidate 03July 29, 2026
+

Atlas Mobile 4.8

+

One required check is blocking production. Review the failed iOS checkout case and its evidence before changing the release decision.

+
+
Blocked1 failed check
+
+ +
+
Candidate4.8.0-rc.3
+
Commit8f31d2a
+
OwnerMaya Chen
+
Evidence current18 minutes ago
+
+ +
+
+
+

Required checks

+

3 of 4 passed · all evidence shown

+
+ +
    +
  1. + +
    Android smoke testPixel 9 · Android 16
    +
    android-smoke-741242 cases passed in 6m 14s
    + Pass +
  2. +
  3. + +
    iOS smoke testiPhone 16 · iOS 19
    +
    ios-smoke-9831Checkout froze after Apple Pay
    + Fail +
  4. +
  5. + +
    API compatibilityMobile contract suite
    +
    contract-186186 checks passed in 2m 08s
    + Pass +
  6. +
  7. + +
    Privacy reviewNo new data collection
    +
    PRV-219Approved by Nia Wallace
    + Pass +
  8. +
+ +
+ +
+ Open risk: iOS checkout completion + The payment sheet closed successfully, but the app did not advance to the confirmation screen. Reproduce and pass the same device flow before release. +
+
+
+ + +
+ +
+ Atlas release desk · review artifact + Visual fidelity only · no live release behavior +
+
+ + diff --git a/examples/release-readiness/prototype.html b/examples/release-readiness/prototype.html new file mode 100644 index 0000000..f075adb --- /dev/null +++ b/examples/release-readiness/prototype.html @@ -0,0 +1,1728 @@ + + + + + + Atlas Mobile 4.8 release-readiness prototype + + + + +
Interactive prototype · local sample data
+
+ +
+
+
+ + Atlas release desk +
+ +
+ Reviewing as Maya Chen + +
+
+ + + +
+
+
+
Release candidate 03July 29, 2026
+

Atlas Mobile 4.8

+

One required check is blocking production. Review the failed iOS checkout case and its evidence before changing the release decision.

+
+
Blocked1 failed check
+
+ +
+
Candidate4.8.0-rc.3
+
Commit8f31d2a
+
OwnerMaya Chen
+
Evidence current18 minutes ago
+
+ +
+
+
+

Required checks

+

3 of 4 passed · all evidence shown

+
+ +
    +
  1. + +
    Android smoke testPixel 9 · Android 16
    +
    android-smoke-741242 cases passed in 6m 14s
    + Pass +
  2. +
  3. + +
    iOS smoke testiPhone 16 · iOS 19
    +
    ios-smoke-9831Checkout froze after Apple Pay
    + Fail +
  4. +
  5. + +
    API compatibilityMobile contract suite
    +
    contract-186186 checks passed in 2m 08s
    + Pass +
  6. +
  7. + +
    Privacy reviewNo new data collection
    +
    PRV-219Approved by Nia Wallace
    + Pass +
  8. +
+ +
+ +
+ Open risk: iOS checkout completion + The payment sheet closed successfully, but the app did not advance to the confirmation screen. Reproduce and pass the same device flow before release. +
+
+
+ + +
+
+ + + +
+ Atlas release desk · review prototype + No live data · no production action +
+
+ + +
+
+
+

Record iOS rerun

+

Replace the failed result with evidence from the same checkout flow.

+
+ +
+
+
+ + +
+
+ + + Use the rerun identifier from the device test record. +
+
+ + +
+

Choose a result and enter an evidence ID to enable saving.

+
+ Prototype controls + +
+ +
+
+ + +
+
+
+ + +
+
+

Production boundary

+

The modeled release flow ends here.

+
+ +
+
+ Prototype only +

A real release request would now require authorization, a fresh evidence check, an audit entry, and a call to the deployment system. This file performs none of those actions.

+
+
+ +
+
+ + + + + + diff --git a/examples/release-readiness/screenshots/mockup-desktop.png b/examples/release-readiness/screenshots/mockup-desktop.png new file mode 100644 index 0000000..3e1392d Binary files /dev/null and b/examples/release-readiness/screenshots/mockup-desktop.png differ diff --git a/examples/release-readiness/screenshots/mockup-mobile.png b/examples/release-readiness/screenshots/mockup-mobile.png new file mode 100644 index 0000000..bd06706 Binary files /dev/null and b/examples/release-readiness/screenshots/mockup-mobile.png differ diff --git a/examples/release-readiness/screenshots/prototype-desktop.png b/examples/release-readiness/screenshots/prototype-desktop.png new file mode 100644 index 0000000..2c1a836 Binary files /dev/null and b/examples/release-readiness/screenshots/prototype-desktop.png differ diff --git a/examples/release-readiness/screenshots/prototype-mobile.png b/examples/release-readiness/screenshots/prototype-mobile.png new file mode 100644 index 0000000..231048f Binary files /dev/null and b/examples/release-readiness/screenshots/prototype-mobile.png differ diff --git a/examples/release-readiness/screenshots/wireframe-desktop.png b/examples/release-readiness/screenshots/wireframe-desktop.png new file mode 100644 index 0000000..51a3d3c Binary files /dev/null and b/examples/release-readiness/screenshots/wireframe-desktop.png differ diff --git a/examples/release-readiness/screenshots/wireframe-evidence-ledger-desktop.png b/examples/release-readiness/screenshots/wireframe-evidence-ledger-desktop.png new file mode 100644 index 0000000..e229f61 Binary files /dev/null and b/examples/release-readiness/screenshots/wireframe-evidence-ledger-desktop.png differ diff --git a/examples/release-readiness/screenshots/wireframe-guided-gate-desktop.png b/examples/release-readiness/screenshots/wireframe-guided-gate-desktop.png new file mode 100644 index 0000000..cca8670 Binary files /dev/null and b/examples/release-readiness/screenshots/wireframe-guided-gate-desktop.png differ diff --git a/examples/release-readiness/screenshots/wireframe-mobile.png b/examples/release-readiness/screenshots/wireframe-mobile.png new file mode 100644 index 0000000..cd738d7 Binary files /dev/null and b/examples/release-readiness/screenshots/wireframe-mobile.png differ diff --git a/examples/release-readiness/states.md b/examples/release-readiness/states.md new file mode 100644 index 0000000..bc87654 --- /dev/null +++ b/examples/release-readiness/states.md @@ -0,0 +1,12 @@ +# Release-readiness states + +| State | Trigger | Visible result | Available action | +| --- | --- | --- | --- | +| Blocked | The iOS smoke test failed | The failed check and release decision show why the candidate is blocked | Record a rerun | +| Saving | A reviewer submits a rerun | The form and trigger are disabled while progress is announced | Wait | +| Save error | The simulated evidence service rejects the update | The dialog keeps its values, explains the failure, and offers retry | Retry or cancel | +| Ready | All four checks pass | The summary changes to 4 of 4 and the release action becomes available | Request production release | +| Release requested | A reviewer selects the enabled release action | The prototype explains where the real release system would take over | Close the explanation | +| Empty notes | A reviewer clears the sample notes | The notes area explains that no reviewer notes have been added | Add a note | + +The prototype also defines a responsive mobile composition and reduced-motion behavior. Authentication, live data, persistence, authorization, and rollback remain outside the prototype. diff --git a/examples/release-readiness/validation.md b/examples/release-readiness/validation.md new file mode 100644 index 0000000..1cdd428 --- /dev/null +++ b/examples/release-readiness/validation.md @@ -0,0 +1,60 @@ +# Validation record + +Validated July 29, 2026, on macOS with Google Chrome. + +## Repository example + +| Check | Result | +| --- | --- | +| Desktop rendering | Passed at 1440 × 1000 for all three stages and all three wireframe directions | +| Mobile rendering | Passed at 390 × 844 with reduced motion enabled | +| Horizontal overflow | None at the page level in any tested stage or direction | +| Console and page errors | None | +| Self-containment | No external scripts, styles, images, fonts, APIs, or services | +| Semantic checks | No duplicate IDs, missing ARIA references, or unnamed buttons | +| Automated accessibility | No WCAG A or AA violations in the tested desktop and mobile views | + +The Guided gate wireframe was also tested as a click-through flow. Back, rerun, continue, and return actions work with pointer, `Enter`, and `Space`; each transition updates the current step and evidence, then moves focus to the new step heading. + +Invalid wireframe `?v=` values fall back to the Decision first direction. In the prototype, the skip link switches from Activity to Overview before it focuses the release checks. + +The prototype was tested in its blocked, dialog, loading, save-error, ready, production-boundary, empty-notes, and add-note states. The test covered: + +- disabled release gating; +- form validation and preserved input after an error; +- retry from error to ready; +- failed rerun from ready back to blocked; +- focus restoration after dialogs; +- `Tab`, `Shift+Tab`, `Enter`, `Space`, arrow-key, and `Escape` behavior; +- overview and activity navigation; +- empty notes and add-note recovery; +- reduced-motion behavior; +- safe rendering of reviewer-entered text. + +The screenshots in this directory were captured from the validated source. The prototype screenshots show the reached ready state rather than the initial blocked state. + +## Clean skill invocations + +Each skill was invoked in an isolated agent context with the product brief embedded in the prompt. The agents were instructed not to inspect the repository examples or screenshots, and all generated files were written outside the repository. + +| Skill | Result | +| --- | --- | +| `html` | Routed a structural review request to `html-wireframe` by reading the sibling skill, then completed the artifact without inspecting repository examples | +| `html-wireframe` | Produced three distinct structural directions and passed wide and narrow rendering checks | +| `html-prototype`, mockup mode | Produced a static release-control mockup with no dead controls and passed wide, narrow, reduced-motion, overflow, console, and contrast checks | +| `html-prototype`, prototype mode | Produced a working blocked-to-ready flow with passing and failing reruns, loading, validation, dialog focus containment, keyboard support, mobile layout, and a production boundary | +| `html-plan` | Preserved the four checks, owner, evidence, blocker, sequence, and readiness gate in a responsive HTML plan | +| `html-diagram` | Produced a responsive release-gate process diagram with failed and passing branches that stop at the production-request boundary | + +The first clean mockup run exposed inherited dark text on a dark decision surface. The skill was updated to require computed foreground and background checks on every distinct surface. A fresh invocation then passed, with a lowest measured contrast ratio of 4.58:1. + +## Packaging + +- All five skills pass the platform skill validator. +- Only `html` allows implicit invocation. The four direct-invocation specialists remain independently usable. +- The repository passes strict Vercel, Claude, and Codex skill-format validation. +- Every JSON manifest parses. +- Claude Code's native marketplace validator passes. +- The current `skills` CLI discovers all five entries. +- A clean local install copied all five skills and the shared `html` references into temporary Claude Code and Codex project directories. +- `git diff --check` passes. diff --git a/examples/release-readiness/wireframe.html b/examples/release-readiness/wireframe.html new file mode 100644 index 0000000..49c8219 --- /dev/null +++ b/examples/release-readiness/wireframe.html @@ -0,0 +1,993 @@ + + + + + + Atlas Mobile release-readiness wireframes + + + +
+ + + + + + diff --git a/skills.sh.json b/skills.sh.json index 5685c86..e839833 100644 --- a/skills.sh.json +++ b/skills.sh.json @@ -4,12 +4,14 @@ "groupings": [ { "title": "Effective HTML", - "description": "Skills for generating pragmatic HTML diagrams and plans.", + "description": "Focused skills for self-contained HTML artifacts, wireframes, prototypes, plans, and diagrams.", "skills": [ "html", + "html-wireframe", + "html-prototype", "html-diagram", "html-plan" ] } ] -} \ No newline at end of file +} diff --git a/skills/html-diagram/SKILL.md b/skills/html-diagram/SKILL.md index 17e347e..072e9c9 100644 --- a/skills/html-diagram/SKILL.md +++ b/skills/html-diagram/SKILL.md @@ -1,27 +1,43 @@ --- name: html-diagram -description: Create a self-contained HTML file for visualizing architecture and understanding the stack with a high-quality SVG diagram. Use when the user wants a full-screen diagram, wants the output to be light on prose, or wants an HTML artifact that is mostly there to make the architecture click fast. -disable-model-invocation: true +description: Direct-invocation specialist for self-contained HTML diagrams whose layout, notation, and interaction clarify relationships, sequence, topology, state, hierarchy, or quantitative structure. Use when the user explicitly invokes html-diagram or the broad html skill routes a diagram request here. Do not activate independently from a general request. --- # HTML Diagram -Review the SVG diagrams used throughout `references/html-effectiveness/`. +Build the smallest visual model that makes the relationship easier to understand than prose alone. Match the notation and visual language to the user's project and subject. Do not force every topic into the same SVG boxes and arrows. -There are a bunch in there, and some of them are focused on architecture and whatnot. +## Choose the right model -After reviewing them, create an HTML file that is strictly for visualizing the architecture and understanding the stack. +Identify the question the reader should answer, then select the form: -It should not be prose-heavy. It should simplify more into a full-screen diagram and whatnot. +- topology for components and connections; +- sequence for ordered messages over time; +- process for steps, branches, and handoffs; +- state for transitions and conditions; +- hierarchy for containment or ownership; +- timeline for change over time; +- matrix for repeated relationships; +- quantitative view when magnitude matters. -Build a high-quality diagram in SVG. Take your time iterating on the diagram more than anything. +Decide what must remain visible together and what can be revealed on demand. Use a simpler form when it carries the same meaning. -If it makes sense, make the diagram interactive and able to visualize and animate different sequences of system behavior. +## Choose the rendering method -Also review `references/architecture-example.html` — a finished example of this skill done well (full-screen SVG stage, clickable nodes, flow chips that light up and animate request paths). +Use HTML and CSS, SVG, Canvas, or WebGL according to the information and scale. Do not use SVG merely because the output is a diagram. -Always include dark mode: hand-rolled CSS variables on `:root` / `html.dark`, a small theme toggle button, `localStorage` persistence, and an apply-before-paint script in `` (default to `prefers-color-scheme`). Style the SVG through CSS classes using those variables — never hard-coded hex inside the SVG — so the diagram follows the theme. +- Keep labels, grouping, direction, and connectors legible before adding interaction. +- Use stable node positions when readers must compare states or steps. +- Keep edge crossings and ambiguous arrowheads to a minimum. +- Put intentionally broad canvases in a contained pan or scroll region. +- Use legends only when notation is not self-explanatory. -Always make floating overlays dismissible. Any card or panel that overlays the SVG stage (e.g., a detail panel, a legend, a side card) MUST have a visible close button, and MUST re-open when the user clicks a relevant node or filter. This prevents floating panels from permanently blocking content on the full-screen stage. +Add sequencing, filtering, path tracing, pan and zoom, or animation only when it helps answer the stated question. Keep overlays dismissible, controls keyboard-accessible, and motion compatible with `prefers-reduced-motion`. -Architecture diagrams almost always exceed the screen. Support pan (drag) and zoom (mouse wheel). Wrap all SVG contents in `` and drive its `transform` attribute. Pan in SVG-space 1:1 (do NOT divide mouse delta by scale — dividing makes dragging feel sluggish when zoomed in). Zoom at the cursor position by translating so the SVG point under the cursor stays fixed. Suppress node `click` events after a drag (track a 5px movement threshold + a capture-phase one-shot `stopPropagation`). Provide visual feedback: `grab` / `grabbing` cursors, a zoom-level indicator, and a reset-to-100% button. +## Build and verify + +Deliver one self-contained HTML file with essential CSS and JavaScript inline. Require no build step or external service. Use accessible text alternatives and keep important meaning available without animation or color alone. + +Inspect the result at wide and narrow widths. Check label collisions, clipped nodes, edge routing, reading order, keyboard operation, overflow, and every interactive state. + +Return the absolute path, the diagram form chosen, and the main simplifications or assumptions. diff --git a/skills/html-diagram/agents/openai.yaml b/skills/html-diagram/agents/openai.yaml index 171a409..c445e41 100644 --- a/skills/html-diagram/agents/openai.yaml +++ b/skills/html-diagram/agents/openai.yaml @@ -1,7 +1,7 @@ interface: display_name: "HTML Diagram" - short_description: "Create effective standalone HTML diagrams" - default_prompt: "Use $html-diagram to create a polished architecture diagram." + short_description: "Direct skill for HTML diagrams and flows" + default_prompt: "Use $html-diagram to create a clear, self-contained HTML diagram for this system or flow." policy: allow_implicit_invocation: false diff --git a/skills/html-diagram/references/architecture-example.html b/skills/html-diagram/references/architecture-example.html deleted file mode 100644 index 9b50ce9..0000000 --- a/skills/html-diagram/references/architecture-example.html +++ /dev/null @@ -1,462 +0,0 @@ - - - - - -Workspaces — Architecture - - - - - -
-
-

Workspaces — the stack

-
two workers · four backends · one access gate
-
-
-
- - - - - - - -
- -
- -
- - - - - - - - - - - - - Clients - same API for all three - - - - App Worker - workspaces.plannotator.ai · Hono · one deploy - - - - Durable Objects - - - - Backends - one source of truth per data type - - - - - - - - - - - - - - - - - - - - - - - - - - loads the app - Bearer wsk_live_… - WebSocket · Yjs - metadata reads / writes - init-safe - upgrade → same DO - checkpoint · 2–10s debounce - git push - commits → D1 - pointer check + cached body - cold miss · readAt(sha) - hosted login redirect - JWKS · verified at the edge - sandboxed iframe - reads blobs @sha - - - - Browser - Vite + React SPA - session cookie · WebSocket - - - - Agent / CLI - curl + API key - same /v1 surface, HTTP only - - - - Anyone with a link - no account · no cookie - the link is the keys - - - - - - Static assets - SPA shell · edge-cached - - - - /auth/* - login · callback · logout - - - - authenticate - session | api key | anon - → one Identity - - - - resolveAccess() - the one gate - open·public·private·org - - - - /v1 route handlers - documents · workspaces · comments · versions · keys · me - - - - /parties/* WS door - onBeforeConnect → gate - - - - agent edit bridge - applyAgentEdit() RPC - - - - /s/* public reads - cookieless · cacheable · never mounts authenticate - - - - - - Document DO - one per document - Yjs merge · live fan-out - SQLite hot tier - humans + agents, one writer - - - - Workspace coordinator - one per workspace · lazy - sole pusher to the repo - expiry alarm - - - - - - WorkOS - identity · hosted AuthKit · orgs - we store only IDs - - - - D1 - metadata source of truth - workspaces · documents · annotations - api_keys · commits projection - - - - Cloudflare Artifacts - content + version history - one git repo per workspace - docs as files · version = blob SHA - - - - KV + Cache API - visibility pointer (fail-closed) - public body cache · JWKS cache - reconstructible only — never truth - - - - - - usercontent Worker - separate domain · cookieless - untrusted HTML can never touch a login - - - -
research/ARCHITECTURE.md v2 · spec.yaml 0.13.0
- -
-
-
    -
    - -
    -

    Click anything

    -
    node detail
    -

    Every box is clickable. The chips up top light up the request paths — Create, Live edit, Agent edit, Public read, Login, HTML render.

    -
    -
    - - - diff --git a/skills/html-diagram/references/html-effectiveness/01-exploration-code-approaches.html b/skills/html-diagram/references/html-effectiveness/01-exploration-code-approaches.html deleted file mode 100644 index fc0c648..0000000 --- a/skills/html-diagram/references/html-effectiveness/01-exploration-code-approaches.html +++ /dev/null @@ -1,454 +0,0 @@ - - - - - - - Debounced search — three approaches - - - -
    - -
    -
    Exploration · Acme web client
    -

    Three ways to implement debounced search

    -
    - Prompt - Show me three different ways to implement debounced search for the task - filter input in our React codebase, with tradeoffs for each. -
    -
    - - - -
    - - -
    -
    -

    01Inline useEffect + setTimeout

    -

    Debounce logic lives directly inside the component that owns the input.

    -
    - -
    export function TaskSearch() {
    -  const [draft, setDraft] = useState('');
    -  const [query, setQuery] = useState('');
    -
    -  useEffect(() => {
    -    const id = setTimeout(() => setQuery(draft), 300);
    -    return () => clearTimeout(id);
    -  }, [draft]);
    -
    -  const { data } = useTasks({ search: query });
    -
    -  return (
    -    <input
    -      value={draft}
    -      onChange={(e) => setDraft(e.target.value)}
    -      placeholder="Filter tasks…"
    -    />
    -  );
    -}
    - -
    -
    -
    Pro
    -
    Con
    -
    -
    -
    Zero new abstractions to learn
    -
    Logic duplicated everywhere search exists
    -
    -
    -
    Easy to step through in devtools
    -
    Two pieces of state for one conceptual value
    -
    -
    -
    No dependency or bundle change
    -
    Delay constant is buried in component body
    -
    -
    - -
    - Bundle impact: +0 kb - Testability: medium - Reuse: low - SSR safe: yes -
    -
    - - -
    -
    -

    02Custom useDebounce hook

    -

    Extract the timer into a shared hook under src/hooks/.

    -
    - -
    // src/hooks/useDebounce.ts
    -export function useDebounce<T>(value: T, ms = 300): T {
    -  const [debounced, setDebounced] = useState(value);
    -  useEffect(() => {
    -    const id = setTimeout(() => setDebounced(value), ms);
    -    return () => clearTimeout(id);
    -  }, [value, ms]);
    -  return debounced;
    -}
    -
    -// TaskSearch.tsx
    -const [draft, setDraft] = useState('');
    -const query = useDebounce(draft, 300);
    -const { data } = useTasks({ search: query });
    - -
    -
    -
    Pro
    -
    Con
    -
    -
    -
    Single import reused across filter, command bar, board search
    -
    One more file to maintain and document
    -
    -
    -
    Trivial to unit test with fake timers
    -
    Generic T hides intent slightly
    -
    -
    -
    Delay is a visible, tunable argument
    -
    Still re-renders on every keystroke
    -
    -
    - -
    - Bundle impact: +0.2 kb - Testability: high - Reuse: high - SSR safe: yes -
    -
    - - -
    -
    -

    03Tiny external library

    -

    Adopt use-debounce for both values and callbacks.

    -
    - -
    import { useDebouncedCallback }
    -  from 'use-debounce';
    -
    -export function TaskSearch() {
    -  const [query, setQuery] = useState('');
    -
    -  const onChange = useDebouncedCallback(
    -    (next: string) => setQuery(next),
    -    300,
    -    { leading: false, maxWait: 1000 },
    -  );
    -
    -  const { data } = useTasks({ search: query });
    -
    -  return (
    -    <input
    -      defaultValue=""
    -      onChange={(e) => onChange(e.target.value)}
    -    />
    -  );
    -}
    - -
    -
    -
    Pro
    -
    Con
    -
    -
    -
    leading / trailing / maxWait handled for us
    -
    New runtime dependency to audit and update
    -
    -
    -
    Callback form skips intermediate re-renders
    -
    Uncontrolled input diverges from Acme form patterns
    -
    -
    -
    Well-tested edge cases (unmount, flush, cancel)
    -
    ~1.4 kb gzipped for something we could own
    -
    -
    - -
    - Bundle impact: +1.4 kb - Testability: high - Reuse: high - SSR safe: yes -
    -
    - -
    - - - - - -
    - - diff --git a/skills/html-diagram/references/html-effectiveness/02-exploration-visual-designs.html b/skills/html-diagram/references/html-effectiveness/02-exploration-visual-designs.html deleted file mode 100644 index 817fcc3..0000000 --- a/skills/html-diagram/references/html-effectiveness/02-exploration-visual-designs.html +++ /dev/null @@ -1,516 +0,0 @@ - - - - - - - Empty state — four visual directions - - - - -
    -
    Acme · design exploration
    -
    - Background: -
    - - -
    -
    -
    - -
    - -
    -
    Exploration · Empty states
    -

    Four visual directions for the “no tasks yet” state

    -
    - Prompt - Explore four visual directions for our empty-state component. Render each - live so we can compare tone, density, and how well they hold up on light - and dark surfaces. -
    -
    - -
    - - -
    - A — Minimal -
    -
    -

    No tasks yet

    -

    When you create a task it will show up here.

    - New task -
    -
    -

    - Pure typography, single quiet action. Reads as calm and confident; - assumes the surrounding UI already carries enough personality. -

    -
    - - -
    - B — Illustrated -
    -
    - -

    Start your first list

    -

    Group related work and watch progress roll up automatically.

    - Create a task -
    -
    -

    - A small geometric spot illustration anchors the eye and explains the - object model (lists contain tasks) without a wall of copy. -

    -
    - - -
    - C — Playful -
    -
    -
    -
    -
    -
    -
    -
    -

    Nothing on your plate

    -

    Enjoy the quiet, or add something to get moving.

    -
    -
    -

    - A gently bobbing stack adds life to an otherwise static screen. Motion - is subtle enough to loop indefinitely without drawing complaints. -

    -
    - - -
    - D — Instructional -
    -
    -

    Set up this project

    -
      -
    1. - Create your first task - Give it a name and an owner. -
    2. -
    3. - Add a due date - Acme will surface it on the timeline. -
    4. -
    5. - Invite a teammate - Shared projects stay in sync automatically. -
    6. -
    -
    -
    -

    - Treats the empty state as onboarding. Higher density, but every line is - actionable — best when the user is new to the product, not just the view. -

    -
    - -
    -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/03-code-review-pr.html b/skills/html-diagram/references/html-effectiveness/03-code-review-pr.html deleted file mode 100644 index bfb344b..0000000 --- a/skills/html-diagram/references/html-effectiveness/03-code-review-pr.html +++ /dev/null @@ -1,639 +0,0 @@ - - - - - - -PR #247 — Review Summary - - - -
    - -
    -
    acme/web · Pull Request #247
    -

    Add optimistic updates to task list mutations

    -
    -
    -
    MO
    -
    -
    Mira Okafor
    -
    opened 2 days ago
    -
    -
    -
    - mo/optimistic-tasks main -
    -
    - +142 / −38 - 6 files changed -
    -
    -
    - -
    -

    What this PR does

    -
      -
    • Replaces the await-then-refetch pattern in TaskList with optimistic cache writes, so toggling or reordering a task feels instant instead of waiting ~300ms for the round-trip.
    • -
    • Introduces a small useOptimisticTasks hook that wraps the mutation, snapshots the previous list, and rolls back on error.
    • -
    • Extends the API client to accept an idempotency key per mutation and adds a toast when a rollback fires.
    • -
    -
    - -
    -

    Risk map

    - -
    - safe - worth a look - needs attention -
    -
    - -
    -

    Files

    - - -
    -
    -
    -
    src/hooks/useOptimisticTasks.ts
    -
    -
    - needs attention - +58 −0 -
    -
    -
    -
    @@ -0,0 +1,58 @@
    -
    1+import { useMutation, useQueryClient } from '@tanstack/react-query';
    -
    2+import { updateTask, TaskPatch } from '../api/tasks';
    -
    3+import type { Task } from '../types/task';
    -
    4+
    -
    5+export function useOptimisticTasks(boardId: string) {
    -
    6+ const qc = useQueryClient();
    -
    7+ const key = ['tasks', boardId];
    -
    8+
    -
    9+ return useMutation({
    -
    10+ mutationFn: (patch: TaskPatch) => updateTask(patch),
    -
    11+ onMutate: async (patch) => {
    -
    12+ const prev = qc.getQueryData<Task[]>(key);
    -
    13+ qc.setQueryData<Task[]>(key, (old = []) =>
    -
    14+ old.map(t => t.id === patch.id ? { ...t, ...patch } : t)
    -
    15+ );
    -
    16+ return { prev };
    -
    17+ },
    -
    18+ onError: (_e, _p, ctx) => qc.setQueryData(key, ctx?.prev),
    -
    19+ });
    -
    20+}
    -
    -
    -
    -
    line 11
    -

    BlockingonMutate doesn't call qc.cancelQueries(key) first. If a background refetch lands between the optimistic write and the server response, it will clobber the optimistic state and the UI will flicker back to the old value.

    -
    -
    -
    line 18
    -

    NitRollback restores the list but never surfaces the error. Consider wiring the existing pushToast here so users know the toggle didn't stick.

    -
    -
    -
    - - -
    -
    -
    -
    src/components/TaskList.tsx
    -
    -
    - worth a look - +31 −24 -
    -
    -
    -
    @@ -42,14 +42,17 @@ export function TaskList({ boardId }: Props) {
    -
    42 const { data: tasks } = useTasks(boardId);
    -
    43- const [pending, setPending] = useState<string | null>(null);
    -
    44-
    -
    45- async function toggle(task: Task) {
    -
    46- setPending(task.id);
    -
    47- await updateTask({ id: task.id, done: !task.done });
    -
    48- await refetch();
    -
    49- setPending(null);
    -
    50- }
    -
    43+ const { mutate, isPending } = useOptimisticTasks(boardId);
    -
    44+
    -
    45+ const toggle = (task: Task) =>
    -
    46+ mutate({ id: task.id, done: !task.done });
    -
    47
    -
    48 return (
    -
    49 <ul className="tasks">
    -
    50- {tasks?.map(t => <TaskRow key={t.id} task={t} busy={pending === t.id} />)}
    -
    50+ {tasks?.map(t => <TaskRow key={t.id} task={t} onToggle={toggle} />)}
    -
    51 </ul>
    -
    -
    -
    -
    line 43
    -

    NitisPending is destructured but never read. Either drop it or pass it to TaskRow so the checkbox can dim while the request is in flight.

    -
    -
    -
    - - -
    -
    -
    -
    src/api/tasks.ts
    -
    -
    - worth a look - +19 −6 -
    -
    -
    -
    @@ -12,10 +12,15 @@ export type TaskPatch = Partial<Task> & { id: string };
    -
    12
    -
    13-export async function updateTask(patch: TaskPatch) {
    -
    14- return http.patch(`/tasks/${patch.id}`, patch);
    -
    13+export async function updateTask(
    -
    14+ patch: TaskPatch,
    -
    15+ key = crypto.randomUUID(),
    -
    16+) {
    -
    17+ return http.patch(`/tasks/${patch.id}`, patch, {
    -
    18+ headers: { 'Idempotency-Key': key },
    -
    19+ });
    -
    20 }
    -
    -
    -
    -
    line 15
    -

    BlockingGenerating the idempotency key as a default parameter means retries from the mutation layer get a new key each time, which defeats the purpose. The key should be minted once in onMutate and threaded through.

    -
    -
    -
    - - -
    - - src/components/Toast.tsx - - safe - +14 −2 - - -
    Adds a variant="warning" style and exports pushToast. Purely additive, no behaviour change for existing call sites.
    -
    - -
    - - src/types/task.ts - - safe - +6 −2 - - -
    Widens Task.status to include "archived" and adds an optional updatedAt timestamp. Type-only change.
    -
    - -
    - - src/components/__tests__/TaskList.test.tsx - - safe - +14 −4 - - -
    Adds a test asserting the row updates synchronously after click, and one asserting rollback when the mocked request rejects. Both pass locally.
    -
    -
    - -
    -

    Suggested next steps

    -
      -
    • - - -
    • -
    • - - -
    • -
    • - - -
    • -
    -
    - -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/04-code-understanding.html b/skills/html-diagram/references/html-effectiveness/04-code-understanding.html deleted file mode 100644 index e36505b..0000000 --- a/skills/html-diagram/references/html-effectiveness/04-code-understanding.html +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - -How authentication flows through acme/web - - - -
    - -
    -
    acme/web · architecture note
    -

    How authentication flows through the codebase

    -

    - Acme uses cookie-based sessions: the browser never holds a bearer token directly. Every authenticated request hits /api/*, passes through a single verifyToken() middleware, and resolves to a Session row that downstream handlers read off req.ctx. The middleware is the only place that talks to the session store, which is the only place that talks to the sessions table — so there's exactly one trust boundary to reason about. -

    -
    - -
    -

    Request path

    -
    - - - - - - - - - - - Browser - acme.app - - - - /api/session - route handler - - - - verifyToken() - middleware/auth.ts - - - - - - SessionStore - lib/sessionStore.ts - - - - Postgres - sessions table - - - - - - - - - cookie - lookup - -
    - -

    Callstack walkthrough

    - - -
    -
    1
    -
    -
    src/app/providers/AuthProvider.tsx :22-48
    -

    On mount, the React provider issues a GET /api/session with credentials: 'include' so the fw_sid cookie rides along. The response either hydrates currentUser into context or leaves it null, which the router treats as "show the sign-in screen".

    -
    - show source -
    // src/app/providers/AuthProvider.tsx
    -export function AuthProvider({ children }: Props) {
    -  const [user, setUser] = useState<User | null>(null);
    -
    -  useEffect(() => {
    -    fetch('/api/session', { credentials: 'include' })
    -      .then(r => r.ok ? r.json() : null)
    -      .then(setUser);
    -  }, []);
    -
    -  return <AuthCtx.Provider value={{ user }}>{children}</AuthCtx.Provider>;
    -}
    -
    -
    -
    - - -
    -
    2
    -
    -
    src/server/routes/session.ts :9-27
    -

    The route itself is thin: it just returns whatever req.ctx.session the middleware attached. If the middleware short-circuited with a 401, this handler never runs — so there's no auth logic duplicated here.

    -
    - show source -
    // src/server/routes/session.ts
    -router.get('/session', verifyToken, (req, res) => {
    -  const { session } = req.ctx;
    -  res.json({
    -    id:    session.userId,
    -    email: session.email,
    -    role:  session.role,
    -    exp:   session.expiresAt,
    -  });
    -});
    -
    -
    -
    - - -
    -
    3
    -
    -
    src/middleware/auth.ts :14-31
    -

    This is the trust boundary. verifyToken reads the signed fw_sid cookie, asks SessionStore to resolve it, and either populates req.ctx.session or responds 401. Every protected route in the app is mounted behind this function, so changing its behaviour changes auth globally.

    -
    - show source -
    // src/middleware/auth.ts
    -export async function verifyToken(req, res, next) {
    -  const raw = req.signedCookies['fw_sid'];
    -  if (!raw) return res.status(401).end();
    -
    -  const session = await SessionStore.get(raw);
    -  if (!session || session.expiresAt < Date.now()) {
    -    return res.status(401).end();
    -  }
    -
    -  req.ctx = { session };
    -  next();
    -}
    -
    -
    -
    - - -
    -
    4
    -
    -
    src/lib/sessionStore.ts :8-52
    -

    SessionStore is a small read-through cache: it checks an in-process LRU first, then falls back to Postgres. Writes (create, revoke) always go straight to the DB and invalidate the cache entry so other workers don't serve a stale session.

    -
    - show source -
    // src/lib/sessionStore.ts
    -const cache = new LRU<string, Session>({ max: 5000, ttl: 60_000 });
    -
    -export const SessionStore = {
    -  async get(id: string) {
    -    const hit = cache.get(id);
    -    if (hit) return hit;
    -    const row = await db.one(SELECT_SESSION, [id]);
    -    if (row) cache.set(id, row);
    -    return row ?? null;
    -  },
    -  /* create, revoke, touch ... */
    -};
    -
    -
    -
    - - -
    -
    5
    -
    -
    db/migrations/004_sessions.sql :1-18
    -

    The sessions table is keyed on a random 32-byte id (the cookie value) with a covering index on user_id for "sign out everywhere". Expiry is enforced both here (expires_at) and again in the middleware as defence in depth.

    -
    - show source -
    -- db/migrations/004_sessions.sql
    -create table sessions (
    -  id          text primary key,
    -  user_id     uuid not null references users(id),
    -  created_at  timestamptz default now(),
    -  expires_at  timestamptz not null,
    -  ip          inet,
    -  user_agent  text
    -);
    -create index sessions_user_id_idx on sessions(user_id);
    -
    -
    -
    -
    - - - -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/05-design-system.html b/skills/html-diagram/references/html-effectiveness/05-design-system.html deleted file mode 100644 index da5460e..0000000 --- a/skills/html-diagram/references/html-effectiveness/05-design-system.html +++ /dev/null @@ -1,630 +0,0 @@ - - - - - - -Acme — Design System Reference - - - -
    - -
    -

    Acme design system

    -

    - Generated from src/styles/tokens.ts and src/components/ — use as a portable reference when prompting. -

    -
    - - -
    -

    Color

    -
    - -
    -
    Primary
    -
    -
    -
    - #D97757 - --clay -
    -
    -
    - #141413 - --slate -
    -
    -
    - #FAF9F5 - --ivory -
    -
    -
    - #E3DACC - --oat -
    -
    -
    - -
    -
    Neutral
    -
    -
    -
    - #FFFFFF - --white -
    -
    -
    - #F0EEE6 - --gray-100 -
    -
    -
    - #D1CFC5 - --gray-300 -
    -
    -
    - #87867F - --gray-500 -
    -
    -
    - #3D3D3A - --gray-700 -
    -
    -
    - -
    -
    Semantic
    -
    -
    -
    - #788C5D - --success -
    -
    -
    - #C78E3F - --warning -
    -
    -
    - #B04A4A - --danger -
    -
    -
    - #5C7CA3 - --info -
    -
    -
    -
    - - -
    -

    Typography

    -
    - -
    -
    -
    Plan the week ahead
    -
    - Display - 48 / 1.1 / 500 -
    -
    -
    -
    Plan the week ahead
    -
    - Heading 1 - 32 / 1.2 / 500 -
    -
    -
    -
    Plan the week ahead
    -
    - Heading 2 - 24 / 1.3 / 500 -
    -
    -
    -
    Review milestones, assign owners, and surface blockers before they cascade.
    -
    - Body - 16 / 1.55 / 430 -
    -
    -
    -
    Review milestones, assign owners, and surface blockers before they cascade.
    -
    - Small - 14 / 1.5 / 430 -
    -
    -
    -
    UPDATED 2 HOURS AGO
    -
    - Caption - 12 / 1.4 / 500 -
    -
    -
    -
    - - -
    -

    Spacing

    -
    - -
    -
    -
    -
    4--sp-1
    -
    -
    -
    -
    8--sp-2
    -
    -
    -
    -
    12--sp-3
    -
    -
    -
    -
    16--sp-4
    -
    -
    -
    -
    24--sp-5
    -
    -
    -
    -
    32--sp-6
    -
    -
    -
    -
    48--sp-7
    -
    -
    -
    -
    64--sp-8
    -
    -
    -
    - - -
    -

    Radius & Elevation

    -
    - -
    -
    -
    4px--r-xs
    -
    -
    -
    8px--r-sm
    -
    -
    -
    12px--r-md
    -
    -
    -
    20px--r-lg
    -
    -
    - -
    -
    -
    --shadow-sm0 1px 2px / 6%
    -
    -
    -
    --shadow-md0 4px 10px / 8%
    -
    -
    -
    --shadow-lg0 12px 28px / 12%
    -
    -
    -
    - - -
    -

    Core components

    -
    - -
    -
    <Button />
    -
    - - - - -
    -
    - -
    -
    <Input />
    -
    - - -
    -
    - -
    -
    <Checkbox />
    -
    - - -
    -
    - -
    -
    <Badge />
    -
    - Draft - In review - Done - Overdue -
    -
    -
    - -
    - - diff --git a/skills/html-diagram/references/html-effectiveness/06-component-variants.html b/skills/html-diagram/references/html-effectiveness/06-component-variants.html deleted file mode 100644 index 75debcf..0000000 --- a/skills/html-diagram/references/html-effectiveness/06-component-variants.html +++ /dev/null @@ -1,606 +0,0 @@ - - - - - - -Acme — Card Variant Matrix - - - -
    - -
    -

    Card variant matrix

    -

    Six structural treatments of the Acme <Card /> component. Adjust density and emphasis with the controls, hover a variant to see its prop combo.

    -
    - - -
    -
    - Padding - - 20px -
    - -
    - Border -
    - - - -
    -
    - -
    - -
    -
    - - -
    - - -
    - A · Flat -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: dense lists on tinted backgrounds

    -
    - - -
    - B · Outlined -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: default content cards on ivory

    -
    - - -
    - C · Elevated -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: draggable items, popovers

    -
    - - -
    - D · Accent stripe -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: pinned or priority items

    -
    - - -
    - E · Inset -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: nested cards inside white panels

    -
    - - -
    - F · Horizontal -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: compact row lists, sidebars

    -
    - -
    - - -
    -
    JSX — hover a variant above
    -
    // hover a card to preview its props
    -
    - -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/07-prototype-animation.html b/skills/html-diagram/references/html-effectiveness/07-prototype-animation.html deleted file mode 100644 index b63929e..0000000 --- a/skills/html-diagram/references/html-effectiveness/07-prototype-animation.html +++ /dev/null @@ -1,456 +0,0 @@ - - - - - - -Acme — Task completed micro-interaction - - - -
    - -
    -
    Acme / prototype / micro-interaction
    -

    Task completed

    -

    - A single click should feel like a tiny win. Circle fills, check draws, - label strikes, a small burst, then the row quietly steps back. Click - the row to play; click again to reset. -

    -
    - -
    - -
    -
    -
    - -
    - Send weekly digest - Fri -
    -
    -
    -
    -
    -
    -
    -
    click to toggle
    -
    - - - -
    - -
    -

    Keyframes

    -
    -
    fill0ms
    -
    check80ms
    -
    strike120ms
    -
    confetti200ms
    -
    collapse600ms
    -
    -
    - -
    -

    Copy-paste CSS

    -
    /* circle: clay flash, settle to olive with spring overshoot */
    -.task.done .check {
    -  animation: settle 380ms cubic-bezier(.34,1.56,.64,1) forwards;
    -}
    -@keyframes settle {
    -  0%   { transform: scale(.8);  background: #D97757; }
    -  55%  { transform: scale(1.18); }
    -  100% { transform: scale(1);   background: #788C5D; }
    -}
    -
    -/* checkmark draws via stroke-dashoffset, 80ms delay */
    -.check path        { stroke-dasharray: 20; stroke-dashoffset: 20;
    -                     transition: stroke-dashoffset 220ms var(--ease) 80ms; }
    -.task.done path    { stroke-dashoffset: 0; }
    -
    -/* strikethrough grows left → right */
    -.label::after      { width: 0; transition: width 240ms var(--ease) 120ms; }
    -.task.done .label::after { width: 100%; }
    -
    -/* row steps back after the celebration */
    -.task.done         { max-height: 44px; opacity: .6;
    -                     transition-delay: 600ms; }
    -
    - -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/08-prototype-interaction.html b/skills/html-diagram/references/html-effectiveness/08-prototype-interaction.html deleted file mode 100644 index fb8fde0..0000000 --- a/skills/html-diagram/references/html-effectiveness/08-prototype-interaction.html +++ /dev/null @@ -1,397 +0,0 @@ - - - - - - -Acme — Sidebar drag-to-reorder - - - -
    - -
    -
    Acme / prototype / interaction
    -

    Sidebar drag-to-reorder

    -

    - Throwaway HTML so we can feel the reorder before porting it to - React. Native dragstart / dragover / drop, - ~40 lines of JS, no libraries. Grab a row by the dots and move it. -

    -
    - -
    - -
    - -

    Order persists in the DOM only — refresh to reset.

    -
    - -
    -
    -

    What you're feeling

    -

    Design decisions baked into this prototype, so you can push back on them.

    -
      -
    • - Drop indicator snaps to the nearest gap, not the raw cursor Y. - It only moves when you cross a row's midpoint — feels more decisive, - less jittery. -
    • -
    • - Dragged row stays in place at 35% opacity with a 2° tilt. - Keeping the ghost in the list preserves your sense of where you - started; the tilt reads as "lifted." -
    • -
    • - Grip dots are the affordance, but the whole row is draggable. - Dots darken on hover to teach the gesture without forcing a - tiny hit target. -
    • -
    • - No auto-scroll, no drop animation. Left out on purpose so the - core feel is easy to judge — say the word and we add them next. -
    • -
    -
    - -
    -

    Open questions

    -
      -
    1. Should Trash (and maybe Archive) be pinned to the bottom and excluded from reordering?
    2. -
    3. Do we want rows to slide to their new slot on drop, or is the instant snap acceptable?
    4. -
    5. Keyboard path: is Alt + Arrow to move the focused row enough for the first ship?
    6. -
    -
    -
    - -
    -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/09-slide-deck.html b/skills/html-diagram/references/html-effectiveness/09-slide-deck.html deleted file mode 100644 index 61fd981..0000000 --- a/skills/html-diagram/references/html-effectiveness/09-slide-deck.html +++ /dev/null @@ -1,593 +0,0 @@ - - - - - - -Platform Eng — Week of Mar 10 - - - - - -
    -
    - -

    Platform Eng
    — Week of Mar 10

    -

    - What shipped, what's moving, and one decision we need from the - room before the Acme 2.4 cut. -

    - -
    -
    - - -
    -
    -
    Shipped this week
    -

    Three things out the door

    -
      -
    • - -
      -
      Bulk task import
      -
      - CSV and JSON uploads now land straight into a board with - column mapping — no more paste-and-pray. -
      -
      - #4211 -
    • -
    • - -
      -
      Webhook retries v2
      -
      - Exponential backoff with jitter; dead-letter queue surfaces - in the workspace admin panel. -
      -
      - #4188 #4203 -
    • -
    • - -
      -
      Postgres 16 migration
      -
      - All read replicas cut over Tuesday night; zero customer-facing - downtime, ~9% faster aggregate queries. -
      -
      - #4179 -
    • -
    -
    -
    - - -
    -
    -
    In progress
    -

    Carrying into next week

    -
      -
    • -
      - Recurring tasks engine - ~70% -
      -
      -

      - Scheduler and RRULE parsing are done; remaining work is the - timezone edge cases and the "skip holidays" toggle. -

      -
    • -
    • -
      - Audit log export - ~35% -
      -
      -

      - Streaming NDJSON endpoint is up behind a flag; still wiring - the S3 destination picker and retention policy UI. -

      -
    • -
    -
    -
    - - -
    -
    -
    Metrics
    -

    Numbers we watch

    - -
    -
    -
    API p95 latency
    -
    184ms
    -
    ↓ 12% wk/wk
    -
    -
    -
    Background job error rate
    -
    0.21%
    -
    ↓ 0.08pp
    -
    -
    - -
    - -
    - p95 latency, trailing 8 days — lower is better -
    -
    -
    -
    - - -
    -
    -
    Decision needed
    -

    One call to make

    - -
    -

    - Do we ship recurring tasks behind a workspace flag in 2.4, or - hold one more week for the timezone fixes? -

    -

    - Flagged rollout gets it to design partners Friday but means two - code paths for ~2 weeks. Holding keeps a single path but slips - the partner promise. -

    -
    - -
    - A — Flag it, ship Friday - B — Hold for 2.5 -
    -
    -
    - - -
    -
    -
    Next week
    -

    On deck

    -
      -
    • Finish recurring tasks — timezone matrix tests, then dogfood on the internal ops board.
    • -
    • Audit log export to private beta — three workspaces lined up.
    • -
    • Start scoping rate-limit headers for the public API; RFC draft by Thursday.
    • -
    -
    - Questions → drop them in the platform channel or grab anyone after standup. -
    -
    -
    - - -
    1 / 6
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/10-svg-illustrations.html b/skills/html-diagram/references/html-effectiveness/10-svg-illustrations.html deleted file mode 100644 index c408408..0000000 --- a/skills/html-diagram/references/html-effectiveness/10-svg-illustrations.html +++ /dev/null @@ -1,493 +0,0 @@ - - - - - - -Background jobs — header illustrations - - - -
    - -
    -

    Background jobs — header illustrations

    -

    - Three 720×320 hand-drawn SVGs for the Acme docs section on - background jobs. Flat fills, 1.5–2px strokes, palette-locked. Each - exports standalone via the button below it. -

    -
    720 × 320 · inline SVG · no external assets
    -
    - - -
    -
    - - - - - - - - - - - - queue - - - - - job 5 - - - job 4 - - - job 3 - - - job 2 - - - - job 1 - - - - - - - - worker - pool=4 - - - next to run - Jobs are pulled FIFO; the worker leases one at a time. - -
    -
    -
    -
    Queue
    -
    For "How jobs are picked up" — intro page header.
    -
    - -
    -
    - - -
    -
    - - - - - - - - - - t = 0 - time → - - - - - - - try 1 - - - - - - try 2 - - - - - - try 3 - - - - - try 4 - - - - +1s - - - +2s - - - +4s - - - Each failure waits twice as long before re-queuing; jitter not pictured. - -
    -
    -
    -
    Retry with backoff
    -
    For "Handling failures" — retry policy header.
    -
    - -
    -
    - - -
    -
    - - - - - - - - - - - - - enqueue - batch() - - - - - - - - - - - shard 0 - - - shard 1 - - - shard 2 - - - shard 3 - - - - - - - - - - - merge - await all - - - fan-out - fan-in - Parent job spawns N children, then blocks on a completion barrier. - -
    -
    -
    -
    Fan-out / fan-in
    -
    For "Batch and parallel work" — fan-out pattern header.
    -
    - -
    -
    - - -
    -

    Palette & rules

    - -
    -
    -
    -
    -
    ivory
    -
    #FAF9F5
    -
    -
    -
    -
    -
    -
    slate
    -
    #141413
    -
    -
    -
    -
    -
    -
    clay
    -
    #D97757
    -
    -
    -
    -
    -
    -
    olive
    -
    #788C5D
    -
    -
    -
    -
    -
    -
    oat
    -
    #E3DACC
    -
    -
    -
    -
    -
    -
    gray-150
    -
    #F0EEE6
    -
    -
    -
    -
    -
    -
    gray-300
    -
    #D1CFC5
    -
    -
    -
    -
    -
    -
    gray-500
    -
    #87867F
    -
    -
    -
    - -
      -
    • Strokes are 1.5px for neutral boxes, 2px for emphasised containers.
    • -
    • All rectangles use rx="10"; no drop shadows or gradients.
    • -
    • Labels inside boxes are 11px mono; annotations outside are 12px sans, gray-500.
    • -
    • Clay marks "the thing in focus"; olive marks "success / done".
    • -
    • Each SVG carries its own <style> block so the download stands alone.
    • -
    -
    - -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/11-status-report.html b/skills/html-diagram/references/html-effectiveness/11-status-report.html deleted file mode 100644 index 7f5ed34..0000000 --- a/skills/html-diagram/references/html-effectiveness/11-status-report.html +++ /dev/null @@ -1,529 +0,0 @@ - - - - - - -Acme — Engineering Status — Week 11 - - - -
    - -
    -
    -

    Engineering Status — Week 11

    - auto-generated -
    -
    - Mar 10 – Mar 16, 2025  ·  - acme/app @ main -
    -
    - - -
    -
    -
    -
    14
    -
    PRs merged
    -
    +3 vs wk10
    -
    -
    -
    6
    -
    Deploys
    -
    ±0
    -
    -
    -
    1
    -
    Incidents
    -
    SEV-2 · 47m
    -
    -
    -
    3
    -
    Flaky tests fixed
    -
    suite now 99.1%
    -
    -
    -
    - - -
    -

    Highlights

    -
    -
      -
    • - Bulk task editing shipped to 100%. The multi-select - toolbar landed behind a flag on Monday and ramped to all workspaces by - Thursday with no error-rate regression. -
    • -
    • - Sync API p95 down 38%. Replacing per-task auth checks - with a scoped batch lookup cut the hot path from 410ms to 255ms on the - staging load test. -
    • -
    • - One SEV-2 on Wednesday — a config rollout pushed - a bad connection-pool limit to the sync workers. Mitigated in 47 minutes; - full postmortem linked below. -
    • -
    -
    - - -
    -

    Shipped

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PRTitleAuthorRisk
    #4871Bulk edit toolbar: selection model + keyboard shortcutsMira OkaforMed
    #4874Batch auth lookup for /v2/sync hot pathDevon ParkMed
    #4878Fix race in attachment uploader retry loopSam ReyesLow
    #4879Migrate reminder scheduler to idempotent job keysPriya AnandHigh
    #4882Board view: collapse empty swimlanes by defaultMira OkaforLow
    #4885Quarantine 3 flaky webhook integration testsJules TanLow
    #4888Connection pool limits configurable per worker tierDevon ParkMed
    #4891Dark mode pass on settings & billing panelsNoor HalabiLow
    -
    - - -
    -

    Velocity

    -
    -
    - - - - - - - - - 0 - 1 - 2 - 3 - - - - - - - - - - - - - - - - - - - 2 - 3 - 1 - 4 - 2 - 1 - 1 - - - Mon - Tue - Wed - Thu - Fri - Sat - Sun - -
    - PRs merged per day. Thursday spike is the bulk-edit feature train (4 PRs landed together). -
    -
    -
    - - -
    -

    Carryover

    -
    -
    -
    - In review -
    - Workspace export to CSV — waiting on pagination review. - · Sam Reyes -
    -
    -
    - Blocked -
    - SSO group mapping — blocked on staging IdP credentials from IT. - · Priya Anand -
    -
    -
    - Slipped -
    - Mobile push reliability dashboard — deprioritized for incident follow-up. - · Devon Park -
    -
    -
    -
    - -
    - Sources: git log main..HEAD · CI dashboard · deploy log -  —  generated Mar 16 2025 18:02 -
    - -
    - - diff --git a/skills/html-diagram/references/html-effectiveness/12-incident-report.html b/skills/html-diagram/references/html-effectiveness/12-incident-report.html deleted file mode 100644 index ff06f1d..0000000 --- a/skills/html-diagram/references/html-effectiveness/12-incident-report.html +++ /dev/null @@ -1,597 +0,0 @@ - - - - - - -INC-2025-0412 — Elevated 502s on task sync - - - - - - -
    - -
    -
    INC-2025-0412
    -

    Elevated 502s on task sync

    -
    - SEV-2 - Resolved - Duration 47 min - Detected Apr 12 · 14:07 - Owner Devon Park -
    -
    - -
    -
    TL;DR
    -

    - A config rollout lowered the database connection-pool limit on the - sync-worker tier from 64 to 8, exhausting connections under - normal afternoon load. The sync API returned 502s for roughly 21% of - requests over 47 minutes. We mitigated by reverting the config and - cycling the worker fleet; no data was lost. -

    -
    - - -
    -

    Timeline

    -
    -
    - -
    - - 14:02 -
    - Config change cfg-9a12 promoted to - production via the standard rollout pipeline. -
    -
    - -
    - - 14:06 -
    - Impact starts. Sync workers begin queueing on pool - checkout; p95 latency climbs past 4s and the load balancer starts - returning 502s. -
    -
    - -
    - - 14:07 -
    - Alert fires: sync_5xx_rate > 2% for 60s. - On-call (Devon) acknowledges. -
    -
    - -
    - - 14:18 -
    - Initial hypothesis is a bad deploy of the API service; last two - application deploys are rolled back with no effect. -
    -
    - -
    - - 14:31 -
    - Mira joins and notices pool-wait saturation in the worker dashboard. - Investigation pivots to infra config rather than app code. -
    -
    - -
    - - 14:44 -
    - Mitigated. cfg-9a12 - reverted; worker fleet cycled. 5xx rate drops below 0.2% within - three minutes. -
    -
    - -
    - - 14:49 -
    - Monitors green for 5 minutes. Incident declared resolved; status - page updated. -
    -
    - -
    -
    - - -
    -

    Root cause

    -
    -

    - PR #4888 made connection-pool limits - configurable per worker tier. The default for the new - sync-worker key was meant to inherit the - global value (64) but was hard-coded to 8 during a local test and - committed. The config linter only validates type, not magnitude, so the - change passed CI. -

    -

    - Because config rollouts and code deploys go through separate pipelines, - the on-call's first instinct — rolling back the most recent - application deploys — had no effect and cost roughly 13 minutes of - diagnosis time. -

    - -
    - infra/config/workers.yaml -
    pool:
    -
    global_max_connections: 64
    -
    tiers:
    -
    - sync-worker: { max_connections: 64 }
    -
    + sync-worker: { max_connections: 8 } # debug value, do not ship
    -
    webhook-worker: { max_connections: 32 }
    -
    -
    - - -
    -

    Impact

    -
    - - - - - - - - - - - - - - - - - - - - - -
    Requests failed (502)~41,200
    Peak error rate21.4%
    Users affected~2,300 workspaces
    Data lossNone — clients retried
    SLA breachNo (within monthly budget)
    -
    - - -
    -

    Action items

    -
    -
    - -
    - - DP - Revert cfg-9a12 and restore pool limit to 64 - Apr 12 -
    - -
    - - MO - Add config-linter range check for max_connections (warn < 32) - Apr 18 -
    - -
    - - SR - Surface “recent config rollouts” alongside deploys in the on-call dashboard - Apr 25 -
    - -
    - - PA - Canary config changes to one worker AZ for 10 min before fleet-wide promote - May 02 -
    - -
    -
    - -
    - Authored from on-call notes + alert history · reviewed by Devon Park, Mira Okafor -
    - -
    - - diff --git a/skills/html-diagram/references/html-effectiveness/13-flowchart-diagram.html b/skills/html-diagram/references/html-effectiveness/13-flowchart-diagram.html deleted file mode 100644 index 8967f6e..0000000 --- a/skills/html-diagram/references/html-effectiveness/13-flowchart-diagram.html +++ /dev/null @@ -1,396 +0,0 @@ - - - - - - -Deploy pipeline — annotated flowchart - - - -
    - -
    -
    Illustrations & Diagrams · Flowchart
    -

    What happens when you git push

    -

    - The deploy pipeline for acme/web, drawn from .github/workflows/ and the - Argo manifests. Click any step to see what runs, how long it usually takes, and where it can short-circuit. -

    -
    - -
    - -
    -
    - - - - - - - - - - - - - - - - - - - pass - - fail → status - - - - healthy - - canary fails - - - - - - - git push main - - - - - CI · lint + typecheck - ~2 min · ci.yml - - - - - Unit + integration tests - ~6 min · 3 shards - - - - - pass? - - - - - Post failure status - slack #deploys - - - - - Build + push image - ghcr.io/acme/web - - - - - Argo canary 5% - 10 min soak - - - - - SLO ok? - - - - - Promote 25 → 50 → 100% - ~8 min - - - - - Auto-rollback - revert image tag - - - - - Smoke tests in prod - playwright · 90s - - - - - ✅ Deploy complete - - -
    - -
    - process step - decision - terminal success - failure path -
    -
    - - - -
    -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/14-research-feature-explainer.html b/skills/html-diagram/references/html-effectiveness/14-research-feature-explainer.html deleted file mode 100644 index aea9deb..0000000 --- a/skills/html-diagram/references/html-effectiveness/14-research-feature-explainer.html +++ /dev/null @@ -1,382 +0,0 @@ - - - - - - -How rate limiting works in acme/api - - - -
    - - - - - -
    -
    -
    Research & Learning · feature summary
    -

    How rate limiting works in acme/api

    -
    - TL;DR — Every request passes through rateLimit() middleware, which resolves the - caller to a bucket key, fetches a token-bucket from Redis, and either consumes one token or - returns 429. Limits are declared per-route in config/limits.yaml; routes - without an entry inherit the default tier (100 req/min per API key). -
    -
    - -

    The request path, step by step

    -

    Expand each step to see what runs and where it lives. The whole path is ~40 lines and adds about - 0.4 ms p50 to every request.

    - -
    - 1 · Identify the caller middleware/ratelimit.ts:21 -
    -

    The middleware first reduces the request to a bucketKey: API key if an - Authorization header is present, otherwise the client IP (via the - x-forwarded-for chain, trusting only our own LB). Anonymous IP traffic gets a much - lower default tier.

    -
    -
    - -
    - 2 · Look up the bucket lib/tokenBucket.ts:9 -
    -

    The route name plus bucket key map to a Redis hash (rl:{route}:{key}) holding - tokens and updatedAt. If the key is missing it's created lazily at full - capacity — there's no warm-up.

    -
    -
    - -
    - 3 · Refill and consume lib/tokenBucket.ts:31 -
    -

    Refill is computed from elapsed time (rate × Δt, capped at burst), then - one token is subtracted. The whole read-modify-write runs as a single Lua script so concurrent - requests can't double-spend.

    -
    -
    - -
    - 4 · Reject when empty middleware/ratelimit.ts:48 -
    -

    If the script returns tokens < 0 the middleware short-circuits with - 429 Too Many Requests and sets Retry-After to the seconds until one token - refills. Successful responses always carry X-RateLimit-Remaining.

    -
    -
    - -

    Configuring a limit on your route

    -

    You don't touch the middleware. Add an entry to config/limits.yaml keyed by route name, - and (optionally) tag the route so the middleware can find it.

    - -
    -
    - - - -
    -
    # config/limits.yaml
    -default:
    -  rate: 100/min
    -  burst: 120
    -
    -search.query:
    -  rate: 20/min
    -  burst: 40
    -  key: api_key        # or: ip
    -
    // routes/search.ts
    -router.post(
    -  "/search",
    -  rateLimit("search.query"),
    -  handler,
    -);
    -
    HTTP/1.1 429 Too Many Requests
    -Retry-After: 17
    -X-RateLimit-Limit: 20
    -X-RateLimit-Remaining: 0
    -
    -{ "error": "rate_limited", "retry_after": 17 }
    -
    - -
    - -
    If you only need the default tier, you don't need a YAML entry at all — just wrap the handler in - rateLimit() with no argument. The route name is inferred from the path.
    -
    - -

    Gotchas worth knowing

    -
      -
    • Limits are per-process in dev. The Redis client falls back to an - in-memory map when REDIS_URL is unset, so local testing won't reflect real cluster - behaviour.
    • -
    • Burst ≠ rate. burst is the bucket capacity; a caller - idle for a minute can fire burst requests instantly even if rate is low.
    • -
    • Streaming responses count once. The token is consumed at request start; a 30-second SSE - stream still costs one token.
    • -
    - -

    FAQ

    -
    -
    How do I exempt internal traffic?
    -
    Set x-acme-internal: 1 from the caller; the middleware checks it against the - mTLS peer name and skips the bucket entirely.
    - -
    Where do I see who's getting limited?
    -
    Every 429 emits a ratelimit.rejected metric tagged with route and key - type. There's a Grafana panel under API → Health.
    - -
    Can a single user have a higher limit?
    -
    Yes — add their API key under overrides: in the YAML. Overrides are reloaded without - a deploy.
    -
    -
    - -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/15-research-concept-explainer.html b/skills/html-diagram/references/html-effectiveness/15-research-concept-explainer.html deleted file mode 100644 index 192869d..0000000 --- a/skills/html-diagram/references/html-effectiveness/15-research-concept-explainer.html +++ /dev/null @@ -1,369 +0,0 @@ - - - - - - -Consistent hashing — an interactive explainer - - - -
    - -
    -
    Research & Learning · concept explainer
    -

    Consistent hashing, in one ring

    -

    - You have K keys spread across N cache servers. A server dies, or you add one. How many - keys have to move? With naive hash(key) mod N the answer is "almost all of them." Consistent - hashing gets it down to roughly K / N. Here's why. -

    - -

    The trick: hash onto a circle, not a line

    -

    - Map both nodes and keys onto the same - ring (the hash output space, wrapped around). A key belongs to - the first node found by walking clockwise from the key's position. When a node leaves, only the keys in - its arc reassign — to the next node round — and everything else - stays put. -

    - -
    -
    - -
    -
    - - - 4 -
    -
    - - - 32 -
    -
    - - - -
    -
    - 4 nodes · 32 keys · moved on last change -
    -
    -
    -
    -

    - Colored arcs show ownership. Removing a node hands its arc to its clockwise neighbor; every dot outside - that arc keeps its color. That's the whole idea. -

    - -

    Versus mod N

    - - - - - - - - -
    hash mod Nconsistent hashing
    Keys moved when N→N+1~ (N−1)/N of all keys~ 1/(N+1)
    Hot-spot riskeven by constructionuneven — fix with virtual nodes
    Lookup costO(1)O(log N) (binary search on ring)
    Used byarray sharding, simple LBDynamo, Cassandra, Memcached clients, Envoy
    - -

    Where you'll meet it

    -

    - Any time you're spreading state across a pool that changes size: cache fleets, partitioned queues, object - storage, request routing with sticky sessions. The - virtual-node variant (each physical node owns many small arcs - instead of one big one) is what production systems actually run, because it smooths out load and makes - rebalancing even gentler. -

    -
    - - - - -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/16-implementation-plan.html b/skills/html-diagram/references/html-effectiveness/16-implementation-plan.html deleted file mode 100644 index 483a826..0000000 --- a/skills/html-diagram/references/html-effectiveness/16-implementation-plan.html +++ /dev/null @@ -1,703 +0,0 @@ - - - - - - - Implementation plan — Comment threads on task cards - - - -
    - -
    -
    Implementation plan · Acme web client
    -

    Comment threads on task cards

    -
    - Prompt - Create a thorough implementation plan for adding threaded comments to - task cards. Include mockups, the data flow from client to persistence, - the key code I'll need to write, and a risk table. Make it easy to - skim on a phone — I'm going to pass this to the implementer as-is. -
    -
    - - - -
    -
    Effort
    ~2 weeks
    -
    Surfaces touched
    3 packages
    -
    New tables
    2
    -
    Feature flag
    task_comments_v1
    -
    - - - -
    -
    01

    Milestones

    -

    Ship in four slices, each independently reviewable and each behind the flag. Nothing is user-visible until slice 4.

    - -
    -
    -
    Week 1 · Mon–Tue
    -
    -
    -

    Schema & API contract

    -

    New comments and comment_reads tables, migrations, and the tRPC router stubs. No UI. Contract reviewed before anything else lands.

    -
    packages/dbpackages/apimigration 0042
    -
    -
    - -
    -
    Week 1 · Wed–Fri
    -
    -
    -

    Thread component & composer

    -

    Static <CommentThread> rendered from fixtures. Optimistic insert on submit, rollback on failure, one level of nesting only.

    -
    apps/webstorybook
    -
    -
    - -
    -
    Week 2 · Mon–Wed
    -
    -
    -

    Realtime fan-out & unread state

    -

    Subscribe the open card to its comment channel. Track per-user read cursors so the sidebar can show an unread count without a second query.

    -
    packages/realtimeapps/web
    -
    -
    - -
    -
    Week 2 · Thu–Fri
    -
    -
    -

    Notifications, flag ramp, docs

    -

    Mention detection → notification row, email digest fallback, ramp task_comments_v1 to internal, then 10% → 100% over three days.

    -
    packages/notifygrowthbook
    -
    -
    -
    -
    - - - -
    -
    02

    Data flow

    -

    Optimistic write path on the left, fan-out on the right. The read cursor update is fire-and-forget — we never block the thread render on it.

    - -
    - - - - - - - - - - - - - - <CommentComposer> - apps/web - - - React Query cache - optimistic insert - - - comments.create - tRPC · packages/api - - - comments table - postgres · packages/db - - - realtime channel - task:{id}:comments - - - Other viewers - subscribed cards - - - notify worker - @mentions → queue - - - - - - - - - - - - - - - - - - submit (id=temp) - mutate - INSERT + read cursor - enqueue - broadcast row - live append - reconcile temp id → real id - - -

    Solid = request/response path. Dashed clay = realtime fan-out. The composer never waits on the dashed path.

    -
    -
    - - - -
    -
    03

    Mockups

    -

    Not pixel-final — just enough that the reviewer and I agree on nesting depth, composer placement, and what the sidebar digest looks like.

    - -
    -
    -
    A · Thread inside an open task card
    -
    -
    -
    Ship onboarding empty-state rewrite
    -
    BIR-1142 · Assigned to Priya · Due Fri
    -
    -
    -
    -
    JM
    -
    -
    Jonah M. 2h ago
    -
    Should the illustration swap when the workspace already has one project? Feels odd to show the "start here" art twice.
    - -
    -
    -
    -
    PS
    -
    -
    Priya S. 40m ago
    -
    Good catch — I'll gate it on projects.count > 0 and fall back to the minimal variant.
    -
    -
    -
    -
    Add a comment…
    -
    Post
    -
    -
    -
    -
    -
    - -
    -
    B · Sidebar unread digest
    -
    -
    -
    -
    JM
    -
    Jonah commented on BIR-1142 — "Should the illustration swap when…"
    -
    -
    -
    AK
    -
    Aiko mentioned you on BIR-1098 — "@priya can you confirm the copy here?"
    -
    -
    -
    RW
    -
    Rowan replied on BIR-0971 — "Merged, thanks for the quick turnaround."
    -
    -
    -
    -
    -
    -
    - - - -
    -
    04

    Key code

    -

    The two pieces most likely to be done wrong: the migration (soft deletes, read cursors) and the optimistic mutation (temp-id reconciliation).

    - -
    -
    -
    packages/db/migrations/0042_comments.sql
    -
    create table comments (
    -  id          uuid primary key default gen_random_uuid(),
    -  task_id     uuid not null references tasks(id),
    -  parent_id   uuid references comments(id),   -- one level only,
    -                                                -- enforced in API
    -  author_id   uuid not null references users(id),
    -  body        text not null,
    -  created_at  timestamptz not null default now(),
    -  deleted_at  timestamptz                       -- soft delete
    -);
    -
    -create table comment_reads (
    -  task_id    uuid not null references tasks(id),
    -  user_id    uuid not null references users(id),
    -  read_up_to timestamptz not null,
    -  primary key (task_id, user_id)
    -);
    -
    -create index comments_task_created
    -  on comments (task_id, created_at);
    -
    - -
    -
    apps/web/hooks/useAddComment.ts
    -
    export function useAddComment(taskId: string) {
    -  const qc = useQueryClient();
    -  return trpc.comments.create.useMutation({
    -    onMutate: async (input) => {
    -      const temp = { ...input, id: `temp-${nanoid()}`,
    -                     createdAt: new Date(), pending: true };
    -      qc.setQueryData(key(taskId), (prev) =>
    -        [...(prev ?? []), temp]);
    -      return { tempId: temp.id };
    -    },
    -    onSuccess: (row, _v, ctx) => {
    -      // reconcile temp id → real id so the
    -      // realtime append doesn't duplicate it
    -      qc.setQueryData(key(taskId), (prev) =>
    -        prev.map((c) => c.id === ctx.tempId ? row : c));
    -    },
    -    onError: (_e, _v, ctx) => {
    -      qc.setQueryData(key(taskId), (prev) =>
    -        prev.filter((c) => c.id !== ctx.tempId));
    -    },
    -  });
    -}
    -
    -
    -
    - - - -
    -
    05

    Risks & mitigations

    -
    -
    -
    Risk
    -
    Sev
    -
    Mitigation
    -
    -
    -
    Realtime duplicate: socket append races with the HTTP response and the temp-id reconcile.
    -
    HIGH
    -
    Dedupe on server-assigned id in the cache updater; socket payload carries the real id, temp rows are filtered on reconcile.
    -
    -
    -
    Unread counts go stale when a user reads the thread on another device.
    -
    MED
    -
    Broadcast comment_reads upserts on the same channel; client treats its own cursor as max(local, remote).
    -
    -
    -
    Mention detection false-positives on pasted markdown (@media, @2x).
    -
    LOW
    -
    Resolve mentions against workspace members only, at write time, and store the resolved user ids — never re-parse on read.
    -
    -
    -
    - - - -
    -
    06

    Open questions

    -
    -
    -
    Do we allow editing, or only delete-and-repost?
    -
    Editing needs an edited_at column and an "edited" affordance. Delete-and-repost is simpler but loses the reply anchor. Leaning toward delete-only for v1.
    -
    Decide with · design, before slice 2
    -
    -
    -
    Email digest cadence when a user has the app closed
    -
    Immediate-per-mention will be noisy. Proposal: batch on a 15-minute window, collapse to one email per task, and respect quiet hours from the existing settings table.
    -
    Decide with · platform, before slice 4
    -
    -
    -
    - -
    - - diff --git a/skills/html-diagram/references/html-effectiveness/17-pr-writeup.html b/skills/html-diagram/references/html-effectiveness/17-pr-writeup.html deleted file mode 100644 index 34c60d0..0000000 --- a/skills/html-diagram/references/html-effectiveness/17-pr-writeup.html +++ /dev/null @@ -1,596 +0,0 @@ - - - - - - - PR #312 — Move notification delivery onto a queue - - - -
    - -
    -
    Pull request · Acme
    -

    #312 — Move notification delivery onto a queue

    -
    - 9 files - +418 / −190 - branch notify-queuemain - author @priya -
    -
    - Prompt - Write up PR #312 for my reviewers. Explain the motivation, walk them - through the change file by file with the why for each, show - before/after behavior, and tell them exactly where to focus. They - haven't touched the notification code in six months. -
    -
    - -
    -
    - -
    -
    TL;DR
    -

    Notification sends were happening inline in the request path. Under load they added 200–800 ms to mutation latency and silently dropped emails when the SMTP pool was exhausted. This PR moves delivery onto the existing pg-boss queue so the API returns immediately and failed sends retry with backoff.

    -
    - - - -
    -

    Why

    -

    When we added @mentions in comments last quarter, every mention started triggering up to three sends (in-app, email, Slack) inside the same transaction that saved the comment. That was fine at launch. It is not fine now that a single task update can fan out to forty watchers.

    - -
    -
    -
    Before
    -
      -
    • Sends run inline in the mutation handler
    • -
    • SMTP timeout = 500 error for the comment
    • -
    • No retries — a dropped email is gone
    • -
    • p99 on comments.create: 1.4 s
    • -
    -
    -
    -
    After
    -
      -
    • Handler enqueues one job per recipient, returns
    • -
    • Worker retries 3× with exponential backoff
    • -
    • Dead-letter table for inspection after exhaustion
    • -
    • p99 on comments.create: 180 ms (staging)
    • -
    -
    -
    -
    - - - -
    -

    File-by-file

    -

    Ordered for reading, not alphabetically. Start at the worker — it's the new thing — then the enqueue call site, then the plumbing.

    - -
    - -
    - - - packages/notify/src/worker.ts - new - +126 - -
    -

    The heart of the PR. A pg-boss subscriber that pulls notify.deliver jobs, resolves the user's channel preferences, and calls the right adapter. Retries are configured per-channel — email gets three attempts, Slack gets one because its API is already idempotent on our side.

    -
    boss.work('notify.deliver', { batchSize: 20 }, async (jobs) => {
    -  for (const job of jobs) {
    -    const { userId, event, channel } = job.data;
    -    const prefs = await getPrefs(userId);
    -    if (!prefs[channel]) return;          // user muted this channel
    -
    -    try {
    -      await adapters[channel].send(userId, event);
    -    } catch (err) {
    -      if (job.retryCount >= MAX_RETRY[channel]) {
    -        await deadLetter(job, err);         // don't throw — ack & park
    -        return;
    -      }
    -      throw err;                            // pg-boss reschedules
    -    }
    -  }
    -});
    -
    -
    - -
    - - - packages/api/src/routers/comments.ts - mod - +14 −62 - -
    -

    Where the win shows up. The mutation used to call sendEmail, sendSlack, and createInApp directly. Now it inserts the comment, computes recipients, and enqueues. The try/catch soup is gone.

    -
      const comment = await db.comments.insert(input);
    -  const recipients = await resolveWatchers(input.taskId, input.mentions);
    -
    -  for (const r of recipients) {
    -    await sendEmail(r, comment);       // blocked the response
    -    await sendSlack(r, comment);
    -  }
    -  await boss.insert(recipients.flatMap((r) =>
    -    CHANNELS.map((ch) => ({
    -      name: 'notify.deliver',
    -      data: { userId: r.id, channel: ch, event: toEvent(comment) },
    -      singletonKey: `${comment.id}:${r.id}:${ch}`,  // idempotent
    -    }))));
    -  return comment;
    -
    -
    - -
    - - - packages/db/migrations/0051_dead_letter.sql - new - +22 - -
    -

    Table for jobs that exhaust their retries. Deliberately not auto-pruned — we want to look at these weekly until we trust the new path. Has the full job payload and the last error string.

    -
    -
    - -
    - - - packages/notify/src/adapters/{email,slack,inapp}.ts - mod - +88 −74 - -
    -

    Mostly moves. Each adapter now implements a shared Adapter interface and throws a typed RetryableError or PermanentError so the worker knows whether to retry. The email adapter also drops its internal retry loop — the queue owns retries now, double-retrying was how we got duplicate emails in April.

    -
    -
    - -
    - - - apps/worker/src/index.ts, infra/fly.toml - mod - +31 −4 - -
    -

    Registers the new subscriber in the existing worker process and bumps its concurrency from 5 → 20. No new deploy unit.

    -
    -
    - -
    - - - packages/notify/src/__tests__/worker.test.ts - new - +137 - -
    -

    Covers the retry boundary, the dead-letter path, channel muting, and the singleton key dedupe. Uses a real pg-boss against the test database — we got burned last quarter when mocked queue tests passed but prod ordering broke.

    -
    -
    - -
    -
    - - - -
    -

    Where to focus your review

    -
    -
    -
    1
    -
    -
    The retry / dead-letter boundary
    -
    worker.ts:31–44. I catch, check retryCount, and either park or rethrow. If this logic is wrong we either retry forever or drop messages — the two failure modes this PR exists to fix.
    -
    -
    -
    -
    2
    -
    -
    The singleton key
    -
    comments.ts:28. ${commentId}:${userId}:${channel} should make re-enqueues idempotent if the API handler retries. Sanity-check that this can't collide across tasks.
    -
    -
    -
    -
    3
    -
    -
    What I deliberately did not do
    -
    No per-user digest batching, no delivery receipts, no priority lanes. All of those layer on top of this cleanly; bundling them would make this unreviewable.
    -
    -
    -
    -
    - - - -
    -

    Test plan

    -
    -
    Unit: retry → dead-letter path, channel mute, singleton dedupe
    packages/notify — 14 cases, real pg-boss on test db
    -
    Integration: create comment with 3 watchers, assert 9 jobs enqueued and drained
    -
    Staging load: 500 rps on comments.create for 10 min, p99 = 180 ms
    was 1.4 s before — dashboard linked in the PR description
    -
    Manual: kill SMTP mid-burst, confirm jobs land in dead-letter and nothing 500s
    will do during the 10% ramp
    -
    -
    - - - -
    -

    Rollout

    -

    Behind notify_queue_v2. The old inline path stays in the codebase, dead but dormant, for one release in case we need to flip back.

    -
    -
    Day 0
    internal
    Acme team only. Watch dead-letter table + worker error rate.
    -
    Day 2
    10%
    Random sample. Alert if dead-letter rate > 0.5% of sends.
    -
    Day 4
    100%
    Ramp fully, delete the inline path in a follow-up PR next week.
    -
    -
    - -
    - - -
    - -
    - - diff --git a/skills/html-diagram/references/html-effectiveness/18-editor-triage-board.html b/skills/html-diagram/references/html-effectiveness/18-editor-triage-board.html deleted file mode 100644 index ae4dbb0..0000000 --- a/skills/html-diagram/references/html-effectiveness/18-editor-triage-board.html +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - -Acme — Cycle 14 triage - - - -
    - -
    -
    Acme / editor / triage
    -

    Cycle 14 triage

    -

    - Twenty-four open Linear tickets, pre-sorted into a best guess. Drag them - across Now / Next / Later / Cut until the cut feels right, then copy the - result back into the planning doc as markdown. -

    -
    drag tickets between columns  ·  click a tag to filter
    -
    - -
    -
    -
    - - - -
    - -
    - -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/19-editor-feature-flags.html b/skills/html-diagram/references/html-effectiveness/19-editor-feature-flags.html deleted file mode 100644 index 15be394..0000000 --- a/skills/html-diagram/references/html-effectiveness/19-editor-feature-flags.html +++ /dev/null @@ -1,664 +0,0 @@ - - - - - - -Acme — flags.production.json - - - -
    - -
    -
    Acme / editor / feature-flags
    -

    flags.production.json

    -

    A form-based editor for the production feature-flag config. - Toggle flags, fix dependency warnings as they surface, then copy out - only the lines that changed.

    -
    - -
    - - -
    - - -
    - -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/20-editor-prompt-tuner.html b/skills/html-diagram/references/html-effectiveness/20-editor-prompt-tuner.html deleted file mode 100644 index 7a27d03..0000000 --- a/skills/html-diagram/references/html-effectiveness/20-editor-prompt-tuner.html +++ /dev/null @@ -1,723 +0,0 @@ - - - - - - -Acme — Support reply prompt tuner - - - -
    - -
    -
    Acme / editor / prompt-tuner
    -

    Support reply draft prompt

    -

    Edit the system prompt on the left and watch three sample tickets re-render the filled template on the right, live as you type. When it reads well across all three moods, copy the template out.

    -
    - -
    - - -
    -
    slots use {{double_brace}} syntax
    -
    - -
    - - -
    -
    - Template -
    - 0 chars · ~0 tokens -
    -
    -
    -
    Available slots
    -
    -
    -
    - - -
    -
    Live preview · 3 sample tickets
    -
    -
    - -
    - -
    Highlighted slots fill from each sample's ticket fields. Anything underlined in dashed clay isn't a known field and will pass through unfilled.
    - -
    - - - - diff --git a/skills/html-diagram/references/html-effectiveness/CODE_OF_CONDUCT.md b/skills/html-diagram/references/html-effectiveness/CODE_OF_CONDUCT.md deleted file mode 100644 index 91bac7d..0000000 --- a/skills/html-diagram/references/html-effectiveness/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,49 +0,0 @@ -# Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment include: - -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -- Focusing on what is best for the overall community - -Examples of unacceptable behavior include: - -- The use of sexualized language or imagery, and sexual attention or advances of - any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email address, - without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the project maintainers at **opensource@anthropic.com**. All -complaints will be reviewed and investigated promptly and fairly. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.1, available at -https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. - -[homepage]: https://www.contributor-covenant.org diff --git a/skills/html-diagram/references/html-effectiveness/LICENSE b/skills/html-diagram/references/html-effectiveness/LICENSE deleted file mode 100644 index 02fe842..0000000 --- a/skills/html-diagram/references/html-effectiveness/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2026 Anthropic PBC - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/skills/html-diagram/references/html-effectiveness/README.md b/skills/html-diagram/references/html-effectiveness/README.md deleted file mode 100644 index aace658..0000000 --- a/skills/html-diagram/references/html-effectiveness/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# The unreasonable effectiveness of HTML — examples - -> **Sample code. Not maintained and not accepting contributions.** - -A gallery of standalone HTML examples that accompany the blog post on using HTML -as a flexible output format. Each file is a self-contained `.html` page (no build -step, no dependencies) demonstrating a different use case — from code review and -design systems to slide decks, status reports, and small interactive editors. - -Open [`index.html`](index.html) for the full, categorized index, or open any -numbered file directly in a browser. - -## Contents - -| Category | Examples | -|---|---| -| Exploration | code approaches, visual designs | -| Code | review, understanding, design systems, component variants | -| Prototyping | animation, interaction | -| Communication | slide deck, status report, incident report, PR write-up | -| Diagrams & research | flowchart, feature/concept explainers | -| Custom editing UIs | triage board, feature flags, prompt tuner | - -## Running - -There is nothing to install or build. Clone the repo and open `index.html` (or -any individual file) in a web browser. - -## A note on sample data - -All product names, data, and scenarios in these examples are fictional and used -only for illustration. The placeholder brand "Acme" and any figures shown are -not real. - -## Security - -See [SECURITY.md](SECURITY.md) for how to report a vulnerability. - -## License - -Released under the [Apache License 2.0](LICENSE). diff --git a/skills/html-diagram/references/html-effectiveness/SECURITY.md b/skills/html-diagram/references/html-effectiveness/SECURITY.md deleted file mode 100644 index 70e008f..0000000 --- a/skills/html-diagram/references/html-effectiveness/SECURITY.md +++ /dev/null @@ -1,22 +0,0 @@ -# Security Policy - -## Reporting a vulnerability - -If you believe you have found a security vulnerability in this repository, -please report it responsibly. - -- **Do not** open a public issue for security problems. -- Email **security@anthropic.com** with a description of the issue and steps to - reproduce it. - -We will acknowledge your report, investigate, and keep you informed of the -resolution. - -## Scope - -This repository contains static, self-contained HTML example files with no -server-side components, no build pipeline, and no third-party runtime -dependencies. The most likely relevant reports are issues such as unsafe inline -script behavior or content that could mislead a reader. General questions about -the accompanying blog post are not security issues — please use normal issues -for those. diff --git a/skills/html-diagram/references/html-effectiveness/index.html b/skills/html-diagram/references/html-effectiveness/index.html deleted file mode 100644 index 4b06272..0000000 --- a/skills/html-diagram/references/html-effectiveness/index.html +++ /dev/null @@ -1,823 +0,0 @@ - - - - - - -The unreasonable effectiveness of HTML — examples - - - -
    - -
    -
    -
    -
    Companion to the blog post
    -

    The unreasonable effectiveness of HTML

    -

    - Twenty self-contained .html files an agent produced instead of a wall of markdown. - Each one trades a document you'd skim for one you'd actually read — open any of them directly in - a browser. Grouped by the kind of work they replace. -

    - -
    - -
    -
    - - -
    -
    01

    Exploration & Planning

    3 demos
    -

    - When you're not sure what you want yet. Ask the agent to fan out across several directions and lay - them next to each other so you can point at one — instead of reading three sequential walls of text - and trying to hold them all in your head. And once you've picked, turn the pick into a plan the - implementer can actually read. -

    - -
    - - -
    -
    02

    Code Review & Understanding

    3 demos
    -

    - Diffs and call-graphs are spatial information; markdown flattens them. Let the agent render the - change as an annotated diff, draw the module as boxes and arrows, or write the PR description your - reviewers actually want — so the shape of the code is visible at a glance. -

    - -
    - - -
    -
    03

    Design

    2 demos
    -

    - HTML is the medium your design system ships in, so it's the natural format for talking about - it. Tokens become swatches, components become contact sheets, and the artifact can be fed straight - back into the next prompt. -

    - -
    - - -
    -
    04

    Prototyping

    2 demos
    -

    - Motion and interaction can't be described, only felt. A throwaway page with the real easing curve or - the real click-through tells you in five seconds what a paragraph of prose never could. -

    - -
    - - -
    -
    05

    Illustrations & Diagrams

    2 demos
    -

    - Inline SVG gives the agent a real pen. Ask for the figures for a post or a flowchart of a process and - get vector art you can tweak by hand or paste straight into the final document. -

    - -
    - - -
    -
    06

    Decks

    1 demo
    -

    - A handful of <section> tags and twenty lines of JS is a slide deck. Point the agent at a - Slack thread or a design doc and get something you can arrow-key through in a meeting — no Keynote, - no export step. -

    - -
    - - -
    -
    07

    Research & Learning

    2 demos
    -

    - An explainer with collapsible sections, tabbed code samples and a glossary in the margin reads very - differently from the same words dumped linearly. The agent can build the scaffolding that makes a new - topic navigable. -

    - -
    - - -
    -
    08

    Reports

    2 demos
    -

    - Recurring documents — status updates, post-mortems — benefit most from a bit of structure and color. - A small chart and a colored timeline turn something people skim into something they actually read. -

    - -
    - - -
    -
    09

    Custom Editing Interfaces

    3 demos
    -

    - Sometimes it's hard to describe what you want in a text box. Ask for a throwaway editor for the exact - thing you're working on — and always end with an export button that turns whatever you did in the UI - back into something you can paste into the agent or commit. You stay in the loop; the loop gets tighter. -

    - -
    - - - -
    - - diff --git a/skills/html-plan/SKILL.md b/skills/html-plan/SKILL.md index fbd3b66..64380d3 100644 --- a/skills/html-plan/SKILL.md +++ b/skills/html-plan/SKILL.md @@ -1,15 +1,40 @@ --- name: html-plan -description: Create a self-contained HTML plan that is pragmatic, simple, and visually organized. Use when the user wants a plan page in the effective HTML style, wants the writing kept close to what they gave you, or wants the grammar cleaned up without turning it into a whole bigger thing. -disable-model-invocation: true +description: Direct-invocation specialist for clear, self-contained HTML plans that preserve source material while improving hierarchy, sequence, ownership, dependencies, and reviewability. Use when the user explicitly invokes html-plan or the broad html skill routes a plan request here. Do not activate independently from a general request. --- # HTML Plan -Review the files throughout `references/html-effectiveness/`. +Turn source material into a plan people can inspect and act on. Preserve the user's scope, ordering, commitments, and terminology unless they ask for broader synthesis. -After reviewing them, create an HTML file for the plan in a similar style. +## Shape the document around the work -Keep it pragmatic and simple. +Read the conversation, project instructions, and supplied plan before designing. Match an existing design language when one is present. Otherwise derive a quiet, workmanlike direction from the audience and subject. -Always include dark mode: hand-rolled CSS variables on `:root` / `html.dark`, a small theme toggle button, `localStorage` persistence, and an apply-before-paint script in `` (default to `prefers-color-scheme`). +Decide what the plan actually needs: + +- phases or sequence; +- status and decision points; +- owners and collaborators; +- dependencies and risks; +- acceptance checks; +- unresolved questions. + +Do not add a timeline, progress percentage, status badge, or dashboard summary unless the source supports it. Improve grammar and structure without inflating an implementation plan into a strategy document. + +## Preserve traceability + +- Keep source commitments recognizable. +- Separate accepted decisions from assumptions and open questions. +- Show sequence and dependency only where they are real. +- Use tables for exact mappings, comparisons, or repeated fields. +- Use a flow or timeline only when it makes order materially easier to understand. +- Keep long prose readable instead of forcing every paragraph into a card. + +## Build and verify + +Deliver one responsive, accessible, self-contained HTML file. Use semantic headings, lists, tables, and landmarks. Keep essential CSS and JavaScript inline, avoid external services, and make any navigation or disclosure keyboard-operable. + +Inspect the result at wide and narrow widths. Check that no commitment disappeared, that stages remain in the intended order, that ownership and dependencies are legible, and that long content does not overflow. + +Return the absolute path and note any structural interpretation you introduced. diff --git a/skills/html-plan/agents/openai.yaml b/skills/html-plan/agents/openai.yaml index 6a17c9d..1d52494 100644 --- a/skills/html-plan/agents/openai.yaml +++ b/skills/html-plan/agents/openai.yaml @@ -1,7 +1,7 @@ interface: display_name: "HTML Plan" - short_description: "Create pragmatic visual HTML plans" - default_prompt: "Use $html-plan to create a pragmatic HTML plan." + short_description: "Direct skill for clear HTML working plans" + default_prompt: "Use $html-plan to turn this source material into a clear, self-contained HTML plan." policy: allow_implicit_invocation: false diff --git a/skills/html-plan/references/html-effectiveness/01-exploration-code-approaches.html b/skills/html-plan/references/html-effectiveness/01-exploration-code-approaches.html deleted file mode 100644 index fc0c648..0000000 --- a/skills/html-plan/references/html-effectiveness/01-exploration-code-approaches.html +++ /dev/null @@ -1,454 +0,0 @@ - - - - - - - Debounced search — three approaches - - - -
    - -
    -
    Exploration · Acme web client
    -

    Three ways to implement debounced search

    -
    - Prompt - Show me three different ways to implement debounced search for the task - filter input in our React codebase, with tradeoffs for each. -
    -
    - - - -
    - - -
    -
    -

    01Inline useEffect + setTimeout

    -

    Debounce logic lives directly inside the component that owns the input.

    -
    - -
    export function TaskSearch() {
    -  const [draft, setDraft] = useState('');
    -  const [query, setQuery] = useState('');
    -
    -  useEffect(() => {
    -    const id = setTimeout(() => setQuery(draft), 300);
    -    return () => clearTimeout(id);
    -  }, [draft]);
    -
    -  const { data } = useTasks({ search: query });
    -
    -  return (
    -    <input
    -      value={draft}
    -      onChange={(e) => setDraft(e.target.value)}
    -      placeholder="Filter tasks…"
    -    />
    -  );
    -}
    - -
    -
    -
    Pro
    -
    Con
    -
    -
    -
    Zero new abstractions to learn
    -
    Logic duplicated everywhere search exists
    -
    -
    -
    Easy to step through in devtools
    -
    Two pieces of state for one conceptual value
    -
    -
    -
    No dependency or bundle change
    -
    Delay constant is buried in component body
    -
    -
    - -
    - Bundle impact: +0 kb - Testability: medium - Reuse: low - SSR safe: yes -
    -
    - - -
    -
    -

    02Custom useDebounce hook

    -

    Extract the timer into a shared hook under src/hooks/.

    -
    - -
    // src/hooks/useDebounce.ts
    -export function useDebounce<T>(value: T, ms = 300): T {
    -  const [debounced, setDebounced] = useState(value);
    -  useEffect(() => {
    -    const id = setTimeout(() => setDebounced(value), ms);
    -    return () => clearTimeout(id);
    -  }, [value, ms]);
    -  return debounced;
    -}
    -
    -// TaskSearch.tsx
    -const [draft, setDraft] = useState('');
    -const query = useDebounce(draft, 300);
    -const { data } = useTasks({ search: query });
    - -
    -
    -
    Pro
    -
    Con
    -
    -
    -
    Single import reused across filter, command bar, board search
    -
    One more file to maintain and document
    -
    -
    -
    Trivial to unit test with fake timers
    -
    Generic T hides intent slightly
    -
    -
    -
    Delay is a visible, tunable argument
    -
    Still re-renders on every keystroke
    -
    -
    - -
    - Bundle impact: +0.2 kb - Testability: high - Reuse: high - SSR safe: yes -
    -
    - - -
    -
    -

    03Tiny external library

    -

    Adopt use-debounce for both values and callbacks.

    -
    - -
    import { useDebouncedCallback }
    -  from 'use-debounce';
    -
    -export function TaskSearch() {
    -  const [query, setQuery] = useState('');
    -
    -  const onChange = useDebouncedCallback(
    -    (next: string) => setQuery(next),
    -    300,
    -    { leading: false, maxWait: 1000 },
    -  );
    -
    -  const { data } = useTasks({ search: query });
    -
    -  return (
    -    <input
    -      defaultValue=""
    -      onChange={(e) => onChange(e.target.value)}
    -    />
    -  );
    -}
    - -
    -
    -
    Pro
    -
    Con
    -
    -
    -
    leading / trailing / maxWait handled for us
    -
    New runtime dependency to audit and update
    -
    -
    -
    Callback form skips intermediate re-renders
    -
    Uncontrolled input diverges from Acme form patterns
    -
    -
    -
    Well-tested edge cases (unmount, flush, cancel)
    -
    ~1.4 kb gzipped for something we could own
    -
    -
    - -
    - Bundle impact: +1.4 kb - Testability: high - Reuse: high - SSR safe: yes -
    -
    - -
    - - - - - -
    - - diff --git a/skills/html-plan/references/html-effectiveness/02-exploration-visual-designs.html b/skills/html-plan/references/html-effectiveness/02-exploration-visual-designs.html deleted file mode 100644 index 817fcc3..0000000 --- a/skills/html-plan/references/html-effectiveness/02-exploration-visual-designs.html +++ /dev/null @@ -1,516 +0,0 @@ - - - - - - - Empty state — four visual directions - - - - -
    -
    Acme · design exploration
    -
    - Background: -
    - - -
    -
    -
    - -
    - -
    -
    Exploration · Empty states
    -

    Four visual directions for the “no tasks yet” state

    -
    - Prompt - Explore four visual directions for our empty-state component. Render each - live so we can compare tone, density, and how well they hold up on light - and dark surfaces. -
    -
    - -
    - - -
    - A — Minimal -
    -
    -

    No tasks yet

    -

    When you create a task it will show up here.

    - New task -
    -
    -

    - Pure typography, single quiet action. Reads as calm and confident; - assumes the surrounding UI already carries enough personality. -

    -
    - - -
    - B — Illustrated -
    -
    - -

    Start your first list

    -

    Group related work and watch progress roll up automatically.

    - Create a task -
    -
    -

    - A small geometric spot illustration anchors the eye and explains the - object model (lists contain tasks) without a wall of copy. -

    -
    - - -
    - C — Playful -
    -
    -
    -
    -
    -
    -
    -
    -

    Nothing on your plate

    -

    Enjoy the quiet, or add something to get moving.

    -
    -
    -

    - A gently bobbing stack adds life to an otherwise static screen. Motion - is subtle enough to loop indefinitely without drawing complaints. -

    -
    - - -
    - D — Instructional -
    -
    -

    Set up this project

    -
      -
    1. - Create your first task - Give it a name and an owner. -
    2. -
    3. - Add a due date - Acme will surface it on the timeline. -
    4. -
    5. - Invite a teammate - Shared projects stay in sync automatically. -
    6. -
    -
    -
    -

    - Treats the empty state as onboarding. Higher density, but every line is - actionable — best when the user is new to the product, not just the view. -

    -
    - -
    -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/03-code-review-pr.html b/skills/html-plan/references/html-effectiveness/03-code-review-pr.html deleted file mode 100644 index bfb344b..0000000 --- a/skills/html-plan/references/html-effectiveness/03-code-review-pr.html +++ /dev/null @@ -1,639 +0,0 @@ - - - - - - -PR #247 — Review Summary - - - -
    - -
    -
    acme/web · Pull Request #247
    -

    Add optimistic updates to task list mutations

    -
    -
    -
    MO
    -
    -
    Mira Okafor
    -
    opened 2 days ago
    -
    -
    -
    - mo/optimistic-tasks main -
    -
    - +142 / −38 - 6 files changed -
    -
    -
    - -
    -

    What this PR does

    -
      -
    • Replaces the await-then-refetch pattern in TaskList with optimistic cache writes, so toggling or reordering a task feels instant instead of waiting ~300ms for the round-trip.
    • -
    • Introduces a small useOptimisticTasks hook that wraps the mutation, snapshots the previous list, and rolls back on error.
    • -
    • Extends the API client to accept an idempotency key per mutation and adds a toast when a rollback fires.
    • -
    -
    - -
    -

    Risk map

    - -
    - safe - worth a look - needs attention -
    -
    - -
    -

    Files

    - - -
    -
    -
    -
    src/hooks/useOptimisticTasks.ts
    -
    -
    - needs attention - +58 −0 -
    -
    -
    -
    @@ -0,0 +1,58 @@
    -
    1+import { useMutation, useQueryClient } from '@tanstack/react-query';
    -
    2+import { updateTask, TaskPatch } from '../api/tasks';
    -
    3+import type { Task } from '../types/task';
    -
    4+
    -
    5+export function useOptimisticTasks(boardId: string) {
    -
    6+ const qc = useQueryClient();
    -
    7+ const key = ['tasks', boardId];
    -
    8+
    -
    9+ return useMutation({
    -
    10+ mutationFn: (patch: TaskPatch) => updateTask(patch),
    -
    11+ onMutate: async (patch) => {
    -
    12+ const prev = qc.getQueryData<Task[]>(key);
    -
    13+ qc.setQueryData<Task[]>(key, (old = []) =>
    -
    14+ old.map(t => t.id === patch.id ? { ...t, ...patch } : t)
    -
    15+ );
    -
    16+ return { prev };
    -
    17+ },
    -
    18+ onError: (_e, _p, ctx) => qc.setQueryData(key, ctx?.prev),
    -
    19+ });
    -
    20+}
    -
    -
    -
    -
    line 11
    -

    BlockingonMutate doesn't call qc.cancelQueries(key) first. If a background refetch lands between the optimistic write and the server response, it will clobber the optimistic state and the UI will flicker back to the old value.

    -
    -
    -
    line 18
    -

    NitRollback restores the list but never surfaces the error. Consider wiring the existing pushToast here so users know the toggle didn't stick.

    -
    -
    -
    - - -
    -
    -
    -
    src/components/TaskList.tsx
    -
    -
    - worth a look - +31 −24 -
    -
    -
    -
    @@ -42,14 +42,17 @@ export function TaskList({ boardId }: Props) {
    -
    42 const { data: tasks } = useTasks(boardId);
    -
    43- const [pending, setPending] = useState<string | null>(null);
    -
    44-
    -
    45- async function toggle(task: Task) {
    -
    46- setPending(task.id);
    -
    47- await updateTask({ id: task.id, done: !task.done });
    -
    48- await refetch();
    -
    49- setPending(null);
    -
    50- }
    -
    43+ const { mutate, isPending } = useOptimisticTasks(boardId);
    -
    44+
    -
    45+ const toggle = (task: Task) =>
    -
    46+ mutate({ id: task.id, done: !task.done });
    -
    47
    -
    48 return (
    -
    49 <ul className="tasks">
    -
    50- {tasks?.map(t => <TaskRow key={t.id} task={t} busy={pending === t.id} />)}
    -
    50+ {tasks?.map(t => <TaskRow key={t.id} task={t} onToggle={toggle} />)}
    -
    51 </ul>
    -
    -
    -
    -
    line 43
    -

    NitisPending is destructured but never read. Either drop it or pass it to TaskRow so the checkbox can dim while the request is in flight.

    -
    -
    -
    - - -
    -
    -
    -
    src/api/tasks.ts
    -
    -
    - worth a look - +19 −6 -
    -
    -
    -
    @@ -12,10 +12,15 @@ export type TaskPatch = Partial<Task> & { id: string };
    -
    12
    -
    13-export async function updateTask(patch: TaskPatch) {
    -
    14- return http.patch(`/tasks/${patch.id}`, patch);
    -
    13+export async function updateTask(
    -
    14+ patch: TaskPatch,
    -
    15+ key = crypto.randomUUID(),
    -
    16+) {
    -
    17+ return http.patch(`/tasks/${patch.id}`, patch, {
    -
    18+ headers: { 'Idempotency-Key': key },
    -
    19+ });
    -
    20 }
    -
    -
    -
    -
    line 15
    -

    BlockingGenerating the idempotency key as a default parameter means retries from the mutation layer get a new key each time, which defeats the purpose. The key should be minted once in onMutate and threaded through.

    -
    -
    -
    - - -
    - - src/components/Toast.tsx - - safe - +14 −2 - - -
    Adds a variant="warning" style and exports pushToast. Purely additive, no behaviour change for existing call sites.
    -
    - -
    - - src/types/task.ts - - safe - +6 −2 - - -
    Widens Task.status to include "archived" and adds an optional updatedAt timestamp. Type-only change.
    -
    - -
    - - src/components/__tests__/TaskList.test.tsx - - safe - +14 −4 - - -
    Adds a test asserting the row updates synchronously after click, and one asserting rollback when the mocked request rejects. Both pass locally.
    -
    -
    - -
    -

    Suggested next steps

    -
      -
    • - - -
    • -
    • - - -
    • -
    • - - -
    • -
    -
    - -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/04-code-understanding.html b/skills/html-plan/references/html-effectiveness/04-code-understanding.html deleted file mode 100644 index e36505b..0000000 --- a/skills/html-plan/references/html-effectiveness/04-code-understanding.html +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - -How authentication flows through acme/web - - - -
    - -
    -
    acme/web · architecture note
    -

    How authentication flows through the codebase

    -

    - Acme uses cookie-based sessions: the browser never holds a bearer token directly. Every authenticated request hits /api/*, passes through a single verifyToken() middleware, and resolves to a Session row that downstream handlers read off req.ctx. The middleware is the only place that talks to the session store, which is the only place that talks to the sessions table — so there's exactly one trust boundary to reason about. -

    -
    - -
    -

    Request path

    -
    - - - - - - - - - - - Browser - acme.app - - - - /api/session - route handler - - - - verifyToken() - middleware/auth.ts - - - - - - SessionStore - lib/sessionStore.ts - - - - Postgres - sessions table - - - - - - - - - cookie - lookup - -
    - -

    Callstack walkthrough

    - - -
    -
    1
    -
    -
    src/app/providers/AuthProvider.tsx :22-48
    -

    On mount, the React provider issues a GET /api/session with credentials: 'include' so the fw_sid cookie rides along. The response either hydrates currentUser into context or leaves it null, which the router treats as "show the sign-in screen".

    -
    - show source -
    // src/app/providers/AuthProvider.tsx
    -export function AuthProvider({ children }: Props) {
    -  const [user, setUser] = useState<User | null>(null);
    -
    -  useEffect(() => {
    -    fetch('/api/session', { credentials: 'include' })
    -      .then(r => r.ok ? r.json() : null)
    -      .then(setUser);
    -  }, []);
    -
    -  return <AuthCtx.Provider value={{ user }}>{children}</AuthCtx.Provider>;
    -}
    -
    -
    -
    - - -
    -
    2
    -
    -
    src/server/routes/session.ts :9-27
    -

    The route itself is thin: it just returns whatever req.ctx.session the middleware attached. If the middleware short-circuited with a 401, this handler never runs — so there's no auth logic duplicated here.

    -
    - show source -
    // src/server/routes/session.ts
    -router.get('/session', verifyToken, (req, res) => {
    -  const { session } = req.ctx;
    -  res.json({
    -    id:    session.userId,
    -    email: session.email,
    -    role:  session.role,
    -    exp:   session.expiresAt,
    -  });
    -});
    -
    -
    -
    - - -
    -
    3
    -
    -
    src/middleware/auth.ts :14-31
    -

    This is the trust boundary. verifyToken reads the signed fw_sid cookie, asks SessionStore to resolve it, and either populates req.ctx.session or responds 401. Every protected route in the app is mounted behind this function, so changing its behaviour changes auth globally.

    -
    - show source -
    // src/middleware/auth.ts
    -export async function verifyToken(req, res, next) {
    -  const raw = req.signedCookies['fw_sid'];
    -  if (!raw) return res.status(401).end();
    -
    -  const session = await SessionStore.get(raw);
    -  if (!session || session.expiresAt < Date.now()) {
    -    return res.status(401).end();
    -  }
    -
    -  req.ctx = { session };
    -  next();
    -}
    -
    -
    -
    - - -
    -
    4
    -
    -
    src/lib/sessionStore.ts :8-52
    -

    SessionStore is a small read-through cache: it checks an in-process LRU first, then falls back to Postgres. Writes (create, revoke) always go straight to the DB and invalidate the cache entry so other workers don't serve a stale session.

    -
    - show source -
    // src/lib/sessionStore.ts
    -const cache = new LRU<string, Session>({ max: 5000, ttl: 60_000 });
    -
    -export const SessionStore = {
    -  async get(id: string) {
    -    const hit = cache.get(id);
    -    if (hit) return hit;
    -    const row = await db.one(SELECT_SESSION, [id]);
    -    if (row) cache.set(id, row);
    -    return row ?? null;
    -  },
    -  /* create, revoke, touch ... */
    -};
    -
    -
    -
    - - -
    -
    5
    -
    -
    db/migrations/004_sessions.sql :1-18
    -

    The sessions table is keyed on a random 32-byte id (the cookie value) with a covering index on user_id for "sign out everywhere". Expiry is enforced both here (expires_at) and again in the middleware as defence in depth.

    -
    - show source -
    -- db/migrations/004_sessions.sql
    -create table sessions (
    -  id          text primary key,
    -  user_id     uuid not null references users(id),
    -  created_at  timestamptz default now(),
    -  expires_at  timestamptz not null,
    -  ip          inet,
    -  user_agent  text
    -);
    -create index sessions_user_id_idx on sessions(user_id);
    -
    -
    -
    -
    - - - -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/05-design-system.html b/skills/html-plan/references/html-effectiveness/05-design-system.html deleted file mode 100644 index da5460e..0000000 --- a/skills/html-plan/references/html-effectiveness/05-design-system.html +++ /dev/null @@ -1,630 +0,0 @@ - - - - - - -Acme — Design System Reference - - - -
    - -
    -

    Acme design system

    -

    - Generated from src/styles/tokens.ts and src/components/ — use as a portable reference when prompting. -

    -
    - - -
    -

    Color

    -
    - -
    -
    Primary
    -
    -
    -
    - #D97757 - --clay -
    -
    -
    - #141413 - --slate -
    -
    -
    - #FAF9F5 - --ivory -
    -
    -
    - #E3DACC - --oat -
    -
    -
    - -
    -
    Neutral
    -
    -
    -
    - #FFFFFF - --white -
    -
    -
    - #F0EEE6 - --gray-100 -
    -
    -
    - #D1CFC5 - --gray-300 -
    -
    -
    - #87867F - --gray-500 -
    -
    -
    - #3D3D3A - --gray-700 -
    -
    -
    - -
    -
    Semantic
    -
    -
    -
    - #788C5D - --success -
    -
    -
    - #C78E3F - --warning -
    -
    -
    - #B04A4A - --danger -
    -
    -
    - #5C7CA3 - --info -
    -
    -
    -
    - - -
    -

    Typography

    -
    - -
    -
    -
    Plan the week ahead
    -
    - Display - 48 / 1.1 / 500 -
    -
    -
    -
    Plan the week ahead
    -
    - Heading 1 - 32 / 1.2 / 500 -
    -
    -
    -
    Plan the week ahead
    -
    - Heading 2 - 24 / 1.3 / 500 -
    -
    -
    -
    Review milestones, assign owners, and surface blockers before they cascade.
    -
    - Body - 16 / 1.55 / 430 -
    -
    -
    -
    Review milestones, assign owners, and surface blockers before they cascade.
    -
    - Small - 14 / 1.5 / 430 -
    -
    -
    -
    UPDATED 2 HOURS AGO
    -
    - Caption - 12 / 1.4 / 500 -
    -
    -
    -
    - - -
    -

    Spacing

    -
    - -
    -
    -
    -
    4--sp-1
    -
    -
    -
    -
    8--sp-2
    -
    -
    -
    -
    12--sp-3
    -
    -
    -
    -
    16--sp-4
    -
    -
    -
    -
    24--sp-5
    -
    -
    -
    -
    32--sp-6
    -
    -
    -
    -
    48--sp-7
    -
    -
    -
    -
    64--sp-8
    -
    -
    -
    - - -
    -

    Radius & Elevation

    -
    - -
    -
    -
    4px--r-xs
    -
    -
    -
    8px--r-sm
    -
    -
    -
    12px--r-md
    -
    -
    -
    20px--r-lg
    -
    -
    - -
    -
    -
    --shadow-sm0 1px 2px / 6%
    -
    -
    -
    --shadow-md0 4px 10px / 8%
    -
    -
    -
    --shadow-lg0 12px 28px / 12%
    -
    -
    -
    - - -
    -

    Core components

    -
    - -
    -
    <Button />
    -
    - - - - -
    -
    - -
    -
    <Input />
    -
    - - -
    -
    - -
    -
    <Checkbox />
    -
    - - -
    -
    - -
    -
    <Badge />
    -
    - Draft - In review - Done - Overdue -
    -
    -
    - -
    - - diff --git a/skills/html-plan/references/html-effectiveness/06-component-variants.html b/skills/html-plan/references/html-effectiveness/06-component-variants.html deleted file mode 100644 index 75debcf..0000000 --- a/skills/html-plan/references/html-effectiveness/06-component-variants.html +++ /dev/null @@ -1,606 +0,0 @@ - - - - - - -Acme — Card Variant Matrix - - - -
    - -
    -

    Card variant matrix

    -

    Six structural treatments of the Acme <Card /> component. Adjust density and emphasis with the controls, hover a variant to see its prop combo.

    -
    - - -
    -
    - Padding - - 20px -
    - -
    - Border -
    - - - -
    -
    - -
    - -
    -
    - - -
    - - -
    - A · Flat -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: dense lists on tinted backgrounds

    -
    - - -
    - B · Outlined -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: default content cards on ivory

    -
    - - -
    - C · Elevated -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: draggable items, popovers

    -
    - - -
    - D · Accent stripe -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: pinned or priority items

    -
    - - -
    - E · Inset -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: nested cards inside white panels

    -
    - - -
    - F · Horizontal -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: compact row lists, sidebars

    -
    - -
    - - -
    -
    JSX — hover a variant above
    -
    // hover a card to preview its props
    -
    - -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/07-prototype-animation.html b/skills/html-plan/references/html-effectiveness/07-prototype-animation.html deleted file mode 100644 index b63929e..0000000 --- a/skills/html-plan/references/html-effectiveness/07-prototype-animation.html +++ /dev/null @@ -1,456 +0,0 @@ - - - - - - -Acme — Task completed micro-interaction - - - -
    - -
    -
    Acme / prototype / micro-interaction
    -

    Task completed

    -

    - A single click should feel like a tiny win. Circle fills, check draws, - label strikes, a small burst, then the row quietly steps back. Click - the row to play; click again to reset. -

    -
    - -
    - -
    -
    -
    - -
    - Send weekly digest - Fri -
    -
    -
    -
    -
    -
    -
    -
    click to toggle
    -
    - - - -
    - -
    -

    Keyframes

    -
    -
    fill0ms
    -
    check80ms
    -
    strike120ms
    -
    confetti200ms
    -
    collapse600ms
    -
    -
    - -
    -

    Copy-paste CSS

    -
    /* circle: clay flash, settle to olive with spring overshoot */
    -.task.done .check {
    -  animation: settle 380ms cubic-bezier(.34,1.56,.64,1) forwards;
    -}
    -@keyframes settle {
    -  0%   { transform: scale(.8);  background: #D97757; }
    -  55%  { transform: scale(1.18); }
    -  100% { transform: scale(1);   background: #788C5D; }
    -}
    -
    -/* checkmark draws via stroke-dashoffset, 80ms delay */
    -.check path        { stroke-dasharray: 20; stroke-dashoffset: 20;
    -                     transition: stroke-dashoffset 220ms var(--ease) 80ms; }
    -.task.done path    { stroke-dashoffset: 0; }
    -
    -/* strikethrough grows left → right */
    -.label::after      { width: 0; transition: width 240ms var(--ease) 120ms; }
    -.task.done .label::after { width: 100%; }
    -
    -/* row steps back after the celebration */
    -.task.done         { max-height: 44px; opacity: .6;
    -                     transition-delay: 600ms; }
    -
    - -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/08-prototype-interaction.html b/skills/html-plan/references/html-effectiveness/08-prototype-interaction.html deleted file mode 100644 index fb8fde0..0000000 --- a/skills/html-plan/references/html-effectiveness/08-prototype-interaction.html +++ /dev/null @@ -1,397 +0,0 @@ - - - - - - -Acme — Sidebar drag-to-reorder - - - -
    - -
    -
    Acme / prototype / interaction
    -

    Sidebar drag-to-reorder

    -

    - Throwaway HTML so we can feel the reorder before porting it to - React. Native dragstart / dragover / drop, - ~40 lines of JS, no libraries. Grab a row by the dots and move it. -

    -
    - -
    - -
    - -

    Order persists in the DOM only — refresh to reset.

    -
    - -
    -
    -

    What you're feeling

    -

    Design decisions baked into this prototype, so you can push back on them.

    -
      -
    • - Drop indicator snaps to the nearest gap, not the raw cursor Y. - It only moves when you cross a row's midpoint — feels more decisive, - less jittery. -
    • -
    • - Dragged row stays in place at 35% opacity with a 2° tilt. - Keeping the ghost in the list preserves your sense of where you - started; the tilt reads as "lifted." -
    • -
    • - Grip dots are the affordance, but the whole row is draggable. - Dots darken on hover to teach the gesture without forcing a - tiny hit target. -
    • -
    • - No auto-scroll, no drop animation. Left out on purpose so the - core feel is easy to judge — say the word and we add them next. -
    • -
    -
    - -
    -

    Open questions

    -
      -
    1. Should Trash (and maybe Archive) be pinned to the bottom and excluded from reordering?
    2. -
    3. Do we want rows to slide to their new slot on drop, or is the instant snap acceptable?
    4. -
    5. Keyboard path: is Alt + Arrow to move the focused row enough for the first ship?
    6. -
    -
    -
    - -
    -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/09-slide-deck.html b/skills/html-plan/references/html-effectiveness/09-slide-deck.html deleted file mode 100644 index 61fd981..0000000 --- a/skills/html-plan/references/html-effectiveness/09-slide-deck.html +++ /dev/null @@ -1,593 +0,0 @@ - - - - - - -Platform Eng — Week of Mar 10 - - - - - -
    -
    - -

    Platform Eng
    — Week of Mar 10

    -

    - What shipped, what's moving, and one decision we need from the - room before the Acme 2.4 cut. -

    - -
    -
    - - -
    -
    -
    Shipped this week
    -

    Three things out the door

    -
      -
    • - -
      -
      Bulk task import
      -
      - CSV and JSON uploads now land straight into a board with - column mapping — no more paste-and-pray. -
      -
      - #4211 -
    • -
    • - -
      -
      Webhook retries v2
      -
      - Exponential backoff with jitter; dead-letter queue surfaces - in the workspace admin panel. -
      -
      - #4188 #4203 -
    • -
    • - -
      -
      Postgres 16 migration
      -
      - All read replicas cut over Tuesday night; zero customer-facing - downtime, ~9% faster aggregate queries. -
      -
      - #4179 -
    • -
    -
    -
    - - -
    -
    -
    In progress
    -

    Carrying into next week

    -
      -
    • -
      - Recurring tasks engine - ~70% -
      -
      -

      - Scheduler and RRULE parsing are done; remaining work is the - timezone edge cases and the "skip holidays" toggle. -

      -
    • -
    • -
      - Audit log export - ~35% -
      -
      -

      - Streaming NDJSON endpoint is up behind a flag; still wiring - the S3 destination picker and retention policy UI. -

      -
    • -
    -
    -
    - - -
    -
    -
    Metrics
    -

    Numbers we watch

    - -
    -
    -
    API p95 latency
    -
    184ms
    -
    ↓ 12% wk/wk
    -
    -
    -
    Background job error rate
    -
    0.21%
    -
    ↓ 0.08pp
    -
    -
    - -
    - -
    - p95 latency, trailing 8 days — lower is better -
    -
    -
    -
    - - -
    -
    -
    Decision needed
    -

    One call to make

    - -
    -

    - Do we ship recurring tasks behind a workspace flag in 2.4, or - hold one more week for the timezone fixes? -

    -

    - Flagged rollout gets it to design partners Friday but means two - code paths for ~2 weeks. Holding keeps a single path but slips - the partner promise. -

    -
    - -
    - A — Flag it, ship Friday - B — Hold for 2.5 -
    -
    -
    - - -
    -
    -
    Next week
    -

    On deck

    -
      -
    • Finish recurring tasks — timezone matrix tests, then dogfood on the internal ops board.
    • -
    • Audit log export to private beta — three workspaces lined up.
    • -
    • Start scoping rate-limit headers for the public API; RFC draft by Thursday.
    • -
    -
    - Questions → drop them in the platform channel or grab anyone after standup. -
    -
    -
    - - -
    1 / 6
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/10-svg-illustrations.html b/skills/html-plan/references/html-effectiveness/10-svg-illustrations.html deleted file mode 100644 index c408408..0000000 --- a/skills/html-plan/references/html-effectiveness/10-svg-illustrations.html +++ /dev/null @@ -1,493 +0,0 @@ - - - - - - -Background jobs — header illustrations - - - -
    - -
    -

    Background jobs — header illustrations

    -

    - Three 720×320 hand-drawn SVGs for the Acme docs section on - background jobs. Flat fills, 1.5–2px strokes, palette-locked. Each - exports standalone via the button below it. -

    -
    720 × 320 · inline SVG · no external assets
    -
    - - -
    -
    - - - - - - - - - - - - queue - - - - - job 5 - - - job 4 - - - job 3 - - - job 2 - - - - job 1 - - - - - - - - worker - pool=4 - - - next to run - Jobs are pulled FIFO; the worker leases one at a time. - -
    -
    -
    -
    Queue
    -
    For "How jobs are picked up" — intro page header.
    -
    - -
    -
    - - -
    -
    - - - - - - - - - - t = 0 - time → - - - - - - - try 1 - - - - - - try 2 - - - - - - try 3 - - - - - try 4 - - - - +1s - - - +2s - - - +4s - - - Each failure waits twice as long before re-queuing; jitter not pictured. - -
    -
    -
    -
    Retry with backoff
    -
    For "Handling failures" — retry policy header.
    -
    - -
    -
    - - -
    -
    - - - - - - - - - - - - - enqueue - batch() - - - - - - - - - - - shard 0 - - - shard 1 - - - shard 2 - - - shard 3 - - - - - - - - - - - merge - await all - - - fan-out - fan-in - Parent job spawns N children, then blocks on a completion barrier. - -
    -
    -
    -
    Fan-out / fan-in
    -
    For "Batch and parallel work" — fan-out pattern header.
    -
    - -
    -
    - - -
    -

    Palette & rules

    - -
    -
    -
    -
    -
    ivory
    -
    #FAF9F5
    -
    -
    -
    -
    -
    -
    slate
    -
    #141413
    -
    -
    -
    -
    -
    -
    clay
    -
    #D97757
    -
    -
    -
    -
    -
    -
    olive
    -
    #788C5D
    -
    -
    -
    -
    -
    -
    oat
    -
    #E3DACC
    -
    -
    -
    -
    -
    -
    gray-150
    -
    #F0EEE6
    -
    -
    -
    -
    -
    -
    gray-300
    -
    #D1CFC5
    -
    -
    -
    -
    -
    -
    gray-500
    -
    #87867F
    -
    -
    -
    - -
      -
    • Strokes are 1.5px for neutral boxes, 2px for emphasised containers.
    • -
    • All rectangles use rx="10"; no drop shadows or gradients.
    • -
    • Labels inside boxes are 11px mono; annotations outside are 12px sans, gray-500.
    • -
    • Clay marks "the thing in focus"; olive marks "success / done".
    • -
    • Each SVG carries its own <style> block so the download stands alone.
    • -
    -
    - -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/11-status-report.html b/skills/html-plan/references/html-effectiveness/11-status-report.html deleted file mode 100644 index 7f5ed34..0000000 --- a/skills/html-plan/references/html-effectiveness/11-status-report.html +++ /dev/null @@ -1,529 +0,0 @@ - - - - - - -Acme — Engineering Status — Week 11 - - - -
    - -
    -
    -

    Engineering Status — Week 11

    - auto-generated -
    -
    - Mar 10 – Mar 16, 2025  ·  - acme/app @ main -
    -
    - - -
    -
    -
    -
    14
    -
    PRs merged
    -
    +3 vs wk10
    -
    -
    -
    6
    -
    Deploys
    -
    ±0
    -
    -
    -
    1
    -
    Incidents
    -
    SEV-2 · 47m
    -
    -
    -
    3
    -
    Flaky tests fixed
    -
    suite now 99.1%
    -
    -
    -
    - - -
    -

    Highlights

    -
    -
      -
    • - Bulk task editing shipped to 100%. The multi-select - toolbar landed behind a flag on Monday and ramped to all workspaces by - Thursday with no error-rate regression. -
    • -
    • - Sync API p95 down 38%. Replacing per-task auth checks - with a scoped batch lookup cut the hot path from 410ms to 255ms on the - staging load test. -
    • -
    • - One SEV-2 on Wednesday — a config rollout pushed - a bad connection-pool limit to the sync workers. Mitigated in 47 minutes; - full postmortem linked below. -
    • -
    -
    - - -
    -

    Shipped

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PRTitleAuthorRisk
    #4871Bulk edit toolbar: selection model + keyboard shortcutsMira OkaforMed
    #4874Batch auth lookup for /v2/sync hot pathDevon ParkMed
    #4878Fix race in attachment uploader retry loopSam ReyesLow
    #4879Migrate reminder scheduler to idempotent job keysPriya AnandHigh
    #4882Board view: collapse empty swimlanes by defaultMira OkaforLow
    #4885Quarantine 3 flaky webhook integration testsJules TanLow
    #4888Connection pool limits configurable per worker tierDevon ParkMed
    #4891Dark mode pass on settings & billing panelsNoor HalabiLow
    -
    - - -
    -

    Velocity

    -
    -
    - - - - - - - - - 0 - 1 - 2 - 3 - - - - - - - - - - - - - - - - - - - 2 - 3 - 1 - 4 - 2 - 1 - 1 - - - Mon - Tue - Wed - Thu - Fri - Sat - Sun - -
    - PRs merged per day. Thursday spike is the bulk-edit feature train (4 PRs landed together). -
    -
    -
    - - -
    -

    Carryover

    -
    -
    -
    - In review -
    - Workspace export to CSV — waiting on pagination review. - · Sam Reyes -
    -
    -
    - Blocked -
    - SSO group mapping — blocked on staging IdP credentials from IT. - · Priya Anand -
    -
    -
    - Slipped -
    - Mobile push reliability dashboard — deprioritized for incident follow-up. - · Devon Park -
    -
    -
    -
    - -
    - Sources: git log main..HEAD · CI dashboard · deploy log -  —  generated Mar 16 2025 18:02 -
    - -
    - - diff --git a/skills/html-plan/references/html-effectiveness/12-incident-report.html b/skills/html-plan/references/html-effectiveness/12-incident-report.html deleted file mode 100644 index ff06f1d..0000000 --- a/skills/html-plan/references/html-effectiveness/12-incident-report.html +++ /dev/null @@ -1,597 +0,0 @@ - - - - - - -INC-2025-0412 — Elevated 502s on task sync - - - - - - -
    - -
    -
    INC-2025-0412
    -

    Elevated 502s on task sync

    -
    - SEV-2 - Resolved - Duration 47 min - Detected Apr 12 · 14:07 - Owner Devon Park -
    -
    - -
    -
    TL;DR
    -

    - A config rollout lowered the database connection-pool limit on the - sync-worker tier from 64 to 8, exhausting connections under - normal afternoon load. The sync API returned 502s for roughly 21% of - requests over 47 minutes. We mitigated by reverting the config and - cycling the worker fleet; no data was lost. -

    -
    - - -
    -

    Timeline

    -
    -
    - -
    - - 14:02 -
    - Config change cfg-9a12 promoted to - production via the standard rollout pipeline. -
    -
    - -
    - - 14:06 -
    - Impact starts. Sync workers begin queueing on pool - checkout; p95 latency climbs past 4s and the load balancer starts - returning 502s. -
    -
    - -
    - - 14:07 -
    - Alert fires: sync_5xx_rate > 2% for 60s. - On-call (Devon) acknowledges. -
    -
    - -
    - - 14:18 -
    - Initial hypothesis is a bad deploy of the API service; last two - application deploys are rolled back with no effect. -
    -
    - -
    - - 14:31 -
    - Mira joins and notices pool-wait saturation in the worker dashboard. - Investigation pivots to infra config rather than app code. -
    -
    - -
    - - 14:44 -
    - Mitigated. cfg-9a12 - reverted; worker fleet cycled. 5xx rate drops below 0.2% within - three minutes. -
    -
    - -
    - - 14:49 -
    - Monitors green for 5 minutes. Incident declared resolved; status - page updated. -
    -
    - -
    -
    - - -
    -

    Root cause

    -
    -

    - PR #4888 made connection-pool limits - configurable per worker tier. The default for the new - sync-worker key was meant to inherit the - global value (64) but was hard-coded to 8 during a local test and - committed. The config linter only validates type, not magnitude, so the - change passed CI. -

    -

    - Because config rollouts and code deploys go through separate pipelines, - the on-call's first instinct — rolling back the most recent - application deploys — had no effect and cost roughly 13 minutes of - diagnosis time. -

    - -
    - infra/config/workers.yaml -
    pool:
    -
    global_max_connections: 64
    -
    tiers:
    -
    - sync-worker: { max_connections: 64 }
    -
    + sync-worker: { max_connections: 8 } # debug value, do not ship
    -
    webhook-worker: { max_connections: 32 }
    -
    -
    - - -
    -

    Impact

    -
    - - - - - - - - - - - - - - - - - - - - - -
    Requests failed (502)~41,200
    Peak error rate21.4%
    Users affected~2,300 workspaces
    Data lossNone — clients retried
    SLA breachNo (within monthly budget)
    -
    - - -
    -

    Action items

    -
    -
    - -
    - - DP - Revert cfg-9a12 and restore pool limit to 64 - Apr 12 -
    - -
    - - MO - Add config-linter range check for max_connections (warn < 32) - Apr 18 -
    - -
    - - SR - Surface “recent config rollouts” alongside deploys in the on-call dashboard - Apr 25 -
    - -
    - - PA - Canary config changes to one worker AZ for 10 min before fleet-wide promote - May 02 -
    - -
    -
    - -
    - Authored from on-call notes + alert history · reviewed by Devon Park, Mira Okafor -
    - -
    - - diff --git a/skills/html-plan/references/html-effectiveness/13-flowchart-diagram.html b/skills/html-plan/references/html-effectiveness/13-flowchart-diagram.html deleted file mode 100644 index 8967f6e..0000000 --- a/skills/html-plan/references/html-effectiveness/13-flowchart-diagram.html +++ /dev/null @@ -1,396 +0,0 @@ - - - - - - -Deploy pipeline — annotated flowchart - - - -
    - -
    -
    Illustrations & Diagrams · Flowchart
    -

    What happens when you git push

    -

    - The deploy pipeline for acme/web, drawn from .github/workflows/ and the - Argo manifests. Click any step to see what runs, how long it usually takes, and where it can short-circuit. -

    -
    - -
    - -
    -
    - - - - - - - - - - - - - - - - - - - pass - - fail → status - - - - healthy - - canary fails - - - - - - - git push main - - - - - CI · lint + typecheck - ~2 min · ci.yml - - - - - Unit + integration tests - ~6 min · 3 shards - - - - - pass? - - - - - Post failure status - slack #deploys - - - - - Build + push image - ghcr.io/acme/web - - - - - Argo canary 5% - 10 min soak - - - - - SLO ok? - - - - - Promote 25 → 50 → 100% - ~8 min - - - - - Auto-rollback - revert image tag - - - - - Smoke tests in prod - playwright · 90s - - - - - ✅ Deploy complete - - -
    - -
    - process step - decision - terminal success - failure path -
    -
    - - - -
    -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/14-research-feature-explainer.html b/skills/html-plan/references/html-effectiveness/14-research-feature-explainer.html deleted file mode 100644 index aea9deb..0000000 --- a/skills/html-plan/references/html-effectiveness/14-research-feature-explainer.html +++ /dev/null @@ -1,382 +0,0 @@ - - - - - - -How rate limiting works in acme/api - - - -
    - - - - - -
    -
    -
    Research & Learning · feature summary
    -

    How rate limiting works in acme/api

    -
    - TL;DR — Every request passes through rateLimit() middleware, which resolves the - caller to a bucket key, fetches a token-bucket from Redis, and either consumes one token or - returns 429. Limits are declared per-route in config/limits.yaml; routes - without an entry inherit the default tier (100 req/min per API key). -
    -
    - -

    The request path, step by step

    -

    Expand each step to see what runs and where it lives. The whole path is ~40 lines and adds about - 0.4 ms p50 to every request.

    - -
    - 1 · Identify the caller middleware/ratelimit.ts:21 -
    -

    The middleware first reduces the request to a bucketKey: API key if an - Authorization header is present, otherwise the client IP (via the - x-forwarded-for chain, trusting only our own LB). Anonymous IP traffic gets a much - lower default tier.

    -
    -
    - -
    - 2 · Look up the bucket lib/tokenBucket.ts:9 -
    -

    The route name plus bucket key map to a Redis hash (rl:{route}:{key}) holding - tokens and updatedAt. If the key is missing it's created lazily at full - capacity — there's no warm-up.

    -
    -
    - -
    - 3 · Refill and consume lib/tokenBucket.ts:31 -
    -

    Refill is computed from elapsed time (rate × Δt, capped at burst), then - one token is subtracted. The whole read-modify-write runs as a single Lua script so concurrent - requests can't double-spend.

    -
    -
    - -
    - 4 · Reject when empty middleware/ratelimit.ts:48 -
    -

    If the script returns tokens < 0 the middleware short-circuits with - 429 Too Many Requests and sets Retry-After to the seconds until one token - refills. Successful responses always carry X-RateLimit-Remaining.

    -
    -
    - -

    Configuring a limit on your route

    -

    You don't touch the middleware. Add an entry to config/limits.yaml keyed by route name, - and (optionally) tag the route so the middleware can find it.

    - -
    -
    - - - -
    -
    # config/limits.yaml
    -default:
    -  rate: 100/min
    -  burst: 120
    -
    -search.query:
    -  rate: 20/min
    -  burst: 40
    -  key: api_key        # or: ip
    -
    // routes/search.ts
    -router.post(
    -  "/search",
    -  rateLimit("search.query"),
    -  handler,
    -);
    -
    HTTP/1.1 429 Too Many Requests
    -Retry-After: 17
    -X-RateLimit-Limit: 20
    -X-RateLimit-Remaining: 0
    -
    -{ "error": "rate_limited", "retry_after": 17 }
    -
    - -
    - -
    If you only need the default tier, you don't need a YAML entry at all — just wrap the handler in - rateLimit() with no argument. The route name is inferred from the path.
    -
    - -

    Gotchas worth knowing

    -
      -
    • Limits are per-process in dev. The Redis client falls back to an - in-memory map when REDIS_URL is unset, so local testing won't reflect real cluster - behaviour.
    • -
    • Burst ≠ rate. burst is the bucket capacity; a caller - idle for a minute can fire burst requests instantly even if rate is low.
    • -
    • Streaming responses count once. The token is consumed at request start; a 30-second SSE - stream still costs one token.
    • -
    - -

    FAQ

    -
    -
    How do I exempt internal traffic?
    -
    Set x-acme-internal: 1 from the caller; the middleware checks it against the - mTLS peer name and skips the bucket entirely.
    - -
    Where do I see who's getting limited?
    -
    Every 429 emits a ratelimit.rejected metric tagged with route and key - type. There's a Grafana panel under API → Health.
    - -
    Can a single user have a higher limit?
    -
    Yes — add their API key under overrides: in the YAML. Overrides are reloaded without - a deploy.
    -
    -
    - -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/15-research-concept-explainer.html b/skills/html-plan/references/html-effectiveness/15-research-concept-explainer.html deleted file mode 100644 index 192869d..0000000 --- a/skills/html-plan/references/html-effectiveness/15-research-concept-explainer.html +++ /dev/null @@ -1,369 +0,0 @@ - - - - - - -Consistent hashing — an interactive explainer - - - -
    - -
    -
    Research & Learning · concept explainer
    -

    Consistent hashing, in one ring

    -

    - You have K keys spread across N cache servers. A server dies, or you add one. How many - keys have to move? With naive hash(key) mod N the answer is "almost all of them." Consistent - hashing gets it down to roughly K / N. Here's why. -

    - -

    The trick: hash onto a circle, not a line

    -

    - Map both nodes and keys onto the same - ring (the hash output space, wrapped around). A key belongs to - the first node found by walking clockwise from the key's position. When a node leaves, only the keys in - its arc reassign — to the next node round — and everything else - stays put. -

    - -
    -
    - -
    -
    - - - 4 -
    -
    - - - 32 -
    -
    - - - -
    -
    - 4 nodes · 32 keys · moved on last change -
    -
    -
    -
    -

    - Colored arcs show ownership. Removing a node hands its arc to its clockwise neighbor; every dot outside - that arc keeps its color. That's the whole idea. -

    - -

    Versus mod N

    - - - - - - - - -
    hash mod Nconsistent hashing
    Keys moved when N→N+1~ (N−1)/N of all keys~ 1/(N+1)
    Hot-spot riskeven by constructionuneven — fix with virtual nodes
    Lookup costO(1)O(log N) (binary search on ring)
    Used byarray sharding, simple LBDynamo, Cassandra, Memcached clients, Envoy
    - -

    Where you'll meet it

    -

    - Any time you're spreading state across a pool that changes size: cache fleets, partitioned queues, object - storage, request routing with sticky sessions. The - virtual-node variant (each physical node owns many small arcs - instead of one big one) is what production systems actually run, because it smooths out load and makes - rebalancing even gentler. -

    -
    - - - - -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/16-implementation-plan.html b/skills/html-plan/references/html-effectiveness/16-implementation-plan.html deleted file mode 100644 index 483a826..0000000 --- a/skills/html-plan/references/html-effectiveness/16-implementation-plan.html +++ /dev/null @@ -1,703 +0,0 @@ - - - - - - - Implementation plan — Comment threads on task cards - - - -
    - -
    -
    Implementation plan · Acme web client
    -

    Comment threads on task cards

    -
    - Prompt - Create a thorough implementation plan for adding threaded comments to - task cards. Include mockups, the data flow from client to persistence, - the key code I'll need to write, and a risk table. Make it easy to - skim on a phone — I'm going to pass this to the implementer as-is. -
    -
    - - - -
    -
    Effort
    ~2 weeks
    -
    Surfaces touched
    3 packages
    -
    New tables
    2
    -
    Feature flag
    task_comments_v1
    -
    - - - -
    -
    01

    Milestones

    -

    Ship in four slices, each independently reviewable and each behind the flag. Nothing is user-visible until slice 4.

    - -
    -
    -
    Week 1 · Mon–Tue
    -
    -
    -

    Schema & API contract

    -

    New comments and comment_reads tables, migrations, and the tRPC router stubs. No UI. Contract reviewed before anything else lands.

    -
    packages/dbpackages/apimigration 0042
    -
    -
    - -
    -
    Week 1 · Wed–Fri
    -
    -
    -

    Thread component & composer

    -

    Static <CommentThread> rendered from fixtures. Optimistic insert on submit, rollback on failure, one level of nesting only.

    -
    apps/webstorybook
    -
    -
    - -
    -
    Week 2 · Mon–Wed
    -
    -
    -

    Realtime fan-out & unread state

    -

    Subscribe the open card to its comment channel. Track per-user read cursors so the sidebar can show an unread count without a second query.

    -
    packages/realtimeapps/web
    -
    -
    - -
    -
    Week 2 · Thu–Fri
    -
    -
    -

    Notifications, flag ramp, docs

    -

    Mention detection → notification row, email digest fallback, ramp task_comments_v1 to internal, then 10% → 100% over three days.

    -
    packages/notifygrowthbook
    -
    -
    -
    -
    - - - -
    -
    02

    Data flow

    -

    Optimistic write path on the left, fan-out on the right. The read cursor update is fire-and-forget — we never block the thread render on it.

    - -
    - - - - - - - - - - - - - - <CommentComposer> - apps/web - - - React Query cache - optimistic insert - - - comments.create - tRPC · packages/api - - - comments table - postgres · packages/db - - - realtime channel - task:{id}:comments - - - Other viewers - subscribed cards - - - notify worker - @mentions → queue - - - - - - - - - - - - - - - - - - submit (id=temp) - mutate - INSERT + read cursor - enqueue - broadcast row - live append - reconcile temp id → real id - - -

    Solid = request/response path. Dashed clay = realtime fan-out. The composer never waits on the dashed path.

    -
    -
    - - - -
    -
    03

    Mockups

    -

    Not pixel-final — just enough that the reviewer and I agree on nesting depth, composer placement, and what the sidebar digest looks like.

    - -
    -
    -
    A · Thread inside an open task card
    -
    -
    -
    Ship onboarding empty-state rewrite
    -
    BIR-1142 · Assigned to Priya · Due Fri
    -
    -
    -
    -
    JM
    -
    -
    Jonah M. 2h ago
    -
    Should the illustration swap when the workspace already has one project? Feels odd to show the "start here" art twice.
    - -
    -
    -
    -
    PS
    -
    -
    Priya S. 40m ago
    -
    Good catch — I'll gate it on projects.count > 0 and fall back to the minimal variant.
    -
    -
    -
    -
    Add a comment…
    -
    Post
    -
    -
    -
    -
    -
    - -
    -
    B · Sidebar unread digest
    -
    -
    -
    -
    JM
    -
    Jonah commented on BIR-1142 — "Should the illustration swap when…"
    -
    -
    -
    AK
    -
    Aiko mentioned you on BIR-1098 — "@priya can you confirm the copy here?"
    -
    -
    -
    RW
    -
    Rowan replied on BIR-0971 — "Merged, thanks for the quick turnaround."
    -
    -
    -
    -
    -
    -
    - - - -
    -
    04

    Key code

    -

    The two pieces most likely to be done wrong: the migration (soft deletes, read cursors) and the optimistic mutation (temp-id reconciliation).

    - -
    -
    -
    packages/db/migrations/0042_comments.sql
    -
    create table comments (
    -  id          uuid primary key default gen_random_uuid(),
    -  task_id     uuid not null references tasks(id),
    -  parent_id   uuid references comments(id),   -- one level only,
    -                                                -- enforced in API
    -  author_id   uuid not null references users(id),
    -  body        text not null,
    -  created_at  timestamptz not null default now(),
    -  deleted_at  timestamptz                       -- soft delete
    -);
    -
    -create table comment_reads (
    -  task_id    uuid not null references tasks(id),
    -  user_id    uuid not null references users(id),
    -  read_up_to timestamptz not null,
    -  primary key (task_id, user_id)
    -);
    -
    -create index comments_task_created
    -  on comments (task_id, created_at);
    -
    - -
    -
    apps/web/hooks/useAddComment.ts
    -
    export function useAddComment(taskId: string) {
    -  const qc = useQueryClient();
    -  return trpc.comments.create.useMutation({
    -    onMutate: async (input) => {
    -      const temp = { ...input, id: `temp-${nanoid()}`,
    -                     createdAt: new Date(), pending: true };
    -      qc.setQueryData(key(taskId), (prev) =>
    -        [...(prev ?? []), temp]);
    -      return { tempId: temp.id };
    -    },
    -    onSuccess: (row, _v, ctx) => {
    -      // reconcile temp id → real id so the
    -      // realtime append doesn't duplicate it
    -      qc.setQueryData(key(taskId), (prev) =>
    -        prev.map((c) => c.id === ctx.tempId ? row : c));
    -    },
    -    onError: (_e, _v, ctx) => {
    -      qc.setQueryData(key(taskId), (prev) =>
    -        prev.filter((c) => c.id !== ctx.tempId));
    -    },
    -  });
    -}
    -
    -
    -
    - - - -
    -
    05

    Risks & mitigations

    -
    -
    -
    Risk
    -
    Sev
    -
    Mitigation
    -
    -
    -
    Realtime duplicate: socket append races with the HTTP response and the temp-id reconcile.
    -
    HIGH
    -
    Dedupe on server-assigned id in the cache updater; socket payload carries the real id, temp rows are filtered on reconcile.
    -
    -
    -
    Unread counts go stale when a user reads the thread on another device.
    -
    MED
    -
    Broadcast comment_reads upserts on the same channel; client treats its own cursor as max(local, remote).
    -
    -
    -
    Mention detection false-positives on pasted markdown (@media, @2x).
    -
    LOW
    -
    Resolve mentions against workspace members only, at write time, and store the resolved user ids — never re-parse on read.
    -
    -
    -
    - - - -
    -
    06

    Open questions

    -
    -
    -
    Do we allow editing, or only delete-and-repost?
    -
    Editing needs an edited_at column and an "edited" affordance. Delete-and-repost is simpler but loses the reply anchor. Leaning toward delete-only for v1.
    -
    Decide with · design, before slice 2
    -
    -
    -
    Email digest cadence when a user has the app closed
    -
    Immediate-per-mention will be noisy. Proposal: batch on a 15-minute window, collapse to one email per task, and respect quiet hours from the existing settings table.
    -
    Decide with · platform, before slice 4
    -
    -
    -
    - -
    - - diff --git a/skills/html-plan/references/html-effectiveness/17-pr-writeup.html b/skills/html-plan/references/html-effectiveness/17-pr-writeup.html deleted file mode 100644 index 34c60d0..0000000 --- a/skills/html-plan/references/html-effectiveness/17-pr-writeup.html +++ /dev/null @@ -1,596 +0,0 @@ - - - - - - - PR #312 — Move notification delivery onto a queue - - - -
    - -
    -
    Pull request · Acme
    -

    #312 — Move notification delivery onto a queue

    -
    - 9 files - +418 / −190 - branch notify-queuemain - author @priya -
    -
    - Prompt - Write up PR #312 for my reviewers. Explain the motivation, walk them - through the change file by file with the why for each, show - before/after behavior, and tell them exactly where to focus. They - haven't touched the notification code in six months. -
    -
    - -
    -
    - -
    -
    TL;DR
    -

    Notification sends were happening inline in the request path. Under load they added 200–800 ms to mutation latency and silently dropped emails when the SMTP pool was exhausted. This PR moves delivery onto the existing pg-boss queue so the API returns immediately and failed sends retry with backoff.

    -
    - - - -
    -

    Why

    -

    When we added @mentions in comments last quarter, every mention started triggering up to three sends (in-app, email, Slack) inside the same transaction that saved the comment. That was fine at launch. It is not fine now that a single task update can fan out to forty watchers.

    - -
    -
    -
    Before
    -
      -
    • Sends run inline in the mutation handler
    • -
    • SMTP timeout = 500 error for the comment
    • -
    • No retries — a dropped email is gone
    • -
    • p99 on comments.create: 1.4 s
    • -
    -
    -
    -
    After
    -
      -
    • Handler enqueues one job per recipient, returns
    • -
    • Worker retries 3× with exponential backoff
    • -
    • Dead-letter table for inspection after exhaustion
    • -
    • p99 on comments.create: 180 ms (staging)
    • -
    -
    -
    -
    - - - -
    -

    File-by-file

    -

    Ordered for reading, not alphabetically. Start at the worker — it's the new thing — then the enqueue call site, then the plumbing.

    - -
    - -
    - - - packages/notify/src/worker.ts - new - +126 - -
    -

    The heart of the PR. A pg-boss subscriber that pulls notify.deliver jobs, resolves the user's channel preferences, and calls the right adapter. Retries are configured per-channel — email gets three attempts, Slack gets one because its API is already idempotent on our side.

    -
    boss.work('notify.deliver', { batchSize: 20 }, async (jobs) => {
    -  for (const job of jobs) {
    -    const { userId, event, channel } = job.data;
    -    const prefs = await getPrefs(userId);
    -    if (!prefs[channel]) return;          // user muted this channel
    -
    -    try {
    -      await adapters[channel].send(userId, event);
    -    } catch (err) {
    -      if (job.retryCount >= MAX_RETRY[channel]) {
    -        await deadLetter(job, err);         // don't throw — ack & park
    -        return;
    -      }
    -      throw err;                            // pg-boss reschedules
    -    }
    -  }
    -});
    -
    -
    - -
    - - - packages/api/src/routers/comments.ts - mod - +14 −62 - -
    -

    Where the win shows up. The mutation used to call sendEmail, sendSlack, and createInApp directly. Now it inserts the comment, computes recipients, and enqueues. The try/catch soup is gone.

    -
      const comment = await db.comments.insert(input);
    -  const recipients = await resolveWatchers(input.taskId, input.mentions);
    -
    -  for (const r of recipients) {
    -    await sendEmail(r, comment);       // blocked the response
    -    await sendSlack(r, comment);
    -  }
    -  await boss.insert(recipients.flatMap((r) =>
    -    CHANNELS.map((ch) => ({
    -      name: 'notify.deliver',
    -      data: { userId: r.id, channel: ch, event: toEvent(comment) },
    -      singletonKey: `${comment.id}:${r.id}:${ch}`,  // idempotent
    -    }))));
    -  return comment;
    -
    -
    - -
    - - - packages/db/migrations/0051_dead_letter.sql - new - +22 - -
    -

    Table for jobs that exhaust their retries. Deliberately not auto-pruned — we want to look at these weekly until we trust the new path. Has the full job payload and the last error string.

    -
    -
    - -
    - - - packages/notify/src/adapters/{email,slack,inapp}.ts - mod - +88 −74 - -
    -

    Mostly moves. Each adapter now implements a shared Adapter interface and throws a typed RetryableError or PermanentError so the worker knows whether to retry. The email adapter also drops its internal retry loop — the queue owns retries now, double-retrying was how we got duplicate emails in April.

    -
    -
    - -
    - - - apps/worker/src/index.ts, infra/fly.toml - mod - +31 −4 - -
    -

    Registers the new subscriber in the existing worker process and bumps its concurrency from 5 → 20. No new deploy unit.

    -
    -
    - -
    - - - packages/notify/src/__tests__/worker.test.ts - new - +137 - -
    -

    Covers the retry boundary, the dead-letter path, channel muting, and the singleton key dedupe. Uses a real pg-boss against the test database — we got burned last quarter when mocked queue tests passed but prod ordering broke.

    -
    -
    - -
    -
    - - - -
    -

    Where to focus your review

    -
    -
    -
    1
    -
    -
    The retry / dead-letter boundary
    -
    worker.ts:31–44. I catch, check retryCount, and either park or rethrow. If this logic is wrong we either retry forever or drop messages — the two failure modes this PR exists to fix.
    -
    -
    -
    -
    2
    -
    -
    The singleton key
    -
    comments.ts:28. ${commentId}:${userId}:${channel} should make re-enqueues idempotent if the API handler retries. Sanity-check that this can't collide across tasks.
    -
    -
    -
    -
    3
    -
    -
    What I deliberately did not do
    -
    No per-user digest batching, no delivery receipts, no priority lanes. All of those layer on top of this cleanly; bundling them would make this unreviewable.
    -
    -
    -
    -
    - - - -
    -

    Test plan

    -
    -
    Unit: retry → dead-letter path, channel mute, singleton dedupe
    packages/notify — 14 cases, real pg-boss on test db
    -
    Integration: create comment with 3 watchers, assert 9 jobs enqueued and drained
    -
    Staging load: 500 rps on comments.create for 10 min, p99 = 180 ms
    was 1.4 s before — dashboard linked in the PR description
    -
    Manual: kill SMTP mid-burst, confirm jobs land in dead-letter and nothing 500s
    will do during the 10% ramp
    -
    -
    - - - -
    -

    Rollout

    -

    Behind notify_queue_v2. The old inline path stays in the codebase, dead but dormant, for one release in case we need to flip back.

    -
    -
    Day 0
    internal
    Acme team only. Watch dead-letter table + worker error rate.
    -
    Day 2
    10%
    Random sample. Alert if dead-letter rate > 0.5% of sends.
    -
    Day 4
    100%
    Ramp fully, delete the inline path in a follow-up PR next week.
    -
    -
    - -
    - - -
    - -
    - - diff --git a/skills/html-plan/references/html-effectiveness/18-editor-triage-board.html b/skills/html-plan/references/html-effectiveness/18-editor-triage-board.html deleted file mode 100644 index ae4dbb0..0000000 --- a/skills/html-plan/references/html-effectiveness/18-editor-triage-board.html +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - -Acme — Cycle 14 triage - - - -
    - -
    -
    Acme / editor / triage
    -

    Cycle 14 triage

    -

    - Twenty-four open Linear tickets, pre-sorted into a best guess. Drag them - across Now / Next / Later / Cut until the cut feels right, then copy the - result back into the planning doc as markdown. -

    -
    drag tickets between columns  ·  click a tag to filter
    -
    - -
    -
    -
    - - - -
    - -
    - -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/19-editor-feature-flags.html b/skills/html-plan/references/html-effectiveness/19-editor-feature-flags.html deleted file mode 100644 index 15be394..0000000 --- a/skills/html-plan/references/html-effectiveness/19-editor-feature-flags.html +++ /dev/null @@ -1,664 +0,0 @@ - - - - - - -Acme — flags.production.json - - - -
    - -
    -
    Acme / editor / feature-flags
    -

    flags.production.json

    -

    A form-based editor for the production feature-flag config. - Toggle flags, fix dependency warnings as they surface, then copy out - only the lines that changed.

    -
    - -
    - - -
    - - -
    - -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/20-editor-prompt-tuner.html b/skills/html-plan/references/html-effectiveness/20-editor-prompt-tuner.html deleted file mode 100644 index 7a27d03..0000000 --- a/skills/html-plan/references/html-effectiveness/20-editor-prompt-tuner.html +++ /dev/null @@ -1,723 +0,0 @@ - - - - - - -Acme — Support reply prompt tuner - - - -
    - -
    -
    Acme / editor / prompt-tuner
    -

    Support reply draft prompt

    -

    Edit the system prompt on the left and watch three sample tickets re-render the filled template on the right, live as you type. When it reads well across all three moods, copy the template out.

    -
    - -
    - - -
    -
    slots use {{double_brace}} syntax
    -
    - -
    - - -
    -
    - Template -
    - 0 chars · ~0 tokens -
    -
    -
    -
    Available slots
    -
    -
    -
    - - -
    -
    Live preview · 3 sample tickets
    -
    -
    - -
    - -
    Highlighted slots fill from each sample's ticket fields. Anything underlined in dashed clay isn't a known field and will pass through unfilled.
    - -
    - - - - diff --git a/skills/html-plan/references/html-effectiveness/CODE_OF_CONDUCT.md b/skills/html-plan/references/html-effectiveness/CODE_OF_CONDUCT.md deleted file mode 100644 index 91bac7d..0000000 --- a/skills/html-plan/references/html-effectiveness/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,49 +0,0 @@ -# Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment include: - -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -- Focusing on what is best for the overall community - -Examples of unacceptable behavior include: - -- The use of sexualized language or imagery, and sexual attention or advances of - any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email address, - without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the project maintainers at **opensource@anthropic.com**. All -complaints will be reviewed and investigated promptly and fairly. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.1, available at -https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. - -[homepage]: https://www.contributor-covenant.org diff --git a/skills/html-plan/references/html-effectiveness/LICENSE b/skills/html-plan/references/html-effectiveness/LICENSE deleted file mode 100644 index 02fe842..0000000 --- a/skills/html-plan/references/html-effectiveness/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2026 Anthropic PBC - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/skills/html-plan/references/html-effectiveness/README.md b/skills/html-plan/references/html-effectiveness/README.md deleted file mode 100644 index aace658..0000000 --- a/skills/html-plan/references/html-effectiveness/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# The unreasonable effectiveness of HTML — examples - -> **Sample code. Not maintained and not accepting contributions.** - -A gallery of standalone HTML examples that accompany the blog post on using HTML -as a flexible output format. Each file is a self-contained `.html` page (no build -step, no dependencies) demonstrating a different use case — from code review and -design systems to slide decks, status reports, and small interactive editors. - -Open [`index.html`](index.html) for the full, categorized index, or open any -numbered file directly in a browser. - -## Contents - -| Category | Examples | -|---|---| -| Exploration | code approaches, visual designs | -| Code | review, understanding, design systems, component variants | -| Prototyping | animation, interaction | -| Communication | slide deck, status report, incident report, PR write-up | -| Diagrams & research | flowchart, feature/concept explainers | -| Custom editing UIs | triage board, feature flags, prompt tuner | - -## Running - -There is nothing to install or build. Clone the repo and open `index.html` (or -any individual file) in a web browser. - -## A note on sample data - -All product names, data, and scenarios in these examples are fictional and used -only for illustration. The placeholder brand "Acme" and any figures shown are -not real. - -## Security - -See [SECURITY.md](SECURITY.md) for how to report a vulnerability. - -## License - -Released under the [Apache License 2.0](LICENSE). diff --git a/skills/html-plan/references/html-effectiveness/SECURITY.md b/skills/html-plan/references/html-effectiveness/SECURITY.md deleted file mode 100644 index 70e008f..0000000 --- a/skills/html-plan/references/html-effectiveness/SECURITY.md +++ /dev/null @@ -1,22 +0,0 @@ -# Security Policy - -## Reporting a vulnerability - -If you believe you have found a security vulnerability in this repository, -please report it responsibly. - -- **Do not** open a public issue for security problems. -- Email **security@anthropic.com** with a description of the issue and steps to - reproduce it. - -We will acknowledge your report, investigate, and keep you informed of the -resolution. - -## Scope - -This repository contains static, self-contained HTML example files with no -server-side components, no build pipeline, and no third-party runtime -dependencies. The most likely relevant reports are issues such as unsafe inline -script behavior or content that could mislead a reader. General questions about -the accompanying blog post are not security issues — please use normal issues -for those. diff --git a/skills/html-plan/references/html-effectiveness/index.html b/skills/html-plan/references/html-effectiveness/index.html deleted file mode 100644 index 4b06272..0000000 --- a/skills/html-plan/references/html-effectiveness/index.html +++ /dev/null @@ -1,823 +0,0 @@ - - - - - - -The unreasonable effectiveness of HTML — examples - - - -
    - -
    -
    -
    -
    Companion to the blog post
    -

    The unreasonable effectiveness of HTML

    -

    - Twenty self-contained .html files an agent produced instead of a wall of markdown. - Each one trades a document you'd skim for one you'd actually read — open any of them directly in - a browser. Grouped by the kind of work they replace. -

    - -
    - -
    -
    - - -
    -
    01

    Exploration & Planning

    3 demos
    -

    - When you're not sure what you want yet. Ask the agent to fan out across several directions and lay - them next to each other so you can point at one — instead of reading three sequential walls of text - and trying to hold them all in your head. And once you've picked, turn the pick into a plan the - implementer can actually read. -

    - -
    - - -
    -
    02

    Code Review & Understanding

    3 demos
    -

    - Diffs and call-graphs are spatial information; markdown flattens them. Let the agent render the - change as an annotated diff, draw the module as boxes and arrows, or write the PR description your - reviewers actually want — so the shape of the code is visible at a glance. -

    - -
    - - -
    -
    03

    Design

    2 demos
    -

    - HTML is the medium your design system ships in, so it's the natural format for talking about - it. Tokens become swatches, components become contact sheets, and the artifact can be fed straight - back into the next prompt. -

    - -
    - - -
    -
    04

    Prototyping

    2 demos
    -

    - Motion and interaction can't be described, only felt. A throwaway page with the real easing curve or - the real click-through tells you in five seconds what a paragraph of prose never could. -

    - -
    - - -
    -
    05

    Illustrations & Diagrams

    2 demos
    -

    - Inline SVG gives the agent a real pen. Ask for the figures for a post or a flowchart of a process and - get vector art you can tweak by hand or paste straight into the final document. -

    - -
    - - -
    -
    06

    Decks

    1 demo
    -

    - A handful of <section> tags and twenty lines of JS is a slide deck. Point the agent at a - Slack thread or a design doc and get something you can arrow-key through in a meeting — no Keynote, - no export step. -

    - -
    - - -
    -
    07

    Research & Learning

    2 demos
    -

    - An explainer with collapsible sections, tabbed code samples and a glossary in the margin reads very - differently from the same words dumped linearly. The agent can build the scaffolding that makes a new - topic navigable. -

    - -
    - - -
    -
    08

    Reports

    2 demos
    -

    - Recurring documents — status updates, post-mortems — benefit most from a bit of structure and color. - A small chart and a colored timeline turn something people skim into something they actually read. -

    - -
    - - -
    -
    09

    Custom Editing Interfaces

    3 demos
    -

    - Sometimes it's hard to describe what you want in a text box. Ask for a throwaway editor for the exact - thing you're working on — and always end with an export button that turns whatever you did in the UI - back into something you can paste into the agent or commit. You stay in the loop; the loop gets tighter. -

    - -
    - - - -
    - - diff --git a/skills/html-prototype/SKILL.md b/skills/html-prototype/SKILL.md new file mode 100644 index 0000000..0e60f8d --- /dev/null +++ b/skills/html-prototype/SKILL.md @@ -0,0 +1,97 @@ +--- +name: html-prototype +description: Direct-invocation specialist for polished, responsive, self-contained HTML mockups and interactive prototypes grounded in the user's conversation, product context, and design language. Use when the user explicitly invokes html-prototype or the broad html skill routes a mockup or prototype request here. Do not activate independently from a general request. Treat a mockup as a noninteractive fidelity mode within this skill, not as a separate skill. +--- + +# HTML Prototype + +Build a credible model of a product decision. Match the artifact to the user's context instead of applying a recurring house style. The goal is not to make every possible screen. The goal is to make the important visual or behavioral question testable. + +## Choose the fidelity mode + +Use one of two modes: + +- **Mockup:** Create a polished, responsive, mostly static artifact when the open question is visual hierarchy, layout, typography, color, or product fit. +- **Prototype:** Create a working flow when the open question is navigation, input, state change, feedback, recovery, or transition. + +Do not create a separate `html-mockup` skill. Do not add behavior merely to make a mockup seem more complete. If a user asks for both modes, preserve the same content and structure so changes in fidelity remain easy to compare. + +## Derive the direction from context + +Inspect the conversation, supplied references, and project before designing. Look for design-system documentation, tokens, existing components, product screenshots, and nearby artifacts. + +Authority runs in this order: + +1. The user's explicit visual and functional instructions. +2. The project's established design language and interaction conventions. +3. The product, audience, content, and scenario. +4. Your own design judgment. + +Before coding, settle: + +- the user and critical job; +- the bounded scenario under review; +- mockup or prototype mode; +- the source of the visual direction; +- the relevant state model; +- the point where the real product would take over. + +When no design system exists, create a specific direction from the subject and use case. Do not default to a gradient, a dark dashboard, interchangeable cards, or decorative metrics. A prototype for a field tool, an editorial workflow, and a financial approval should not feel like the same product. + +## Scope one credible experience + +Choose the smallest flow that can answer the review question. Use realistic, internally consistent names, dates, statuses, quantities, and copy. + +- Make navigation work for the modeled scope. +- Implement forms with labels, validation, submission feedback, and sensible defaults. +- Use dialogs only when interruption or confirmation is part of the scenario. +- Use transitions to clarify continuity or state change, not as decoration. +- Remove dead buttons. If an action belongs to the real system, explain the boundary instead of pretending it completed. + +## Model relevant states + +List the states before building. Include the states that the chosen scenario can actually reach: + +- loading; +- empty; +- error; +- success; +- disabled; +- mobile; +- domain-specific states from the brief. + +An asynchronous-looking prototype action should normally show loading, success, and failure or recovery. A collection should normally consider empty state. A gated action should show why it is disabled. Do not force irrelevant states into the main flow just to satisfy a checklist. Make omitted states explicit in the handoff. + +## Make interaction complete + +- Use native elements when they provide the right semantics. +- Support the entire modeled flow with a keyboard. +- Keep focus visible and place it deliberately after meaningful transitions. +- Give dialogs an accessible name, contain focus, close on `Escape`, and restore focus to the trigger. +- Associate form errors with their controls and announce important status changes. +- Do not hide essential behavior behind hover. +- Respect `prefers-reduced-motion` while preserving state feedback. +- Make touch targets usable and prevent accidental page-level horizontal overflow. + +In mockup mode, preserve semantic structure and visible focus styles even if the controls are not wired. Make the static review boundary clear. + +## Build contract + +- Deliver one self-contained `.html` file with essential CSS and JavaScript inline. +- Require no build tooling, authentication, live API, or external service. +- Use a responsive composition rather than shrinking a desktop canvas. +- Keep design tokens small and specific to the chosen direction. +- Use accessible contrast and more than color alone to communicate state. +- Prefer depth and correctness in one flow over breadth across a fake product. + +## Verify and hand off + +Test the artifact at wide desktop and narrow mobile widths. Exercise every modeled state and control. Test `Tab`, `Shift+Tab`, `Enter`, `Space`, arrow keys where appropriate, and `Escape` for dialogs. Check the console, page overflow, long content, disabled behavior, focus restoration, and reduced-motion mode. + +Inspect computed foreground and background colors on every distinct surface, especially text that may inherit the body color inside a dark or tinted region. If browser tooling is unavailable, say which visual and interaction checks remain unverified instead of treating source inspection as a substitute. + +Return the absolute file path, the fidelity mode, the scenario modeled, the states implemented, and the production behavior deliberately left out. + +## Further reading + +Read Plannotator's [HTML wireframes and prototypes for coding agents](https://docs.plannotator.ai/learn/code-context/html-wireframes-and-prototypes-for-coding-agents) for guidance on moving from an approved structure to a mockup or working prototype. diff --git a/skills/html-prototype/agents/openai.yaml b/skills/html-prototype/agents/openai.yaml new file mode 100644 index 0000000..a96abdf --- /dev/null +++ b/skills/html-prototype/agents/openai.yaml @@ -0,0 +1,7 @@ +interface: + display_name: "HTML Prototype" + short_description: "Direct skill for HTML mockups and prototypes" + default_prompt: "Use $html-prototype to build a responsive HTML mockup or working prototype for this product brief." + +policy: + allow_implicit_invocation: false diff --git a/skills/html-wireframe/SKILL.md b/skills/html-wireframe/SKILL.md new file mode 100644 index 0000000..1af65d4 --- /dev/null +++ b/skills/html-wireframe/SKILL.md @@ -0,0 +1,82 @@ +--- +name: html-wireframe +description: Direct-invocation specialist for low-fidelity, self-contained HTML wireframes that test information hierarchy, content, navigation, task flow, and responsive structure before visual design. Use when the user explicitly invokes html-wireframe or the broad html skill routes a wireframe request here. Do not activate independently from a general request. Do not use for polished mockups or production-like interaction; use html-prototype for those. +--- + +# HTML Wireframe + +Turn a product question into a low-fidelity HTML artifact that is easy to inspect, change, and discuss. The wireframe should help reviewers decide what belongs on the screen and how the task should work. It should not look like a finished product. + +## Establish the review question + +Read the conversation, supplied brief, and nearby project material before choosing a layout. Reuse the project's vocabulary, content model, and known product constraints. + +Authority runs in this order: + +1. The user's explicit instructions and accepted decisions. +2. The product's existing structure and terminology. +3. The user, task, and content being modeled. +4. Your own layout judgment. + +Before coding, identify: + +- the user and the job they need to complete; +- the screen or bounded flow under review; +- the information and actions the artifact must contain; +- the assumptions that can be made safely; +- the structural questions the wireframe should help answer. + +Use real labels and representative content. Low fidelity is not permission to use anonymous boxes or lorem ipsum where wording affects the layout. + +## Explore structure before style + +When the layout is still unsettled, create two or three meaningfully different directions. Vary product decisions such as: + +- navigation model; +- grouping and order; +- primary-action placement; +- content density; +- overview versus step-by-step flow; +- desktop-to-mobile reflow. + +Do not call color changes or minor card rearrangements separate directions. Give each direction a short descriptive name and one sentence about its tradeoff. + +Keep the directions in one HTML file when practical. Use a small, keyboard-operable selector so reviewers can compare them without opening several files. Preserve the same core content and task across directions. If the user has already chosen a structure, build that direction only. + +## Keep the artifact intentionally unfinished + +- Use a restrained grayscale palette, system type, plain borders, and simple blocks. +- Avoid brand colors, gradients, shadows, illustrations, decorative imagery, and polished component styling. +- Use limited radius and spacing. Enough order should be present to judge hierarchy, but not enough polish to invite a brand review. +- Show images or rich media as labeled placeholders unless the asset changes a structural decision. +- Add annotations only when they expose an assumption, open question, or behavior that cannot be shown directly. + +The wireframe may still be well composed. Intentional unfinishedness is different from careless spacing, illegible type, or broken responsive behavior. + +## Add only useful behavior + +Use basic click-through behavior when it helps test navigation, disclosure, or a short task flow. Keep it immediate and plain. + +- Make links, tabs, and next or back actions work when they are part of the review. +- Use native controls and visible keyboard focus. +- Do not build elaborate animation, persistence, simulated APIs, or production state management. +- Remove controls that have no review purpose, or label them clearly as out of scope. + +## Build contract + +- Deliver one self-contained `.html` file with essential CSS and JavaScript inline. +- Require no build tooling or external service. +- Use semantic landmarks, headings, lists, forms, and buttons. +- Make the layout useful at wide desktop and narrow mobile widths. +- Keep the page free of accidental horizontal overflow. +- Respect the source material. Do not invent extra product scope to fill space. + +## Verify and hand off + +Open the result at desktop and mobile widths. Check reading order, wrapping, overflow, focus visibility, and every implemented click path. Confirm that the directions remain structurally distinct at both sizes. + +Return the absolute file path, the names and tradeoffs of the directions, and the visual decisions deliberately deferred to a later mockup or prototype. + +## Further reading + +Read Plannotator's [HTML wireframes and prototypes for coding agents](https://docs.plannotator.ai/learn/code-context/html-wireframes-and-prototypes-for-coding-agents) for guidance on what to decide at the wireframe stage. diff --git a/skills/html-wireframe/agents/openai.yaml b/skills/html-wireframe/agents/openai.yaml new file mode 100644 index 0000000..9eb7e66 --- /dev/null +++ b/skills/html-wireframe/agents/openai.yaml @@ -0,0 +1,7 @@ +interface: + display_name: "HTML Wireframe" + short_description: "Direct skill for low-fidelity HTML layouts" + default_prompt: "Use $html-wireframe to explore low-fidelity layouts for this product brief." + +policy: + allow_implicit_invocation: false diff --git a/skills/html/SKILL.md b/skills/html/SKILL.md index f2a2e27..637a630 100644 --- a/skills/html/SKILL.md +++ b/skills/html/SKILL.md @@ -1,13 +1,69 @@ --- name: html -description: Create a self-contained HTML file for whatever the user is describing, in the effective HTML style. Use when the user wants an HTML artifact that isn't specifically a diagram or a plan — a report, explainer, comparison, deck, prototype, or anything else best delivered as one HTML file. -disable-model-invocation: true +description: Create or redesign self-contained single-file HTML artifacts with a visual direction shaped by the user's brief, project, and subject. Use when HTML is the deliverable for a report, explainer, landing page, presentation, tool, mixed artifact, or broad request. This is the collection's only implicit router. Route clear wireframe, prototype, mockup, plan, or diagram requests to the matching direct-invocation specialist when available. Do not use for ordinary application implementation when a standalone HTML file is not the deliverable. --- # HTML -Review the files throughout `references/html-effectiveness/`. +Build one self-contained HTML file that makes the subject clearer, easier to use, or easier to understand. The standard is consistent care, not a consistent look. Do not reproduce a house palette, typography stack, card system, or layout from prior runs. -Create an HTML file for whatever the user is describing. Use the references as best you can to match alignment — style, density, and tone. +## Route the request first -Always include dark mode: hand-rolled CSS variables on `:root` / `html.dark`, a small theme toggle button, `localStorage` persistence, and an apply-before-paint script in `` (default to `prefers-color-scheme`). +Use the narrowest skill that owns the main review question: + +- Read and follow [`html-wireframe`](../html-wireframe/SKILL.md) when structure, information hierarchy, navigation, or task flow is still unsettled. It should remain visibly low fidelity and may compare two or three layout directions. +- Read and follow [`html-prototype`](../html-prototype/SKILL.md) when the user needs a polished mockup or a working interactive flow. A mockup is the static fidelity mode inside that skill. +- Read and follow [`html-plan`](../html-plan/SKILL.md) when the artifact is primarily a plan, roadmap, implementation sequence, or rollout document whose source commitments must remain easy to verify. +- Read and follow [`html-diagram`](../html-diagram/SKILL.md) when relationships, sequence, topology, state, hierarchy, or system behavior are the main content. +- Continue with `html` for reports, explainers, presentations, landing pages, data stories, tools, and mixed artifacts that do not have a clearer owner. + +These sibling links are the nesting mechanism when the collection is installed together. If a specialized skill is unavailable, continue here and load the closest reference below. Do not make the user install another skill before completing the request. + +## Read the room before designing + +Inspect the user's request and any material they supplied. When working in a repository, look for its design language in `AGENTS.md`, `CLAUDE.md`, design-system documentation, tokens, existing components, and nearby artifacts. + +Authority runs in this order: + +1. The user's explicit visual and functional instructions. +2. The project's established design system and conventions. +3. The subject matter, audience, and purpose of this artifact. +4. Your own design judgment. + +Before coding, settle five things in working notes: + +- **Audience and job:** who will use this, and what should they understand or do? +- **Form:** document, presentation, interface, diagram, or data visualization. +- **Register:** quiet and workmanlike, polished and editorial, or intentionally expressive. +- **Fidelity:** whether to preserve the user's structure and wording or synthesize more freely. +- **Interaction:** what benefits from exploration, sequencing, filtering, or motion, if anything. + +If the project already answers the visual questions, follow it. Otherwise read [`references/creative-direction.md`](references/creative-direction.md) before choosing the palette, type, composition, or motion. + +## Load only the guidance the artifact needs + +- For reports, briefs, plans, explainers, and decks, read [`references/documents-and-presentations.md`](references/documents-and-presentations.md). +- For interfaces, calculators, and other tools that remain in this broad skill, read [`references/interfaces.md`](references/interfaces.md). +- For architecture, process, sequence, state, hierarchy, or concept diagrams, read [`references/diagrams.md`](references/diagrams.md). +- For quantitative charts, tables, metrics, or data stories, read [`references/charts-and-data.md`](references/charts-and-data.md). + +Requests can span forms. Read every reference that materially applies, then give the artifact one coherent direction. + +## Build contract + +- Produce one `.html` file with its essential CSS and JavaScript inline. It should work when opened directly, without a build step. Do not require a network connection unless the user permits external dependencies. +- Use real content. Do not fill prominent space with placeholder copy, decorative statistics, or controls that do nothing. +- Let content determine structure. A sequence should read in order; a comparison should make differences easy to scan; an interface should expose state and actions; a diagram should make relationships legible. +- Use semantic HTML, responsive layout, accessible contrast, visible keyboard focus, and reduced-motion handling. Make interactive elements work with a keyboard. +- Keep the page body free of accidental horizontal overflow. Put intentionally broad content in a contained scrolling or pannable region. +- Define a small set of CSS tokens for the chosen direction and use them consistently. Tokens are an implementation tool, not a predetermined palette. +- Treat motion as explanation or feedback. If removing an animation loses no meaning or useful feedback, remove it. +- Follow the user's or project's theme policy. When none exists, give durable utility artifacts considered light and dark themes if that improves their use. A deliberate single-theme concept is valid. + +## Finish the work + +Write the file to the requested location, or choose a clear filename in the current workspace. When browser tooling is available, open it and inspect a wide and narrow viewport. Exercise its controls, check the console, and fix clipping, overlap, illegible text, broken states, and accidental overflow. + +Before delivery, run one originality check: if the subject were swapped for a neighboring topic, would the same visual concept still make just as much sense? If yes, the direction is too generic; revise the composition, type, color, imagery, or interaction so it belongs to this subject. + +Return the absolute path and a short description of the artifact's visual and interaction choices. diff --git a/skills/html/agents/openai.yaml b/skills/html/agents/openai.yaml index 3a5df66..372eac5 100644 --- a/skills/html/agents/openai.yaml +++ b/skills/html/agents/openai.yaml @@ -1,7 +1,7 @@ interface: display_name: "HTML" - short_description: "Create effective standalone HTML artifacts" - default_prompt: "Use $html to create a polished standalone HTML artifact." + short_description: "Implicit router for standalone HTML artifacts" + default_prompt: "Use $html to choose the right Effective HTML workflow and create a self-contained artifact from this brief." policy: - allow_implicit_invocation: false + allow_implicit_invocation: true diff --git a/skills/html/references/charts-and-data.md b/skills/html/references/charts-and-data.md new file mode 100644 index 0000000..679a00c --- /dev/null +++ b/skills/html/references/charts-and-data.md @@ -0,0 +1,32 @@ +# Charts and data + +Read this when the artifact contains quantitative charts, metrics, tables, or a data-driven story. + +Start with the comparison the viewer needs to make. Select the chart from that question rather than from visual novelty: + +- Change over time → line, area, or aligned small multiples. +- Ranked magnitude → ordered bars or a table with visual emphasis. +- Part to whole → stacked bars when the denominator is meaningful; avoid decorative slices. +- Distribution → histogram, dot plot, box plot, or density view. +- Relationship → scatter plot with meaningful scales and annotations. +- Flow → Sankey or network only when path magnitude is genuinely the point. + +Use a table when exact values matter more than shape. A chart and a compact table can coexist when they serve different reading needs. + +## Make the data honest + +- Label units, time ranges, sources, and important filters. +- Use scales that support the intended comparison. Make truncation or nonlinearity explicit. +- Separate measured values, estimates, targets, and forecasts visually and in text. +- Do not invent data to make the artifact look complete. Mark missing or illustrative values plainly. +- Keep color categories consistent and distinguishable without relying on color alone. +- Treat status colors separately from the general palette. +- Give dense data room; contain horizontal overflow rather than compressing labels into illegibility. + +## Interaction + +Tooltips should add precision, not carry facts that the chart otherwise fails to communicate. Keep essential values and conclusions available without hover. + +Filters, brushing, zooming, and linked views should answer real follow-up questions. Show active filters and provide a clear reset. Preserve an accessible summary or table for data that is otherwise available only through pointer interaction. + +Use animation to explain change between states, not to make bars and lines perform on arrival. diff --git a/skills/html/references/creative-direction.md b/skills/html/references/creative-direction.md new file mode 100644 index 0000000..354f286 --- /dev/null +++ b/skills/html/references/creative-direction.md @@ -0,0 +1,48 @@ +# Creative direction + +Read this when the user or project has not already supplied a complete visual direction. + +Operate like a small design studio with range, not a template engine with a favorite costume. Every artifact should feel designed for this commission. A planning memo, systems map, product demo, and launch deck can all show equal care without sharing a palette, typeface, silhouette, or amount of drama. + +## Find the direction inside the brief + +Start with the subject's own world: its materials, tools, environments, notation, history, audience, and language. Pull one organizing idea from there. It might shape the grid, the behavior of a diagram, the rhythm of the type, the way information reveals itself, or the role of imagery. + +Choose a register that fits: + +- **Workmanlike:** quiet hierarchy, exact spacing, restrained color, direct language. Right for plans, internal briefs, operational reports, and many tools. +- **Editorial:** stronger composition, distinctive type, art-directed pacing, and one memorable visual move. Right for explainers, launches, research stories, and presentations that need to travel. +- **Expressive:** a more immersive visual or interactive idea whose execution is itself part of the message. Use rarely, when the subject truly benefits. + +Do not confuse restraint with neglect or expression with a theatrical hero. Finish the chosen register properly. + +## Make a short design plan + +Before writing CSS, decide: + +- The visual premise in one sentence. +- The hierarchy and organizing layout. +- The color roles and why they belong to the subject. +- The type roles and the voice each contributes. +- The density, edge treatment, and image or diagram language. +- The one place, if any, where motion or interaction carries meaning. + +The number of colors, typefaces, columns, and components should follow the idea. Do not satisfy a quota. + +## Avoid the template reflex + +Common components are not a visual direction. Cards, pills, rounded rectangles, gradients, tiny uppercase labels, large numerals, and side rails may be useful, but each must express real structure. Do not use them merely because they make an unfinished page look designed. + +Vary more than color. A new palette on the same centered hero and card grid is still the same design. Reconsider composition, scale, density, typography, shape language, navigation, and interaction. + +Use one decisive move rather than many unrelated flourishes. Let the rest of the page support it. + +Typography should establish voice and hierarchy. One well-used family can outperform an arbitrary pairing; several roles are useful only when they remain coherent. Use system fonts when they suit the brief. Embed custom fonts only when their value justifies the file weight and their license permits it. + +Color should be selected rather than inherited from habit. Neutrals are part of the palette. Status colors must remain semantically distinct from the decorative accent. + +## Respect prior art + +When the user names a style or supplies a reference, follow it faithfully, even if it resembles a convention you would not choose yourself. When a project has tokens and components, use them before inventing replacements. + +Bundled guidance is for technique, not imitation. Never copy a previous artifact's palette, typography, or composition simply because it worked once. diff --git a/skills/html/references/diagrams.md b/skills/html/references/diagrams.md new file mode 100644 index 0000000..4e55cac --- /dev/null +++ b/skills/html/references/diagrams.md @@ -0,0 +1,68 @@ +# Diagrams, architecture, and sequences + +Read this when relationships, flow, time, state, or structure are the main thing the artifact must explain. + +## Choose the diagram before choosing the renderer + +Name the question the viewer should be able to answer, then choose the visual grammar: + +| Question | Useful grammar | +| --- | --- | +| What exists, and how is it connected? | Topology or system map | +| What happens over time? | Sequence, timeline, or request trace | +| What decisions or transformations occur? | Process flow | +| How can something change? | State diagram | +| What contains or owns what? | Hierarchy or nested boundary map | +| How do alternatives compare? | Matrix or aligned comparison | +| How much, how often, or how fast? | Quantitative chart; also read [`charts-and-data.md`](charts-and-data.md) | + +Do not force several questions into one overloaded picture. Use coordinated views or selectable layers when the audience genuinely needs more than one. + +## Choose the medium from the information + +- **HTML and CSS:** strong for labeled regions, aligned comparisons, grids, timelines, and diagrams whose text needs to reflow. +- **SVG:** strong for crisp relational diagrams, custom paths, annotations, and interactive vector scenes. +- **Canvas:** strong for dense, frequently changing, or generative graphics where thousands of DOM nodes would be wasteful. +- **WebGL:** reserve for spatial, high-volume, or truly three-dimensional work that earns the added complexity. + +Mix media when useful. A diagram can use semantic HTML controls and explanation around an SVG or Canvas stage. +Style SVG elements through CSS classes and the artifact's chosen tokens when practical so the scene remains coherent across states and themes. + +## Make the structure legible + +- Establish hierarchy with position, grouping, containment, scale, and whitespace before reaching for color. +- Keep labels readable at the default view. Do not rotate important prose or place text over busy paths. +- Route connectors around nodes and labels. Make direction unmistakable and distinguish different edge meanings. +- Use boundaries to communicate ownership, trust, deployment, or responsibility, not as decoration. +- Keep a stable overview while exposing detail on demand. +- For architecture, show the concepts the audience uses. File names and implementation classes belong only when the question is specifically about code structure. + +Avoid the automatic architecture wallpaper of identical rounded boxes connected by arrows. Services, queues, actors, boundaries, stores, and transformations do not all need the same shape or visual weight. + +## Sequence and interaction + +Sequence should expose causality, not merely flash elements in order. + +- Give steps durable labels and a visible current state. +- Let the viewer play, pause, restart, step, or choose a path when the sequence is more than a brief self-explanatory animation. +- Keep the full system understandable when animation is stopped. +- Use motion to trace requests, reveal transitions, or connect cause with effect. Respect `prefers-reduced-motion` with an immediate or step-based alternative. +- Use filtering and layer toggles when they reduce complexity without hiding necessary context. + +If nodes expose details, make selection obvious. Floating panels must be dismissible and must reopen from the relevant node or control. Important information must remain reachable by keyboard. + +## Pan and zoom only when needed + +A clear diagram that fits should not become a map application. Add pan and zoom when the information space materially exceeds the viewport or close inspection is part of the task. + +For an SVG stage: + +- Transform one containing `` rather than rewriting every node. +- Keep pointer, pan, and zoom math in a single coordinate system. Preserve the point under the cursor while zooming. +- Suppress click activation after a drag using a small movement threshold. +- Provide `grab` and `grabbing` feedback, a visible zoom level, and a reset control. +- Set useful minimum and maximum scales and ensure the initial fit is understandable. + +## Verify the picture + +Inspect the default overview, every interactive state, and any sequence endpoints. Check that connectors do not cross labels, arrows terminate cleanly, text remains legible, panels do not cover critical content, and narrow-screen behavior has an intentional fallback. diff --git a/skills/html/references/documents-and-presentations.md b/skills/html/references/documents-and-presentations.md new file mode 100644 index 0000000..8fef75d --- /dev/null +++ b/skills/html/references/documents-and-presentations.md @@ -0,0 +1,28 @@ +# Documents and presentations + +Read this for reports, briefs, plans, explainers, comparisons, and slide-like artifacts. + +## Documents + +Design around the reader's decision or understanding, not around a generic page outline. The opening should orient quickly: what this is, why it matters, and what deserves attention. Follow with evidence, structure, and detail in the order the reader needs them. + +- Keep prose measures readable and let tables, timelines, code, and diagrams use wider regions. +- Use headings, labels, numbering, dividers, and callouts only when they express genuine hierarchy or sequence. +- For plans, stay close to the user's language and ambition. Clarify ownership, order, dependencies, risks, and completion conditions without inventing a larger program. +- For reports, distinguish observation, interpretation, recommendation, and uncertainty. +- For comparisons, keep like-for-like attributes aligned so the eye can compare without remembering. +- For print-oriented work, add sensible print styles and avoid interactions that hide essential content. + +Most operational documents want a workmanlike register. They still deserve intentional typography, spacing, and color, but rarely need a giant hero or ornamental dashboard furniture. + +## Presentations + +A presentation is paced, not merely paginated. Give each screen one job and one dominant idea. + +- Establish a visual rhythm across slides, then break it only for emphasis. +- Keep essential information visible without hover. +- If the file behaves like a deck, support keyboard navigation, clear progress, and direct slide links when practical. +- Use builds and transitions to control explanation order, not to decorate every change. +- Ensure a useful narrow-screen or scrolling fallback when the fixed stage cannot fit. + +When a request blends a document and a deck, prefer the reading mode the audience will actually use rather than building two half-working experiences. diff --git a/skills/html/references/html-effectiveness/01-exploration-code-approaches.html b/skills/html/references/html-effectiveness/01-exploration-code-approaches.html deleted file mode 100644 index fc0c648..0000000 --- a/skills/html/references/html-effectiveness/01-exploration-code-approaches.html +++ /dev/null @@ -1,454 +0,0 @@ - - - - - - - Debounced search — three approaches - - - -
    - -
    -
    Exploration · Acme web client
    -

    Three ways to implement debounced search

    -
    - Prompt - Show me three different ways to implement debounced search for the task - filter input in our React codebase, with tradeoffs for each. -
    -
    - - - -
    - - -
    -
    -

    01Inline useEffect + setTimeout

    -

    Debounce logic lives directly inside the component that owns the input.

    -
    - -
    export function TaskSearch() {
    -  const [draft, setDraft] = useState('');
    -  const [query, setQuery] = useState('');
    -
    -  useEffect(() => {
    -    const id = setTimeout(() => setQuery(draft), 300);
    -    return () => clearTimeout(id);
    -  }, [draft]);
    -
    -  const { data } = useTasks({ search: query });
    -
    -  return (
    -    <input
    -      value={draft}
    -      onChange={(e) => setDraft(e.target.value)}
    -      placeholder="Filter tasks…"
    -    />
    -  );
    -}
    - -
    -
    -
    Pro
    -
    Con
    -
    -
    -
    Zero new abstractions to learn
    -
    Logic duplicated everywhere search exists
    -
    -
    -
    Easy to step through in devtools
    -
    Two pieces of state for one conceptual value
    -
    -
    -
    No dependency or bundle change
    -
    Delay constant is buried in component body
    -
    -
    - -
    - Bundle impact: +0 kb - Testability: medium - Reuse: low - SSR safe: yes -
    -
    - - -
    -
    -

    02Custom useDebounce hook

    -

    Extract the timer into a shared hook under src/hooks/.

    -
    - -
    // src/hooks/useDebounce.ts
    -export function useDebounce<T>(value: T, ms = 300): T {
    -  const [debounced, setDebounced] = useState(value);
    -  useEffect(() => {
    -    const id = setTimeout(() => setDebounced(value), ms);
    -    return () => clearTimeout(id);
    -  }, [value, ms]);
    -  return debounced;
    -}
    -
    -// TaskSearch.tsx
    -const [draft, setDraft] = useState('');
    -const query = useDebounce(draft, 300);
    -const { data } = useTasks({ search: query });
    - -
    -
    -
    Pro
    -
    Con
    -
    -
    -
    Single import reused across filter, command bar, board search
    -
    One more file to maintain and document
    -
    -
    -
    Trivial to unit test with fake timers
    -
    Generic T hides intent slightly
    -
    -
    -
    Delay is a visible, tunable argument
    -
    Still re-renders on every keystroke
    -
    -
    - -
    - Bundle impact: +0.2 kb - Testability: high - Reuse: high - SSR safe: yes -
    -
    - - -
    -
    -

    03Tiny external library

    -

    Adopt use-debounce for both values and callbacks.

    -
    - -
    import { useDebouncedCallback }
    -  from 'use-debounce';
    -
    -export function TaskSearch() {
    -  const [query, setQuery] = useState('');
    -
    -  const onChange = useDebouncedCallback(
    -    (next: string) => setQuery(next),
    -    300,
    -    { leading: false, maxWait: 1000 },
    -  );
    -
    -  const { data } = useTasks({ search: query });
    -
    -  return (
    -    <input
    -      defaultValue=""
    -      onChange={(e) => onChange(e.target.value)}
    -    />
    -  );
    -}
    - -
    -
    -
    Pro
    -
    Con
    -
    -
    -
    leading / trailing / maxWait handled for us
    -
    New runtime dependency to audit and update
    -
    -
    -
    Callback form skips intermediate re-renders
    -
    Uncontrolled input diverges from Acme form patterns
    -
    -
    -
    Well-tested edge cases (unmount, flush, cancel)
    -
    ~1.4 kb gzipped for something we could own
    -
    -
    - -
    - Bundle impact: +1.4 kb - Testability: high - Reuse: high - SSR safe: yes -
    -
    - -
    - - - - - -
    - - diff --git a/skills/html/references/html-effectiveness/02-exploration-visual-designs.html b/skills/html/references/html-effectiveness/02-exploration-visual-designs.html deleted file mode 100644 index 817fcc3..0000000 --- a/skills/html/references/html-effectiveness/02-exploration-visual-designs.html +++ /dev/null @@ -1,516 +0,0 @@ - - - - - - - Empty state — four visual directions - - - - -
    -
    Acme · design exploration
    -
    - Background: -
    - - -
    -
    -
    - -
    - -
    -
    Exploration · Empty states
    -

    Four visual directions for the “no tasks yet” state

    -
    - Prompt - Explore four visual directions for our empty-state component. Render each - live so we can compare tone, density, and how well they hold up on light - and dark surfaces. -
    -
    - -
    - - -
    - A — Minimal -
    -
    -

    No tasks yet

    -

    When you create a task it will show up here.

    - New task -
    -
    -

    - Pure typography, single quiet action. Reads as calm and confident; - assumes the surrounding UI already carries enough personality. -

    -
    - - -
    - B — Illustrated -
    -
    - -

    Start your first list

    -

    Group related work and watch progress roll up automatically.

    - Create a task -
    -
    -

    - A small geometric spot illustration anchors the eye and explains the - object model (lists contain tasks) without a wall of copy. -

    -
    - - -
    - C — Playful -
    -
    -
    -
    -
    -
    -
    -
    -

    Nothing on your plate

    -

    Enjoy the quiet, or add something to get moving.

    -
    -
    -

    - A gently bobbing stack adds life to an otherwise static screen. Motion - is subtle enough to loop indefinitely without drawing complaints. -

    -
    - - -
    - D — Instructional -
    -
    -

    Set up this project

    -
      -
    1. - Create your first task - Give it a name and an owner. -
    2. -
    3. - Add a due date - Acme will surface it on the timeline. -
    4. -
    5. - Invite a teammate - Shared projects stay in sync automatically. -
    6. -
    -
    -
    -

    - Treats the empty state as onboarding. Higher density, but every line is - actionable — best when the user is new to the product, not just the view. -

    -
    - -
    -
    - - - - diff --git a/skills/html/references/html-effectiveness/03-code-review-pr.html b/skills/html/references/html-effectiveness/03-code-review-pr.html deleted file mode 100644 index bfb344b..0000000 --- a/skills/html/references/html-effectiveness/03-code-review-pr.html +++ /dev/null @@ -1,639 +0,0 @@ - - - - - - -PR #247 — Review Summary - - - -
    - -
    -
    acme/web · Pull Request #247
    -

    Add optimistic updates to task list mutations

    -
    -
    -
    MO
    -
    -
    Mira Okafor
    -
    opened 2 days ago
    -
    -
    -
    - mo/optimistic-tasks main -
    -
    - +142 / −38 - 6 files changed -
    -
    -
    - -
    -

    What this PR does

    -
      -
    • Replaces the await-then-refetch pattern in TaskList with optimistic cache writes, so toggling or reordering a task feels instant instead of waiting ~300ms for the round-trip.
    • -
    • Introduces a small useOptimisticTasks hook that wraps the mutation, snapshots the previous list, and rolls back on error.
    • -
    • Extends the API client to accept an idempotency key per mutation and adds a toast when a rollback fires.
    • -
    -
    - -
    -

    Risk map

    - -
    - safe - worth a look - needs attention -
    -
    - -
    -

    Files

    - - -
    -
    -
    -
    src/hooks/useOptimisticTasks.ts
    -
    -
    - needs attention - +58 −0 -
    -
    -
    -
    @@ -0,0 +1,58 @@
    -
    1+import { useMutation, useQueryClient } from '@tanstack/react-query';
    -
    2+import { updateTask, TaskPatch } from '../api/tasks';
    -
    3+import type { Task } from '../types/task';
    -
    4+
    -
    5+export function useOptimisticTasks(boardId: string) {
    -
    6+ const qc = useQueryClient();
    -
    7+ const key = ['tasks', boardId];
    -
    8+
    -
    9+ return useMutation({
    -
    10+ mutationFn: (patch: TaskPatch) => updateTask(patch),
    -
    11+ onMutate: async (patch) => {
    -
    12+ const prev = qc.getQueryData<Task[]>(key);
    -
    13+ qc.setQueryData<Task[]>(key, (old = []) =>
    -
    14+ old.map(t => t.id === patch.id ? { ...t, ...patch } : t)
    -
    15+ );
    -
    16+ return { prev };
    -
    17+ },
    -
    18+ onError: (_e, _p, ctx) => qc.setQueryData(key, ctx?.prev),
    -
    19+ });
    -
    20+}
    -
    -
    -
    -
    line 11
    -

    BlockingonMutate doesn't call qc.cancelQueries(key) first. If a background refetch lands between the optimistic write and the server response, it will clobber the optimistic state and the UI will flicker back to the old value.

    -
    -
    -
    line 18
    -

    NitRollback restores the list but never surfaces the error. Consider wiring the existing pushToast here so users know the toggle didn't stick.

    -
    -
    -
    - - -
    -
    -
    -
    src/components/TaskList.tsx
    -
    -
    - worth a look - +31 −24 -
    -
    -
    -
    @@ -42,14 +42,17 @@ export function TaskList({ boardId }: Props) {
    -
    42 const { data: tasks } = useTasks(boardId);
    -
    43- const [pending, setPending] = useState<string | null>(null);
    -
    44-
    -
    45- async function toggle(task: Task) {
    -
    46- setPending(task.id);
    -
    47- await updateTask({ id: task.id, done: !task.done });
    -
    48- await refetch();
    -
    49- setPending(null);
    -
    50- }
    -
    43+ const { mutate, isPending } = useOptimisticTasks(boardId);
    -
    44+
    -
    45+ const toggle = (task: Task) =>
    -
    46+ mutate({ id: task.id, done: !task.done });
    -
    47
    -
    48 return (
    -
    49 <ul className="tasks">
    -
    50- {tasks?.map(t => <TaskRow key={t.id} task={t} busy={pending === t.id} />)}
    -
    50+ {tasks?.map(t => <TaskRow key={t.id} task={t} onToggle={toggle} />)}
    -
    51 </ul>
    -
    -
    -
    -
    line 43
    -

    NitisPending is destructured but never read. Either drop it or pass it to TaskRow so the checkbox can dim while the request is in flight.

    -
    -
    -
    - - -
    -
    -
    -
    src/api/tasks.ts
    -
    -
    - worth a look - +19 −6 -
    -
    -
    -
    @@ -12,10 +12,15 @@ export type TaskPatch = Partial<Task> & { id: string };
    -
    12
    -
    13-export async function updateTask(patch: TaskPatch) {
    -
    14- return http.patch(`/tasks/${patch.id}`, patch);
    -
    13+export async function updateTask(
    -
    14+ patch: TaskPatch,
    -
    15+ key = crypto.randomUUID(),
    -
    16+) {
    -
    17+ return http.patch(`/tasks/${patch.id}`, patch, {
    -
    18+ headers: { 'Idempotency-Key': key },
    -
    19+ });
    -
    20 }
    -
    -
    -
    -
    line 15
    -

    BlockingGenerating the idempotency key as a default parameter means retries from the mutation layer get a new key each time, which defeats the purpose. The key should be minted once in onMutate and threaded through.

    -
    -
    -
    - - -
    - - src/components/Toast.tsx - - safe - +14 −2 - - -
    Adds a variant="warning" style and exports pushToast. Purely additive, no behaviour change for existing call sites.
    -
    - -
    - - src/types/task.ts - - safe - +6 −2 - - -
    Widens Task.status to include "archived" and adds an optional updatedAt timestamp. Type-only change.
    -
    - -
    - - src/components/__tests__/TaskList.test.tsx - - safe - +14 −4 - - -
    Adds a test asserting the row updates synchronously after click, and one asserting rollback when the mocked request rejects. Both pass locally.
    -
    -
    - -
    -

    Suggested next steps

    -
      -
    • - - -
    • -
    • - - -
    • -
    • - - -
    • -
    -
    - -
    - - - - diff --git a/skills/html/references/html-effectiveness/04-code-understanding.html b/skills/html/references/html-effectiveness/04-code-understanding.html deleted file mode 100644 index e36505b..0000000 --- a/skills/html/references/html-effectiveness/04-code-understanding.html +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - -How authentication flows through acme/web - - - -
    - -
    -
    acme/web · architecture note
    -

    How authentication flows through the codebase

    -

    - Acme uses cookie-based sessions: the browser never holds a bearer token directly. Every authenticated request hits /api/*, passes through a single verifyToken() middleware, and resolves to a Session row that downstream handlers read off req.ctx. The middleware is the only place that talks to the session store, which is the only place that talks to the sessions table — so there's exactly one trust boundary to reason about. -

    -
    - -
    -

    Request path

    -
    - - - - - - - - - - - Browser - acme.app - - - - /api/session - route handler - - - - verifyToken() - middleware/auth.ts - - - - - - SessionStore - lib/sessionStore.ts - - - - Postgres - sessions table - - - - - - - - - cookie - lookup - -
    - -

    Callstack walkthrough

    - - -
    -
    1
    -
    -
    src/app/providers/AuthProvider.tsx :22-48
    -

    On mount, the React provider issues a GET /api/session with credentials: 'include' so the fw_sid cookie rides along. The response either hydrates currentUser into context or leaves it null, which the router treats as "show the sign-in screen".

    -
    - show source -
    // src/app/providers/AuthProvider.tsx
    -export function AuthProvider({ children }: Props) {
    -  const [user, setUser] = useState<User | null>(null);
    -
    -  useEffect(() => {
    -    fetch('/api/session', { credentials: 'include' })
    -      .then(r => r.ok ? r.json() : null)
    -      .then(setUser);
    -  }, []);
    -
    -  return <AuthCtx.Provider value={{ user }}>{children}</AuthCtx.Provider>;
    -}
    -
    -
    -
    - - -
    -
    2
    -
    -
    src/server/routes/session.ts :9-27
    -

    The route itself is thin: it just returns whatever req.ctx.session the middleware attached. If the middleware short-circuited with a 401, this handler never runs — so there's no auth logic duplicated here.

    -
    - show source -
    // src/server/routes/session.ts
    -router.get('/session', verifyToken, (req, res) => {
    -  const { session } = req.ctx;
    -  res.json({
    -    id:    session.userId,
    -    email: session.email,
    -    role:  session.role,
    -    exp:   session.expiresAt,
    -  });
    -});
    -
    -
    -
    - - -
    -
    3
    -
    -
    src/middleware/auth.ts :14-31
    -

    This is the trust boundary. verifyToken reads the signed fw_sid cookie, asks SessionStore to resolve it, and either populates req.ctx.session or responds 401. Every protected route in the app is mounted behind this function, so changing its behaviour changes auth globally.

    -
    - show source -
    // src/middleware/auth.ts
    -export async function verifyToken(req, res, next) {
    -  const raw = req.signedCookies['fw_sid'];
    -  if (!raw) return res.status(401).end();
    -
    -  const session = await SessionStore.get(raw);
    -  if (!session || session.expiresAt < Date.now()) {
    -    return res.status(401).end();
    -  }
    -
    -  req.ctx = { session };
    -  next();
    -}
    -
    -
    -
    - - -
    -
    4
    -
    -
    src/lib/sessionStore.ts :8-52
    -

    SessionStore is a small read-through cache: it checks an in-process LRU first, then falls back to Postgres. Writes (create, revoke) always go straight to the DB and invalidate the cache entry so other workers don't serve a stale session.

    -
    - show source -
    // src/lib/sessionStore.ts
    -const cache = new LRU<string, Session>({ max: 5000, ttl: 60_000 });
    -
    -export const SessionStore = {
    -  async get(id: string) {
    -    const hit = cache.get(id);
    -    if (hit) return hit;
    -    const row = await db.one(SELECT_SESSION, [id]);
    -    if (row) cache.set(id, row);
    -    return row ?? null;
    -  },
    -  /* create, revoke, touch ... */
    -};
    -
    -
    -
    - - -
    -
    5
    -
    -
    db/migrations/004_sessions.sql :1-18
    -

    The sessions table is keyed on a random 32-byte id (the cookie value) with a covering index on user_id for "sign out everywhere". Expiry is enforced both here (expires_at) and again in the middleware as defence in depth.

    -
    - show source -
    -- db/migrations/004_sessions.sql
    -create table sessions (
    -  id          text primary key,
    -  user_id     uuid not null references users(id),
    -  created_at  timestamptz default now(),
    -  expires_at  timestamptz not null,
    -  ip          inet,
    -  user_agent  text
    -);
    -create index sessions_user_id_idx on sessions(user_id);
    -
    -
    -
    -
    - - - -
    - - - - diff --git a/skills/html/references/html-effectiveness/05-design-system.html b/skills/html/references/html-effectiveness/05-design-system.html deleted file mode 100644 index da5460e..0000000 --- a/skills/html/references/html-effectiveness/05-design-system.html +++ /dev/null @@ -1,630 +0,0 @@ - - - - - - -Acme — Design System Reference - - - -
    - -
    -

    Acme design system

    -

    - Generated from src/styles/tokens.ts and src/components/ — use as a portable reference when prompting. -

    -
    - - -
    -

    Color

    -
    - -
    -
    Primary
    -
    -
    -
    - #D97757 - --clay -
    -
    -
    - #141413 - --slate -
    -
    -
    - #FAF9F5 - --ivory -
    -
    -
    - #E3DACC - --oat -
    -
    -
    - -
    -
    Neutral
    -
    -
    -
    - #FFFFFF - --white -
    -
    -
    - #F0EEE6 - --gray-100 -
    -
    -
    - #D1CFC5 - --gray-300 -
    -
    -
    - #87867F - --gray-500 -
    -
    -
    - #3D3D3A - --gray-700 -
    -
    -
    - -
    -
    Semantic
    -
    -
    -
    - #788C5D - --success -
    -
    -
    - #C78E3F - --warning -
    -
    -
    - #B04A4A - --danger -
    -
    -
    - #5C7CA3 - --info -
    -
    -
    -
    - - -
    -

    Typography

    -
    - -
    -
    -
    Plan the week ahead
    -
    - Display - 48 / 1.1 / 500 -
    -
    -
    -
    Plan the week ahead
    -
    - Heading 1 - 32 / 1.2 / 500 -
    -
    -
    -
    Plan the week ahead
    -
    - Heading 2 - 24 / 1.3 / 500 -
    -
    -
    -
    Review milestones, assign owners, and surface blockers before they cascade.
    -
    - Body - 16 / 1.55 / 430 -
    -
    -
    -
    Review milestones, assign owners, and surface blockers before they cascade.
    -
    - Small - 14 / 1.5 / 430 -
    -
    -
    -
    UPDATED 2 HOURS AGO
    -
    - Caption - 12 / 1.4 / 500 -
    -
    -
    -
    - - -
    -

    Spacing

    -
    - -
    -
    -
    -
    4--sp-1
    -
    -
    -
    -
    8--sp-2
    -
    -
    -
    -
    12--sp-3
    -
    -
    -
    -
    16--sp-4
    -
    -
    -
    -
    24--sp-5
    -
    -
    -
    -
    32--sp-6
    -
    -
    -
    -
    48--sp-7
    -
    -
    -
    -
    64--sp-8
    -
    -
    -
    - - -
    -

    Radius & Elevation

    -
    - -
    -
    -
    4px--r-xs
    -
    -
    -
    8px--r-sm
    -
    -
    -
    12px--r-md
    -
    -
    -
    20px--r-lg
    -
    -
    - -
    -
    -
    --shadow-sm0 1px 2px / 6%
    -
    -
    -
    --shadow-md0 4px 10px / 8%
    -
    -
    -
    --shadow-lg0 12px 28px / 12%
    -
    -
    -
    - - -
    -

    Core components

    -
    - -
    -
    <Button />
    -
    - - - - -
    -
    - -
    -
    <Input />
    -
    - - -
    -
    - -
    -
    <Checkbox />
    -
    - - -
    -
    - -
    -
    <Badge />
    -
    - Draft - In review - Done - Overdue -
    -
    -
    - -
    - - diff --git a/skills/html/references/html-effectiveness/06-component-variants.html b/skills/html/references/html-effectiveness/06-component-variants.html deleted file mode 100644 index 75debcf..0000000 --- a/skills/html/references/html-effectiveness/06-component-variants.html +++ /dev/null @@ -1,606 +0,0 @@ - - - - - - -Acme — Card Variant Matrix - - - -
    - -
    -

    Card variant matrix

    -

    Six structural treatments of the Acme <Card /> component. Adjust density and emphasis with the controls, hover a variant to see its prop combo.

    -
    - - -
    -
    - Padding - - 20px -
    - -
    - Border -
    - - - -
    -
    - -
    - -
    -
    - - -
    - - -
    - A · Flat -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: dense lists on tinted backgrounds

    -
    - - -
    - B · Outlined -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: default content cards on ivory

    -
    - - -
    - C · Elevated -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: draggable items, popovers

    -
    - - -
    - D · Accent stripe -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: pinned or priority items

    -
    - - -
    - E · Inset -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: nested cards inside white panels

    -
    - - -
    - F · Horizontal -
    -
    -
    WP
    -
    -

    Weekly planning

    -

    12 tasks · due Friday

    -
    -
    -
    - Q2 - Roadmap -
    - -
    -

    best for: compact row lists, sidebars

    -
    - -
    - - -
    -
    JSX — hover a variant above
    -
    // hover a card to preview its props
    -
    - -
    - - - - diff --git a/skills/html/references/html-effectiveness/07-prototype-animation.html b/skills/html/references/html-effectiveness/07-prototype-animation.html deleted file mode 100644 index b63929e..0000000 --- a/skills/html/references/html-effectiveness/07-prototype-animation.html +++ /dev/null @@ -1,456 +0,0 @@ - - - - - - -Acme — Task completed micro-interaction - - - -
    - -
    -
    Acme / prototype / micro-interaction
    -

    Task completed

    -

    - A single click should feel like a tiny win. Circle fills, check draws, - label strikes, a small burst, then the row quietly steps back. Click - the row to play; click again to reset. -

    -
    - -
    - -
    -
    -
    - -
    - Send weekly digest - Fri -
    -
    -
    -
    -
    -
    -
    -
    click to toggle
    -
    - - - -
    - -
    -

    Keyframes

    -
    -
    fill0ms
    -
    check80ms
    -
    strike120ms
    -
    confetti200ms
    -
    collapse600ms
    -
    -
    - -
    -

    Copy-paste CSS

    -
    /* circle: clay flash, settle to olive with spring overshoot */
    -.task.done .check {
    -  animation: settle 380ms cubic-bezier(.34,1.56,.64,1) forwards;
    -}
    -@keyframes settle {
    -  0%   { transform: scale(.8);  background: #D97757; }
    -  55%  { transform: scale(1.18); }
    -  100% { transform: scale(1);   background: #788C5D; }
    -}
    -
    -/* checkmark draws via stroke-dashoffset, 80ms delay */
    -.check path        { stroke-dasharray: 20; stroke-dashoffset: 20;
    -                     transition: stroke-dashoffset 220ms var(--ease) 80ms; }
    -.task.done path    { stroke-dashoffset: 0; }
    -
    -/* strikethrough grows left → right */
    -.label::after      { width: 0; transition: width 240ms var(--ease) 120ms; }
    -.task.done .label::after { width: 100%; }
    -
    -/* row steps back after the celebration */
    -.task.done         { max-height: 44px; opacity: .6;
    -                     transition-delay: 600ms; }
    -
    - -
    - - - - diff --git a/skills/html/references/html-effectiveness/08-prototype-interaction.html b/skills/html/references/html-effectiveness/08-prototype-interaction.html deleted file mode 100644 index fb8fde0..0000000 --- a/skills/html/references/html-effectiveness/08-prototype-interaction.html +++ /dev/null @@ -1,397 +0,0 @@ - - - - - - -Acme — Sidebar drag-to-reorder - - - -
    - -
    -
    Acme / prototype / interaction
    -

    Sidebar drag-to-reorder

    -

    - Throwaway HTML so we can feel the reorder before porting it to - React. Native dragstart / dragover / drop, - ~40 lines of JS, no libraries. Grab a row by the dots and move it. -

    -
    - -
    - -
    - -

    Order persists in the DOM only — refresh to reset.

    -
    - -
    -
    -

    What you're feeling

    -

    Design decisions baked into this prototype, so you can push back on them.

    -
      -
    • - Drop indicator snaps to the nearest gap, not the raw cursor Y. - It only moves when you cross a row's midpoint — feels more decisive, - less jittery. -
    • -
    • - Dragged row stays in place at 35% opacity with a 2° tilt. - Keeping the ghost in the list preserves your sense of where you - started; the tilt reads as "lifted." -
    • -
    • - Grip dots are the affordance, but the whole row is draggable. - Dots darken on hover to teach the gesture without forcing a - tiny hit target. -
    • -
    • - No auto-scroll, no drop animation. Left out on purpose so the - core feel is easy to judge — say the word and we add them next. -
    • -
    -
    - -
    -

    Open questions

    -
      -
    1. Should Trash (and maybe Archive) be pinned to the bottom and excluded from reordering?
    2. -
    3. Do we want rows to slide to their new slot on drop, or is the instant snap acceptable?
    4. -
    5. Keyboard path: is Alt + Arrow to move the focused row enough for the first ship?
    6. -
    -
    -
    - -
    -
    - - - - diff --git a/skills/html/references/html-effectiveness/09-slide-deck.html b/skills/html/references/html-effectiveness/09-slide-deck.html deleted file mode 100644 index 61fd981..0000000 --- a/skills/html/references/html-effectiveness/09-slide-deck.html +++ /dev/null @@ -1,593 +0,0 @@ - - - - - - -Platform Eng — Week of Mar 10 - - - - - -
    -
    - -

    Platform Eng
    — Week of Mar 10

    -

    - What shipped, what's moving, and one decision we need from the - room before the Acme 2.4 cut. -

    - -
    -
    - - -
    -
    -
    Shipped this week
    -

    Three things out the door

    -
      -
    • - -
      -
      Bulk task import
      -
      - CSV and JSON uploads now land straight into a board with - column mapping — no more paste-and-pray. -
      -
      - #4211 -
    • -
    • - -
      -
      Webhook retries v2
      -
      - Exponential backoff with jitter; dead-letter queue surfaces - in the workspace admin panel. -
      -
      - #4188 #4203 -
    • -
    • - -
      -
      Postgres 16 migration
      -
      - All read replicas cut over Tuesday night; zero customer-facing - downtime, ~9% faster aggregate queries. -
      -
      - #4179 -
    • -
    -
    -
    - - -
    -
    -
    In progress
    -

    Carrying into next week

    -
      -
    • -
      - Recurring tasks engine - ~70% -
      -
      -

      - Scheduler and RRULE parsing are done; remaining work is the - timezone edge cases and the "skip holidays" toggle. -

      -
    • -
    • -
      - Audit log export - ~35% -
      -
      -

      - Streaming NDJSON endpoint is up behind a flag; still wiring - the S3 destination picker and retention policy UI. -

      -
    • -
    -
    -
    - - -
    -
    -
    Metrics
    -

    Numbers we watch

    - -
    -
    -
    API p95 latency
    -
    184ms
    -
    ↓ 12% wk/wk
    -
    -
    -
    Background job error rate
    -
    0.21%
    -
    ↓ 0.08pp
    -
    -
    - -
    - -
    - p95 latency, trailing 8 days — lower is better -
    -
    -
    -
    - - -
    -
    -
    Decision needed
    -

    One call to make

    - -
    -

    - Do we ship recurring tasks behind a workspace flag in 2.4, or - hold one more week for the timezone fixes? -

    -

    - Flagged rollout gets it to design partners Friday but means two - code paths for ~2 weeks. Holding keeps a single path but slips - the partner promise. -

    -
    - -
    - A — Flag it, ship Friday - B — Hold for 2.5 -
    -
    -
    - - -
    -
    -
    Next week
    -

    On deck

    -
      -
    • Finish recurring tasks — timezone matrix tests, then dogfood on the internal ops board.
    • -
    • Audit log export to private beta — three workspaces lined up.
    • -
    • Start scoping rate-limit headers for the public API; RFC draft by Thursday.
    • -
    -
    - Questions → drop them in the platform channel or grab anyone after standup. -
    -
    -
    - - -
    1 / 6
    - - - - diff --git a/skills/html/references/html-effectiveness/10-svg-illustrations.html b/skills/html/references/html-effectiveness/10-svg-illustrations.html deleted file mode 100644 index c408408..0000000 --- a/skills/html/references/html-effectiveness/10-svg-illustrations.html +++ /dev/null @@ -1,493 +0,0 @@ - - - - - - -Background jobs — header illustrations - - - -
    - -
    -

    Background jobs — header illustrations

    -

    - Three 720×320 hand-drawn SVGs for the Acme docs section on - background jobs. Flat fills, 1.5–2px strokes, palette-locked. Each - exports standalone via the button below it. -

    -
    720 × 320 · inline SVG · no external assets
    -
    - - -
    -
    - - - - - - - - - - - - queue - - - - - job 5 - - - job 4 - - - job 3 - - - job 2 - - - - job 1 - - - - - - - - worker - pool=4 - - - next to run - Jobs are pulled FIFO; the worker leases one at a time. - -
    -
    -
    -
    Queue
    -
    For "How jobs are picked up" — intro page header.
    -
    - -
    -
    - - -
    -
    - - - - - - - - - - t = 0 - time → - - - - - - - try 1 - - - - - - try 2 - - - - - - try 3 - - - - - try 4 - - - - +1s - - - +2s - - - +4s - - - Each failure waits twice as long before re-queuing; jitter not pictured. - -
    -
    -
    -
    Retry with backoff
    -
    For "Handling failures" — retry policy header.
    -
    - -
    -
    - - -
    -
    - - - - - - - - - - - - - enqueue - batch() - - - - - - - - - - - shard 0 - - - shard 1 - - - shard 2 - - - shard 3 - - - - - - - - - - - merge - await all - - - fan-out - fan-in - Parent job spawns N children, then blocks on a completion barrier. - -
    -
    -
    -
    Fan-out / fan-in
    -
    For "Batch and parallel work" — fan-out pattern header.
    -
    - -
    -
    - - -
    -

    Palette & rules

    - -
    -
    -
    -
    -
    ivory
    -
    #FAF9F5
    -
    -
    -
    -
    -
    -
    slate
    -
    #141413
    -
    -
    -
    -
    -
    -
    clay
    -
    #D97757
    -
    -
    -
    -
    -
    -
    olive
    -
    #788C5D
    -
    -
    -
    -
    -
    -
    oat
    -
    #E3DACC
    -
    -
    -
    -
    -
    -
    gray-150
    -
    #F0EEE6
    -
    -
    -
    -
    -
    -
    gray-300
    -
    #D1CFC5
    -
    -
    -
    -
    -
    -
    gray-500
    -
    #87867F
    -
    -
    -
    - -
      -
    • Strokes are 1.5px for neutral boxes, 2px for emphasised containers.
    • -
    • All rectangles use rx="10"; no drop shadows or gradients.
    • -
    • Labels inside boxes are 11px mono; annotations outside are 12px sans, gray-500.
    • -
    • Clay marks "the thing in focus"; olive marks "success / done".
    • -
    • Each SVG carries its own <style> block so the download stands alone.
    • -
    -
    - -
    - - - - diff --git a/skills/html/references/html-effectiveness/11-status-report.html b/skills/html/references/html-effectiveness/11-status-report.html deleted file mode 100644 index 7f5ed34..0000000 --- a/skills/html/references/html-effectiveness/11-status-report.html +++ /dev/null @@ -1,529 +0,0 @@ - - - - - - -Acme — Engineering Status — Week 11 - - - -
    - -
    -
    -

    Engineering Status — Week 11

    - auto-generated -
    -
    - Mar 10 – Mar 16, 2025  ·  - acme/app @ main -
    -
    - - -
    -
    -
    -
    14
    -
    PRs merged
    -
    +3 vs wk10
    -
    -
    -
    6
    -
    Deploys
    -
    ±0
    -
    -
    -
    1
    -
    Incidents
    -
    SEV-2 · 47m
    -
    -
    -
    3
    -
    Flaky tests fixed
    -
    suite now 99.1%
    -
    -
    -
    - - -
    -

    Highlights

    -
    -
      -
    • - Bulk task editing shipped to 100%. The multi-select - toolbar landed behind a flag on Monday and ramped to all workspaces by - Thursday with no error-rate regression. -
    • -
    • - Sync API p95 down 38%. Replacing per-task auth checks - with a scoped batch lookup cut the hot path from 410ms to 255ms on the - staging load test. -
    • -
    • - One SEV-2 on Wednesday — a config rollout pushed - a bad connection-pool limit to the sync workers. Mitigated in 47 minutes; - full postmortem linked below. -
    • -
    -
    - - -
    -

    Shipped

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PRTitleAuthorRisk
    #4871Bulk edit toolbar: selection model + keyboard shortcutsMira OkaforMed
    #4874Batch auth lookup for /v2/sync hot pathDevon ParkMed
    #4878Fix race in attachment uploader retry loopSam ReyesLow
    #4879Migrate reminder scheduler to idempotent job keysPriya AnandHigh
    #4882Board view: collapse empty swimlanes by defaultMira OkaforLow
    #4885Quarantine 3 flaky webhook integration testsJules TanLow
    #4888Connection pool limits configurable per worker tierDevon ParkMed
    #4891Dark mode pass on settings & billing panelsNoor HalabiLow
    -
    - - -
    -

    Velocity

    -
    -
    - - - - - - - - - 0 - 1 - 2 - 3 - - - - - - - - - - - - - - - - - - - 2 - 3 - 1 - 4 - 2 - 1 - 1 - - - Mon - Tue - Wed - Thu - Fri - Sat - Sun - -
    - PRs merged per day. Thursday spike is the bulk-edit feature train (4 PRs landed together). -
    -
    -
    - - -
    -

    Carryover

    -
    -
    -
    - In review -
    - Workspace export to CSV — waiting on pagination review. - · Sam Reyes -
    -
    -
    - Blocked -
    - SSO group mapping — blocked on staging IdP credentials from IT. - · Priya Anand -
    -
    -
    - Slipped -
    - Mobile push reliability dashboard — deprioritized for incident follow-up. - · Devon Park -
    -
    -
    -
    - -
    - Sources: git log main..HEAD · CI dashboard · deploy log -  —  generated Mar 16 2025 18:02 -
    - -
    - - diff --git a/skills/html/references/html-effectiveness/12-incident-report.html b/skills/html/references/html-effectiveness/12-incident-report.html deleted file mode 100644 index ff06f1d..0000000 --- a/skills/html/references/html-effectiveness/12-incident-report.html +++ /dev/null @@ -1,597 +0,0 @@ - - - - - - -INC-2025-0412 — Elevated 502s on task sync - - - - - - -
    - -
    -
    INC-2025-0412
    -

    Elevated 502s on task sync

    -
    - SEV-2 - Resolved - Duration 47 min - Detected Apr 12 · 14:07 - Owner Devon Park -
    -
    - -
    -
    TL;DR
    -

    - A config rollout lowered the database connection-pool limit on the - sync-worker tier from 64 to 8, exhausting connections under - normal afternoon load. The sync API returned 502s for roughly 21% of - requests over 47 minutes. We mitigated by reverting the config and - cycling the worker fleet; no data was lost. -

    -
    - - -
    -

    Timeline

    -
    -
    - -
    - - 14:02 -
    - Config change cfg-9a12 promoted to - production via the standard rollout pipeline. -
    -
    - -
    - - 14:06 -
    - Impact starts. Sync workers begin queueing on pool - checkout; p95 latency climbs past 4s and the load balancer starts - returning 502s. -
    -
    - -
    - - 14:07 -
    - Alert fires: sync_5xx_rate > 2% for 60s. - On-call (Devon) acknowledges. -
    -
    - -
    - - 14:18 -
    - Initial hypothesis is a bad deploy of the API service; last two - application deploys are rolled back with no effect. -
    -
    - -
    - - 14:31 -
    - Mira joins and notices pool-wait saturation in the worker dashboard. - Investigation pivots to infra config rather than app code. -
    -
    - -
    - - 14:44 -
    - Mitigated. cfg-9a12 - reverted; worker fleet cycled. 5xx rate drops below 0.2% within - three minutes. -
    -
    - -
    - - 14:49 -
    - Monitors green for 5 minutes. Incident declared resolved; status - page updated. -
    -
    - -
    -
    - - -
    -

    Root cause

    -
    -

    - PR #4888 made connection-pool limits - configurable per worker tier. The default for the new - sync-worker key was meant to inherit the - global value (64) but was hard-coded to 8 during a local test and - committed. The config linter only validates type, not magnitude, so the - change passed CI. -

    -

    - Because config rollouts and code deploys go through separate pipelines, - the on-call's first instinct — rolling back the most recent - application deploys — had no effect and cost roughly 13 minutes of - diagnosis time. -

    - -
    - infra/config/workers.yaml -
    pool:
    -
    global_max_connections: 64
    -
    tiers:
    -
    - sync-worker: { max_connections: 64 }
    -
    + sync-worker: { max_connections: 8 } # debug value, do not ship
    -
    webhook-worker: { max_connections: 32 }
    -
    -
    - - -
    -

    Impact

    -
    - - - - - - - - - - - - - - - - - - - - - -
    Requests failed (502)~41,200
    Peak error rate21.4%
    Users affected~2,300 workspaces
    Data lossNone — clients retried
    SLA breachNo (within monthly budget)
    -
    - - -
    -

    Action items

    -
    -
    - -
    - - DP - Revert cfg-9a12 and restore pool limit to 64 - Apr 12 -
    - -
    - - MO - Add config-linter range check for max_connections (warn < 32) - Apr 18 -
    - -
    - - SR - Surface “recent config rollouts” alongside deploys in the on-call dashboard - Apr 25 -
    - -
    - - PA - Canary config changes to one worker AZ for 10 min before fleet-wide promote - May 02 -
    - -
    -
    - -
    - Authored from on-call notes + alert history · reviewed by Devon Park, Mira Okafor -
    - -
    - - diff --git a/skills/html/references/html-effectiveness/13-flowchart-diagram.html b/skills/html/references/html-effectiveness/13-flowchart-diagram.html deleted file mode 100644 index 8967f6e..0000000 --- a/skills/html/references/html-effectiveness/13-flowchart-diagram.html +++ /dev/null @@ -1,396 +0,0 @@ - - - - - - -Deploy pipeline — annotated flowchart - - - -
    - -
    -
    Illustrations & Diagrams · Flowchart
    -

    What happens when you git push

    -

    - The deploy pipeline for acme/web, drawn from .github/workflows/ and the - Argo manifests. Click any step to see what runs, how long it usually takes, and where it can short-circuit. -

    -
    - -
    - -
    -
    - - - - - - - - - - - - - - - - - - - pass - - fail → status - - - - healthy - - canary fails - - - - - - - git push main - - - - - CI · lint + typecheck - ~2 min · ci.yml - - - - - Unit + integration tests - ~6 min · 3 shards - - - - - pass? - - - - - Post failure status - slack #deploys - - - - - Build + push image - ghcr.io/acme/web - - - - - Argo canary 5% - 10 min soak - - - - - SLO ok? - - - - - Promote 25 → 50 → 100% - ~8 min - - - - - Auto-rollback - revert image tag - - - - - Smoke tests in prod - playwright · 90s - - - - - ✅ Deploy complete - - -
    - -
    - process step - decision - terminal success - failure path -
    -
    - - - -
    -
    - - - - diff --git a/skills/html/references/html-effectiveness/14-research-feature-explainer.html b/skills/html/references/html-effectiveness/14-research-feature-explainer.html deleted file mode 100644 index aea9deb..0000000 --- a/skills/html/references/html-effectiveness/14-research-feature-explainer.html +++ /dev/null @@ -1,382 +0,0 @@ - - - - - - -How rate limiting works in acme/api - - - -
    - - - - - -
    -
    -
    Research & Learning · feature summary
    -

    How rate limiting works in acme/api

    -
    - TL;DR — Every request passes through rateLimit() middleware, which resolves the - caller to a bucket key, fetches a token-bucket from Redis, and either consumes one token or - returns 429. Limits are declared per-route in config/limits.yaml; routes - without an entry inherit the default tier (100 req/min per API key). -
    -
    - -

    The request path, step by step

    -

    Expand each step to see what runs and where it lives. The whole path is ~40 lines and adds about - 0.4 ms p50 to every request.

    - -
    - 1 · Identify the caller middleware/ratelimit.ts:21 -
    -

    The middleware first reduces the request to a bucketKey: API key if an - Authorization header is present, otherwise the client IP (via the - x-forwarded-for chain, trusting only our own LB). Anonymous IP traffic gets a much - lower default tier.

    -
    -
    - -
    - 2 · Look up the bucket lib/tokenBucket.ts:9 -
    -

    The route name plus bucket key map to a Redis hash (rl:{route}:{key}) holding - tokens and updatedAt. If the key is missing it's created lazily at full - capacity — there's no warm-up.

    -
    -
    - -
    - 3 · Refill and consume lib/tokenBucket.ts:31 -
    -

    Refill is computed from elapsed time (rate × Δt, capped at burst), then - one token is subtracted. The whole read-modify-write runs as a single Lua script so concurrent - requests can't double-spend.

    -
    -
    - -
    - 4 · Reject when empty middleware/ratelimit.ts:48 -
    -

    If the script returns tokens < 0 the middleware short-circuits with - 429 Too Many Requests and sets Retry-After to the seconds until one token - refills. Successful responses always carry X-RateLimit-Remaining.

    -
    -
    - -

    Configuring a limit on your route

    -

    You don't touch the middleware. Add an entry to config/limits.yaml keyed by route name, - and (optionally) tag the route so the middleware can find it.

    - -
    -
    - - - -
    -
    # config/limits.yaml
    -default:
    -  rate: 100/min
    -  burst: 120
    -
    -search.query:
    -  rate: 20/min
    -  burst: 40
    -  key: api_key        # or: ip
    -
    // routes/search.ts
    -router.post(
    -  "/search",
    -  rateLimit("search.query"),
    -  handler,
    -);
    -
    HTTP/1.1 429 Too Many Requests
    -Retry-After: 17
    -X-RateLimit-Limit: 20
    -X-RateLimit-Remaining: 0
    -
    -{ "error": "rate_limited", "retry_after": 17 }
    -
    - -
    - -
    If you only need the default tier, you don't need a YAML entry at all — just wrap the handler in - rateLimit() with no argument. The route name is inferred from the path.
    -
    - -

    Gotchas worth knowing

    -
      -
    • Limits are per-process in dev. The Redis client falls back to an - in-memory map when REDIS_URL is unset, so local testing won't reflect real cluster - behaviour.
    • -
    • Burst ≠ rate. burst is the bucket capacity; a caller - idle for a minute can fire burst requests instantly even if rate is low.
    • -
    • Streaming responses count once. The token is consumed at request start; a 30-second SSE - stream still costs one token.
    • -
    - -

    FAQ

    -
    -
    How do I exempt internal traffic?
    -
    Set x-acme-internal: 1 from the caller; the middleware checks it against the - mTLS peer name and skips the bucket entirely.
    - -
    Where do I see who's getting limited?
    -
    Every 429 emits a ratelimit.rejected metric tagged with route and key - type. There's a Grafana panel under API → Health.
    - -
    Can a single user have a higher limit?
    -
    Yes — add their API key under overrides: in the YAML. Overrides are reloaded without - a deploy.
    -
    -
    - -
    - - - - diff --git a/skills/html/references/html-effectiveness/15-research-concept-explainer.html b/skills/html/references/html-effectiveness/15-research-concept-explainer.html deleted file mode 100644 index 192869d..0000000 --- a/skills/html/references/html-effectiveness/15-research-concept-explainer.html +++ /dev/null @@ -1,369 +0,0 @@ - - - - - - -Consistent hashing — an interactive explainer - - - -
    - -
    -
    Research & Learning · concept explainer
    -

    Consistent hashing, in one ring

    -

    - You have K keys spread across N cache servers. A server dies, or you add one. How many - keys have to move? With naive hash(key) mod N the answer is "almost all of them." Consistent - hashing gets it down to roughly K / N. Here's why. -

    - -

    The trick: hash onto a circle, not a line

    -

    - Map both nodes and keys onto the same - ring (the hash output space, wrapped around). A key belongs to - the first node found by walking clockwise from the key's position. When a node leaves, only the keys in - its arc reassign — to the next node round — and everything else - stays put. -

    - -
    -
    - -
    -
    - - - 4 -
    -
    - - - 32 -
    -
    - - - -
    -
    - 4 nodes · 32 keys · moved on last change -
    -
    -
    -
    -

    - Colored arcs show ownership. Removing a node hands its arc to its clockwise neighbor; every dot outside - that arc keeps its color. That's the whole idea. -

    - -

    Versus mod N

    - - - - - - - - -
    hash mod Nconsistent hashing
    Keys moved when N→N+1~ (N−1)/N of all keys~ 1/(N+1)
    Hot-spot riskeven by constructionuneven — fix with virtual nodes
    Lookup costO(1)O(log N) (binary search on ring)
    Used byarray sharding, simple LBDynamo, Cassandra, Memcached clients, Envoy
    - -

    Where you'll meet it

    -

    - Any time you're spreading state across a pool that changes size: cache fleets, partitioned queues, object - storage, request routing with sticky sessions. The - virtual-node variant (each physical node owns many small arcs - instead of one big one) is what production systems actually run, because it smooths out load and makes - rebalancing even gentler. -

    -
    - - - - -
    - - - - diff --git a/skills/html/references/html-effectiveness/16-implementation-plan.html b/skills/html/references/html-effectiveness/16-implementation-plan.html deleted file mode 100644 index 483a826..0000000 --- a/skills/html/references/html-effectiveness/16-implementation-plan.html +++ /dev/null @@ -1,703 +0,0 @@ - - - - - - - Implementation plan — Comment threads on task cards - - - -
    - -
    -
    Implementation plan · Acme web client
    -

    Comment threads on task cards

    -
    - Prompt - Create a thorough implementation plan for adding threaded comments to - task cards. Include mockups, the data flow from client to persistence, - the key code I'll need to write, and a risk table. Make it easy to - skim on a phone — I'm going to pass this to the implementer as-is. -
    -
    - - - -
    -
    Effort
    ~2 weeks
    -
    Surfaces touched
    3 packages
    -
    New tables
    2
    -
    Feature flag
    task_comments_v1
    -
    - - - -
    -
    01

    Milestones

    -

    Ship in four slices, each independently reviewable and each behind the flag. Nothing is user-visible until slice 4.

    - -
    -
    -
    Week 1 · Mon–Tue
    -
    -
    -

    Schema & API contract

    -

    New comments and comment_reads tables, migrations, and the tRPC router stubs. No UI. Contract reviewed before anything else lands.

    -
    packages/dbpackages/apimigration 0042
    -
    -
    - -
    -
    Week 1 · Wed–Fri
    -
    -
    -

    Thread component & composer

    -

    Static <CommentThread> rendered from fixtures. Optimistic insert on submit, rollback on failure, one level of nesting only.

    -
    apps/webstorybook
    -
    -
    - -
    -
    Week 2 · Mon–Wed
    -
    -
    -

    Realtime fan-out & unread state

    -

    Subscribe the open card to its comment channel. Track per-user read cursors so the sidebar can show an unread count without a second query.

    -
    packages/realtimeapps/web
    -
    -
    - -
    -
    Week 2 · Thu–Fri
    -
    -
    -

    Notifications, flag ramp, docs

    -

    Mention detection → notification row, email digest fallback, ramp task_comments_v1 to internal, then 10% → 100% over three days.

    -
    packages/notifygrowthbook
    -
    -
    -
    -
    - - - -
    -
    02

    Data flow

    -

    Optimistic write path on the left, fan-out on the right. The read cursor update is fire-and-forget — we never block the thread render on it.

    - -
    - - - - - - - - - - - - - - <CommentComposer> - apps/web - - - React Query cache - optimistic insert - - - comments.create - tRPC · packages/api - - - comments table - postgres · packages/db - - - realtime channel - task:{id}:comments - - - Other viewers - subscribed cards - - - notify worker - @mentions → queue - - - - - - - - - - - - - - - - - - submit (id=temp) - mutate - INSERT + read cursor - enqueue - broadcast row - live append - reconcile temp id → real id - - -

    Solid = request/response path. Dashed clay = realtime fan-out. The composer never waits on the dashed path.

    -
    -
    - - - -
    -
    03

    Mockups

    -

    Not pixel-final — just enough that the reviewer and I agree on nesting depth, composer placement, and what the sidebar digest looks like.

    - -
    -
    -
    A · Thread inside an open task card
    -
    -
    -
    Ship onboarding empty-state rewrite
    -
    BIR-1142 · Assigned to Priya · Due Fri
    -
    -
    -
    -
    JM
    -
    -
    Jonah M. 2h ago
    -
    Should the illustration swap when the workspace already has one project? Feels odd to show the "start here" art twice.
    - -
    -
    -
    -
    PS
    -
    -
    Priya S. 40m ago
    -
    Good catch — I'll gate it on projects.count > 0 and fall back to the minimal variant.
    -
    -
    -
    -
    Add a comment…
    -
    Post
    -
    -
    -
    -
    -
    - -
    -
    B · Sidebar unread digest
    -
    -
    -
    -
    JM
    -
    Jonah commented on BIR-1142 — "Should the illustration swap when…"
    -
    -
    -
    AK
    -
    Aiko mentioned you on BIR-1098 — "@priya can you confirm the copy here?"
    -
    -
    -
    RW
    -
    Rowan replied on BIR-0971 — "Merged, thanks for the quick turnaround."
    -
    -
    -
    -
    -
    -
    - - - -
    -
    04

    Key code

    -

    The two pieces most likely to be done wrong: the migration (soft deletes, read cursors) and the optimistic mutation (temp-id reconciliation).

    - -
    -
    -
    packages/db/migrations/0042_comments.sql
    -
    create table comments (
    -  id          uuid primary key default gen_random_uuid(),
    -  task_id     uuid not null references tasks(id),
    -  parent_id   uuid references comments(id),   -- one level only,
    -                                                -- enforced in API
    -  author_id   uuid not null references users(id),
    -  body        text not null,
    -  created_at  timestamptz not null default now(),
    -  deleted_at  timestamptz                       -- soft delete
    -);
    -
    -create table comment_reads (
    -  task_id    uuid not null references tasks(id),
    -  user_id    uuid not null references users(id),
    -  read_up_to timestamptz not null,
    -  primary key (task_id, user_id)
    -);
    -
    -create index comments_task_created
    -  on comments (task_id, created_at);
    -
    - -
    -
    apps/web/hooks/useAddComment.ts
    -
    export function useAddComment(taskId: string) {
    -  const qc = useQueryClient();
    -  return trpc.comments.create.useMutation({
    -    onMutate: async (input) => {
    -      const temp = { ...input, id: `temp-${nanoid()}`,
    -                     createdAt: new Date(), pending: true };
    -      qc.setQueryData(key(taskId), (prev) =>
    -        [...(prev ?? []), temp]);
    -      return { tempId: temp.id };
    -    },
    -    onSuccess: (row, _v, ctx) => {
    -      // reconcile temp id → real id so the
    -      // realtime append doesn't duplicate it
    -      qc.setQueryData(key(taskId), (prev) =>
    -        prev.map((c) => c.id === ctx.tempId ? row : c));
    -    },
    -    onError: (_e, _v, ctx) => {
    -      qc.setQueryData(key(taskId), (prev) =>
    -        prev.filter((c) => c.id !== ctx.tempId));
    -    },
    -  });
    -}
    -
    -
    -
    - - - -
    -
    05

    Risks & mitigations

    -
    -
    -
    Risk
    -
    Sev
    -
    Mitigation
    -
    -
    -
    Realtime duplicate: socket append races with the HTTP response and the temp-id reconcile.
    -
    HIGH
    -
    Dedupe on server-assigned id in the cache updater; socket payload carries the real id, temp rows are filtered on reconcile.
    -
    -
    -
    Unread counts go stale when a user reads the thread on another device.
    -
    MED
    -
    Broadcast comment_reads upserts on the same channel; client treats its own cursor as max(local, remote).
    -
    -
    -
    Mention detection false-positives on pasted markdown (@media, @2x).
    -
    LOW
    -
    Resolve mentions against workspace members only, at write time, and store the resolved user ids — never re-parse on read.
    -
    -
    -
    - - - -
    -
    06

    Open questions

    -
    -
    -
    Do we allow editing, or only delete-and-repost?
    -
    Editing needs an edited_at column and an "edited" affordance. Delete-and-repost is simpler but loses the reply anchor. Leaning toward delete-only for v1.
    -
    Decide with · design, before slice 2
    -
    -
    -
    Email digest cadence when a user has the app closed
    -
    Immediate-per-mention will be noisy. Proposal: batch on a 15-minute window, collapse to one email per task, and respect quiet hours from the existing settings table.
    -
    Decide with · platform, before slice 4
    -
    -
    -
    - -
    - - diff --git a/skills/html/references/html-effectiveness/17-pr-writeup.html b/skills/html/references/html-effectiveness/17-pr-writeup.html deleted file mode 100644 index 34c60d0..0000000 --- a/skills/html/references/html-effectiveness/17-pr-writeup.html +++ /dev/null @@ -1,596 +0,0 @@ - - - - - - - PR #312 — Move notification delivery onto a queue - - - -
    - -
    -
    Pull request · Acme
    -

    #312 — Move notification delivery onto a queue

    -
    - 9 files - +418 / −190 - branch notify-queuemain - author @priya -
    -
    - Prompt - Write up PR #312 for my reviewers. Explain the motivation, walk them - through the change file by file with the why for each, show - before/after behavior, and tell them exactly where to focus. They - haven't touched the notification code in six months. -
    -
    - -
    -
    - -
    -
    TL;DR
    -

    Notification sends were happening inline in the request path. Under load they added 200–800 ms to mutation latency and silently dropped emails when the SMTP pool was exhausted. This PR moves delivery onto the existing pg-boss queue so the API returns immediately and failed sends retry with backoff.

    -
    - - - -
    -

    Why

    -

    When we added @mentions in comments last quarter, every mention started triggering up to three sends (in-app, email, Slack) inside the same transaction that saved the comment. That was fine at launch. It is not fine now that a single task update can fan out to forty watchers.

    - -
    -
    -
    Before
    -
      -
    • Sends run inline in the mutation handler
    • -
    • SMTP timeout = 500 error for the comment
    • -
    • No retries — a dropped email is gone
    • -
    • p99 on comments.create: 1.4 s
    • -
    -
    -
    -
    After
    -
      -
    • Handler enqueues one job per recipient, returns
    • -
    • Worker retries 3× with exponential backoff
    • -
    • Dead-letter table for inspection after exhaustion
    • -
    • p99 on comments.create: 180 ms (staging)
    • -
    -
    -
    -
    - - - -
    -

    File-by-file

    -

    Ordered for reading, not alphabetically. Start at the worker — it's the new thing — then the enqueue call site, then the plumbing.

    - -
    - -
    - - - packages/notify/src/worker.ts - new - +126 - -
    -

    The heart of the PR. A pg-boss subscriber that pulls notify.deliver jobs, resolves the user's channel preferences, and calls the right adapter. Retries are configured per-channel — email gets three attempts, Slack gets one because its API is already idempotent on our side.

    -
    boss.work('notify.deliver', { batchSize: 20 }, async (jobs) => {
    -  for (const job of jobs) {
    -    const { userId, event, channel } = job.data;
    -    const prefs = await getPrefs(userId);
    -    if (!prefs[channel]) return;          // user muted this channel
    -
    -    try {
    -      await adapters[channel].send(userId, event);
    -    } catch (err) {
    -      if (job.retryCount >= MAX_RETRY[channel]) {
    -        await deadLetter(job, err);         // don't throw — ack & park
    -        return;
    -      }
    -      throw err;                            // pg-boss reschedules
    -    }
    -  }
    -});
    -
    -
    - -
    - - - packages/api/src/routers/comments.ts - mod - +14 −62 - -
    -

    Where the win shows up. The mutation used to call sendEmail, sendSlack, and createInApp directly. Now it inserts the comment, computes recipients, and enqueues. The try/catch soup is gone.

    -
      const comment = await db.comments.insert(input);
    -  const recipients = await resolveWatchers(input.taskId, input.mentions);
    -
    -  for (const r of recipients) {
    -    await sendEmail(r, comment);       // blocked the response
    -    await sendSlack(r, comment);
    -  }
    -  await boss.insert(recipients.flatMap((r) =>
    -    CHANNELS.map((ch) => ({
    -      name: 'notify.deliver',
    -      data: { userId: r.id, channel: ch, event: toEvent(comment) },
    -      singletonKey: `${comment.id}:${r.id}:${ch}`,  // idempotent
    -    }))));
    -  return comment;
    -
    -
    - -
    - - - packages/db/migrations/0051_dead_letter.sql - new - +22 - -
    -

    Table for jobs that exhaust their retries. Deliberately not auto-pruned — we want to look at these weekly until we trust the new path. Has the full job payload and the last error string.

    -
    -
    - -
    - - - packages/notify/src/adapters/{email,slack,inapp}.ts - mod - +88 −74 - -
    -

    Mostly moves. Each adapter now implements a shared Adapter interface and throws a typed RetryableError or PermanentError so the worker knows whether to retry. The email adapter also drops its internal retry loop — the queue owns retries now, double-retrying was how we got duplicate emails in April.

    -
    -
    - -
    - - - apps/worker/src/index.ts, infra/fly.toml - mod - +31 −4 - -
    -

    Registers the new subscriber in the existing worker process and bumps its concurrency from 5 → 20. No new deploy unit.

    -
    -
    - -
    - - - packages/notify/src/__tests__/worker.test.ts - new - +137 - -
    -

    Covers the retry boundary, the dead-letter path, channel muting, and the singleton key dedupe. Uses a real pg-boss against the test database — we got burned last quarter when mocked queue tests passed but prod ordering broke.

    -
    -
    - -
    -
    - - - -
    -

    Where to focus your review

    -
    -
    -
    1
    -
    -
    The retry / dead-letter boundary
    -
    worker.ts:31–44. I catch, check retryCount, and either park or rethrow. If this logic is wrong we either retry forever or drop messages — the two failure modes this PR exists to fix.
    -
    -
    -
    -
    2
    -
    -
    The singleton key
    -
    comments.ts:28. ${commentId}:${userId}:${channel} should make re-enqueues idempotent if the API handler retries. Sanity-check that this can't collide across tasks.
    -
    -
    -
    -
    3
    -
    -
    What I deliberately did not do
    -
    No per-user digest batching, no delivery receipts, no priority lanes. All of those layer on top of this cleanly; bundling them would make this unreviewable.
    -
    -
    -
    -
    - - - -
    -

    Test plan

    -
    -
    Unit: retry → dead-letter path, channel mute, singleton dedupe
    packages/notify — 14 cases, real pg-boss on test db
    -
    Integration: create comment with 3 watchers, assert 9 jobs enqueued and drained
    -
    Staging load: 500 rps on comments.create for 10 min, p99 = 180 ms
    was 1.4 s before — dashboard linked in the PR description
    -
    Manual: kill SMTP mid-burst, confirm jobs land in dead-letter and nothing 500s
    will do during the 10% ramp
    -
    -
    - - - -
    -

    Rollout

    -

    Behind notify_queue_v2. The old inline path stays in the codebase, dead but dormant, for one release in case we need to flip back.

    -
    -
    Day 0
    internal
    Acme team only. Watch dead-letter table + worker error rate.
    -
    Day 2
    10%
    Random sample. Alert if dead-letter rate > 0.5% of sends.
    -
    Day 4
    100%
    Ramp fully, delete the inline path in a follow-up PR next week.
    -
    -
    - -
    - - -
    - -
    - - diff --git a/skills/html/references/html-effectiveness/18-editor-triage-board.html b/skills/html/references/html-effectiveness/18-editor-triage-board.html deleted file mode 100644 index ae4dbb0..0000000 --- a/skills/html/references/html-effectiveness/18-editor-triage-board.html +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - -Acme — Cycle 14 triage - - - -
    - -
    -
    Acme / editor / triage
    -

    Cycle 14 triage

    -

    - Twenty-four open Linear tickets, pre-sorted into a best guess. Drag them - across Now / Next / Later / Cut until the cut feels right, then copy the - result back into the planning doc as markdown. -

    -
    drag tickets between columns  ·  click a tag to filter
    -
    - -
    -
    -
    - - - -
    - -
    - -
    - - - - diff --git a/skills/html/references/html-effectiveness/19-editor-feature-flags.html b/skills/html/references/html-effectiveness/19-editor-feature-flags.html deleted file mode 100644 index 15be394..0000000 --- a/skills/html/references/html-effectiveness/19-editor-feature-flags.html +++ /dev/null @@ -1,664 +0,0 @@ - - - - - - -Acme — flags.production.json - - - -
    - -
    -
    Acme / editor / feature-flags
    -

    flags.production.json

    -

    A form-based editor for the production feature-flag config. - Toggle flags, fix dependency warnings as they surface, then copy out - only the lines that changed.

    -
    - -
    - - -
    - - -
    - -
    - - - - diff --git a/skills/html/references/html-effectiveness/20-editor-prompt-tuner.html b/skills/html/references/html-effectiveness/20-editor-prompt-tuner.html deleted file mode 100644 index 7a27d03..0000000 --- a/skills/html/references/html-effectiveness/20-editor-prompt-tuner.html +++ /dev/null @@ -1,723 +0,0 @@ - - - - - - -Acme — Support reply prompt tuner - - - -
    - -
    -
    Acme / editor / prompt-tuner
    -

    Support reply draft prompt

    -

    Edit the system prompt on the left and watch three sample tickets re-render the filled template on the right, live as you type. When it reads well across all three moods, copy the template out.

    -
    - -
    - - -
    -
    slots use {{double_brace}} syntax
    -
    - -
    - - -
    -
    - Template -
    - 0 chars · ~0 tokens -
    -
    -
    -
    Available slots
    -
    -
    -
    - - -
    -
    Live preview · 3 sample tickets
    -
    -
    - -
    - -
    Highlighted slots fill from each sample's ticket fields. Anything underlined in dashed clay isn't a known field and will pass through unfilled.
    - -
    - - - - diff --git a/skills/html/references/html-effectiveness/CODE_OF_CONDUCT.md b/skills/html/references/html-effectiveness/CODE_OF_CONDUCT.md deleted file mode 100644 index 91bac7d..0000000 --- a/skills/html/references/html-effectiveness/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,49 +0,0 @@ -# Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment include: - -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -- Focusing on what is best for the overall community - -Examples of unacceptable behavior include: - -- The use of sexualized language or imagery, and sexual attention or advances of - any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email address, - without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the project maintainers at **opensource@anthropic.com**. All -complaints will be reviewed and investigated promptly and fairly. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.1, available at -https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. - -[homepage]: https://www.contributor-covenant.org diff --git a/skills/html/references/html-effectiveness/LICENSE b/skills/html/references/html-effectiveness/LICENSE deleted file mode 100644 index 02fe842..0000000 --- a/skills/html/references/html-effectiveness/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2026 Anthropic PBC - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/skills/html/references/html-effectiveness/README.md b/skills/html/references/html-effectiveness/README.md deleted file mode 100644 index aace658..0000000 --- a/skills/html/references/html-effectiveness/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# The unreasonable effectiveness of HTML — examples - -> **Sample code. Not maintained and not accepting contributions.** - -A gallery of standalone HTML examples that accompany the blog post on using HTML -as a flexible output format. Each file is a self-contained `.html` page (no build -step, no dependencies) demonstrating a different use case — from code review and -design systems to slide decks, status reports, and small interactive editors. - -Open [`index.html`](index.html) for the full, categorized index, or open any -numbered file directly in a browser. - -## Contents - -| Category | Examples | -|---|---| -| Exploration | code approaches, visual designs | -| Code | review, understanding, design systems, component variants | -| Prototyping | animation, interaction | -| Communication | slide deck, status report, incident report, PR write-up | -| Diagrams & research | flowchart, feature/concept explainers | -| Custom editing UIs | triage board, feature flags, prompt tuner | - -## Running - -There is nothing to install or build. Clone the repo and open `index.html` (or -any individual file) in a web browser. - -## A note on sample data - -All product names, data, and scenarios in these examples are fictional and used -only for illustration. The placeholder brand "Acme" and any figures shown are -not real. - -## Security - -See [SECURITY.md](SECURITY.md) for how to report a vulnerability. - -## License - -Released under the [Apache License 2.0](LICENSE). diff --git a/skills/html/references/html-effectiveness/SECURITY.md b/skills/html/references/html-effectiveness/SECURITY.md deleted file mode 100644 index 70e008f..0000000 --- a/skills/html/references/html-effectiveness/SECURITY.md +++ /dev/null @@ -1,22 +0,0 @@ -# Security Policy - -## Reporting a vulnerability - -If you believe you have found a security vulnerability in this repository, -please report it responsibly. - -- **Do not** open a public issue for security problems. -- Email **security@anthropic.com** with a description of the issue and steps to - reproduce it. - -We will acknowledge your report, investigate, and keep you informed of the -resolution. - -## Scope - -This repository contains static, self-contained HTML example files with no -server-side components, no build pipeline, and no third-party runtime -dependencies. The most likely relevant reports are issues such as unsafe inline -script behavior or content that could mislead a reader. General questions about -the accompanying blog post are not security issues — please use normal issues -for those. diff --git a/skills/html/references/html-effectiveness/index.html b/skills/html/references/html-effectiveness/index.html deleted file mode 100644 index 4b06272..0000000 --- a/skills/html/references/html-effectiveness/index.html +++ /dev/null @@ -1,823 +0,0 @@ - - - - - - -The unreasonable effectiveness of HTML — examples - - - -
    - -
    -
    -
    -
    Companion to the blog post
    -

    The unreasonable effectiveness of HTML

    -

    - Twenty self-contained .html files an agent produced instead of a wall of markdown. - Each one trades a document you'd skim for one you'd actually read — open any of them directly in - a browser. Grouped by the kind of work they replace. -

    - -
    - -
    -
    - - -
    -
    01

    Exploration & Planning

    3 demos
    -

    - When you're not sure what you want yet. Ask the agent to fan out across several directions and lay - them next to each other so you can point at one — instead of reading three sequential walls of text - and trying to hold them all in your head. And once you've picked, turn the pick into a plan the - implementer can actually read. -

    - -
    - - -
    -
    02

    Code Review & Understanding

    3 demos
    -

    - Diffs and call-graphs are spatial information; markdown flattens them. Let the agent render the - change as an annotated diff, draw the module as boxes and arrows, or write the PR description your - reviewers actually want — so the shape of the code is visible at a glance. -

    - -
    - - -
    -
    03

    Design

    2 demos
    -

    - HTML is the medium your design system ships in, so it's the natural format for talking about - it. Tokens become swatches, components become contact sheets, and the artifact can be fed straight - back into the next prompt. -

    - -
    - - -
    -
    04

    Prototyping

    2 demos
    -

    - Motion and interaction can't be described, only felt. A throwaway page with the real easing curve or - the real click-through tells you in five seconds what a paragraph of prose never could. -

    - -
    - - -
    -
    05

    Illustrations & Diagrams

    2 demos
    -

    - Inline SVG gives the agent a real pen. Ask for the figures for a post or a flowchart of a process and - get vector art you can tweak by hand or paste straight into the final document. -

    - -
    - - -
    -
    06

    Decks

    1 demo
    -

    - A handful of <section> tags and twenty lines of JS is a slide deck. Point the agent at a - Slack thread or a design doc and get something you can arrow-key through in a meeting — no Keynote, - no export step. -

    - -
    - - -
    -
    07

    Research & Learning

    2 demos
    -

    - An explainer with collapsible sections, tabbed code samples and a glossary in the margin reads very - differently from the same words dumped linearly. The agent can build the scaffolding that makes a new - topic navigable. -

    - -
    - - -
    -
    08

    Reports

    2 demos
    -

    - Recurring documents — status updates, post-mortems — benefit most from a bit of structure and color. - A small chart and a colored timeline turn something people skim into something they actually read. -

    - -
    - - -
    -
    09

    Custom Editing Interfaces

    3 demos
    -

    - Sometimes it's hard to describe what you want in a text box. Ask for a throwaway editor for the exact - thing you're working on — and always end with an export button that turns whatever you did in the UI - back into something you can paste into the agent or commit. You stay in the loop; the loop gets tighter. -

    - -
    - - - -
    - - diff --git a/skills/html/references/interfaces.md b/skills/html/references/interfaces.md new file mode 100644 index 0000000..6cd4ad6 --- /dev/null +++ b/skills/html/references/interfaces.md @@ -0,0 +1,17 @@ +# Interfaces and tools + +Read this for editors, calculators, control panels, and other broad HTML artifacts people operate rather than read straight through. Use `html-prototype` for a styled mockup or a bounded product flow when that skill is available. + +Lead with the current state and the next useful action. Organize the interface around the user's task, not the shape of the underlying data model. + +- Make controls look actionable and label them with the result they produce. +- Show feedback close to the action: pending, success, empty, validation, and error states should all be designed. +- Preserve state visibly. Selected filters, active modes, changed values, and unsaved work should never be mysteries. +- Put summaries before detail when scanning matters, while keeping the path to the underlying evidence obvious. +- Use status color for status, independently from the artifact's decorative accent. +- Keep forms keyboard-friendly, labels explicit, targets comfortably sized, and destructive actions difficult to trigger accidentally. +- Prefer a few strong regions over a uniform grid of interchangeable cards. + +Implement the important path when behavior is part of the request. A convincing static shell with dead controls is worse than a simpler interface whose important path works end to end. + +On narrow screens, preserve the primary task. Reflow secondary panels, turn dense toolbars into deliberate controls, and contain wide data rather than shrinking it until it is illegible.