diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 0d7f9a0..5cf28a7 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -11,7 +11,7 @@ "source": "github", "repo": "plannotator/effective-html" }, - "description": "HTML skills for pragmatic visual artifacts — html, html-diagram, and html-plan.", + "description": "One effective-html skill that routes between artifact, diagram, and plan modes for pragmatic, self-contained HTML.", "homepage": "https://github.com/plannotator/effective-html", "repository": "https://github.com/plannotator/effective-html", "license": "MIT", diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 9ea9960..357b3e3 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,8 +1,6 @@ { "name": "plannotator-effective-html", "skills": [ - "./skills/html", - "./skills/html-diagram", - "./skills/html-plan" + "./skills/effective-html" ] } \ No newline at end of file diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index da8ddf5..474946b 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.", + "description": "One effective-html skill that routes between artifact, diagram, and plan modes for pragmatic, self-contained HTML.", "author": { "name": "plannotator", "url": "https://github.com/plannotator" diff --git a/README.md b/README.md index 265fa77..e8c29df 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ _**Note:** The diagram was made by `Fable 5`, I will create more fable 5 artifac [example demo](https://x.com/backnotprop/status/2065479594023829619?s=20) -Focused skills for generating self-contained HTML deliverables with a strong visual bias: +One skill for generating self-contained HTML deliverables with a strong visual bias. It routes to the mode that fits the request: -- `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 +- **Artifact**: an HTML file for whatever you're describing, in the effective HTML style +- **Diagram**: architecture, stack, and systems understanding rendered as a full-screen HTML diagram with high-quality SVG +- **Plan**: an HTML plan page in the effective HTML style, kept close to what you wrote

@@ -37,11 +37,10 @@ List available skills first: npx skills add plannotator/effective-html --list ``` -Install a specific skill: +Install the skill by name: ```bash -npx skills add plannotator/effective-html --skill html-diagram -npx skills add plannotator/effective-html --skill html-plan +npx skills add plannotator/effective-html --skill effective-html ``` ### As a Claude Code plugin @@ -60,14 +59,16 @@ codex plugin marketplace add plannotator/effective-html codex plugin add plannotator-effective-html@effective-html ``` -## Skills +## Skill -- `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. +`effective-html` reads the request and picks a mode: + +- **Artifact** - an HTML file for whatever the user is describing, matching the effective HTML references. +- **Diagram** - a full-screen HTML architecture or stack diagram, SVG-first, minimal prose. Also draws on `references/architecture-example.html`. +- **Plan** - an HTML plan page 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. +The skill lives at `skills/effective-html/SKILL.md` and bundles 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 diff --git a/skills.sh.json b/skills.sh.json index 5685c86..5805f1f 100644 --- a/skills.sh.json +++ b/skills.sh.json @@ -6,9 +6,7 @@ "title": "Effective HTML", "description": "Skills for generating pragmatic HTML diagrams and plans.", "skills": [ - "html", - "html-diagram", - "html-plan" + "effective-html" ] } ] diff --git a/skills/effective-html/SKILL.md b/skills/effective-html/SKILL.md new file mode 100644 index 0000000..423ab7e --- /dev/null +++ b/skills/effective-html/SKILL.md @@ -0,0 +1,26 @@ +--- +name: effective-html +description: Create elegant, self-contained HTML artifacts in the effective-HTML style. This skill should be used whenever the user wants something delivered as a single HTML file — a general artifact (report, explainer, comparison, slide deck, prototype), a full-screen architecture/system diagram (low-prose, high-quality interactive SVG), or a pragmatic plan page. Routes the request to the matching mode and follows the bundled reference examples for style, density, and tone. +--- + +# Effective HTML + +One entry point for producing self-contained HTML artifacts in the effective-HTML style. This file is a router: pick the mode that matches the request, follow its notes, and apply the shared requirement below to every mode. + +## Read first + +Review the example files throughout [`references/html-effectiveness/`](references/html-effectiveness/). Match their alignment — style, density, and tone — as closely as the request allows. Every mode below assumes these examples are in mind. + +## Mode routing + +| The user wants… | Mode | Mode-specific guidance | +|---|---|---| +| A general artifact — report, explainer, comparison, slide deck, prototype, or anything else best delivered as one HTML file | **Artifact** | Build the HTML for whatever is being described, leaning on the references to match style, density, and tone. | +| A full-screen architecture or system diagram, light on prose, that makes the stack click fast | **Diagram** | Build a high-quality SVG and iterate on the diagram more than anything else. Keep prose minimal — simplify toward a full-screen diagram. Where it helps, make the diagram interactive and animate different sequences of system behavior. Also review [`references/architecture-example.html`](references/architecture-example.html) — a finished example (full-screen SVG stage, clickable nodes, flow chips that light up and animate request paths). Style the SVG through CSS classes that use the theme variables — never hard-coded hex inside the SVG — so the diagram follows the theme. | +| A plan page that stays pragmatic and close to what they gave you | **Plan** | Keep it pragmatic and simple. Keep the writing close to the user's input; clean up the grammar without turning it into something bigger. | + +When a request spans modes, pick the dominant one and borrow from the others as needed. + +## Always (every mode) + +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`). diff --git a/skills/effective-html/agents/openai.yaml b/skills/effective-html/agents/openai.yaml new file mode 100644 index 0000000..941a178 --- /dev/null +++ b/skills/effective-html/agents/openai.yaml @@ -0,0 +1,7 @@ +interface: + display_name: "Effective HTML" + short_description: "Create effective standalone HTML artifacts, diagrams, and plans" + default_prompt: "Use $effective-html to create a polished standalone HTML artifact, diagram, or plan." + +policy: + allow_implicit_invocation: true diff --git a/skills/html-diagram/references/architecture-example.html b/skills/effective-html/references/architecture-example.html similarity index 100% rename from skills/html-diagram/references/architecture-example.html rename to skills/effective-html/references/architecture-example.html diff --git a/skills/html-diagram/references/html-effectiveness/01-exploration-code-approaches.html b/skills/effective-html/references/html-effectiveness/01-exploration-code-approaches.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/01-exploration-code-approaches.html rename to skills/effective-html/references/html-effectiveness/01-exploration-code-approaches.html diff --git a/skills/html-diagram/references/html-effectiveness/02-exploration-visual-designs.html b/skills/effective-html/references/html-effectiveness/02-exploration-visual-designs.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/02-exploration-visual-designs.html rename to skills/effective-html/references/html-effectiveness/02-exploration-visual-designs.html diff --git a/skills/html-diagram/references/html-effectiveness/03-code-review-pr.html b/skills/effective-html/references/html-effectiveness/03-code-review-pr.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/03-code-review-pr.html rename to skills/effective-html/references/html-effectiveness/03-code-review-pr.html diff --git a/skills/html-diagram/references/html-effectiveness/04-code-understanding.html b/skills/effective-html/references/html-effectiveness/04-code-understanding.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/04-code-understanding.html rename to skills/effective-html/references/html-effectiveness/04-code-understanding.html diff --git a/skills/html-diagram/references/html-effectiveness/05-design-system.html b/skills/effective-html/references/html-effectiveness/05-design-system.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/05-design-system.html rename to skills/effective-html/references/html-effectiveness/05-design-system.html diff --git a/skills/html-diagram/references/html-effectiveness/06-component-variants.html b/skills/effective-html/references/html-effectiveness/06-component-variants.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/06-component-variants.html rename to skills/effective-html/references/html-effectiveness/06-component-variants.html diff --git a/skills/html-diagram/references/html-effectiveness/07-prototype-animation.html b/skills/effective-html/references/html-effectiveness/07-prototype-animation.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/07-prototype-animation.html rename to skills/effective-html/references/html-effectiveness/07-prototype-animation.html diff --git a/skills/html-diagram/references/html-effectiveness/08-prototype-interaction.html b/skills/effective-html/references/html-effectiveness/08-prototype-interaction.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/08-prototype-interaction.html rename to skills/effective-html/references/html-effectiveness/08-prototype-interaction.html diff --git a/skills/html-diagram/references/html-effectiveness/09-slide-deck.html b/skills/effective-html/references/html-effectiveness/09-slide-deck.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/09-slide-deck.html rename to skills/effective-html/references/html-effectiveness/09-slide-deck.html diff --git a/skills/html-diagram/references/html-effectiveness/10-svg-illustrations.html b/skills/effective-html/references/html-effectiveness/10-svg-illustrations.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/10-svg-illustrations.html rename to skills/effective-html/references/html-effectiveness/10-svg-illustrations.html diff --git a/skills/html-diagram/references/html-effectiveness/11-status-report.html b/skills/effective-html/references/html-effectiveness/11-status-report.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/11-status-report.html rename to skills/effective-html/references/html-effectiveness/11-status-report.html diff --git a/skills/html-diagram/references/html-effectiveness/12-incident-report.html b/skills/effective-html/references/html-effectiveness/12-incident-report.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/12-incident-report.html rename to skills/effective-html/references/html-effectiveness/12-incident-report.html diff --git a/skills/html-diagram/references/html-effectiveness/13-flowchart-diagram.html b/skills/effective-html/references/html-effectiveness/13-flowchart-diagram.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/13-flowchart-diagram.html rename to skills/effective-html/references/html-effectiveness/13-flowchart-diagram.html diff --git a/skills/html-diagram/references/html-effectiveness/14-research-feature-explainer.html b/skills/effective-html/references/html-effectiveness/14-research-feature-explainer.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/14-research-feature-explainer.html rename to skills/effective-html/references/html-effectiveness/14-research-feature-explainer.html diff --git a/skills/html-diagram/references/html-effectiveness/15-research-concept-explainer.html b/skills/effective-html/references/html-effectiveness/15-research-concept-explainer.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/15-research-concept-explainer.html rename to skills/effective-html/references/html-effectiveness/15-research-concept-explainer.html diff --git a/skills/html-diagram/references/html-effectiveness/16-implementation-plan.html b/skills/effective-html/references/html-effectiveness/16-implementation-plan.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/16-implementation-plan.html rename to skills/effective-html/references/html-effectiveness/16-implementation-plan.html diff --git a/skills/html-diagram/references/html-effectiveness/17-pr-writeup.html b/skills/effective-html/references/html-effectiveness/17-pr-writeup.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/17-pr-writeup.html rename to skills/effective-html/references/html-effectiveness/17-pr-writeup.html diff --git a/skills/html-diagram/references/html-effectiveness/18-editor-triage-board.html b/skills/effective-html/references/html-effectiveness/18-editor-triage-board.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/18-editor-triage-board.html rename to skills/effective-html/references/html-effectiveness/18-editor-triage-board.html diff --git a/skills/html-diagram/references/html-effectiveness/19-editor-feature-flags.html b/skills/effective-html/references/html-effectiveness/19-editor-feature-flags.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/19-editor-feature-flags.html rename to skills/effective-html/references/html-effectiveness/19-editor-feature-flags.html diff --git a/skills/html-diagram/references/html-effectiveness/20-editor-prompt-tuner.html b/skills/effective-html/references/html-effectiveness/20-editor-prompt-tuner.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/20-editor-prompt-tuner.html rename to skills/effective-html/references/html-effectiveness/20-editor-prompt-tuner.html diff --git a/skills/html-diagram/references/html-effectiveness/CODE_OF_CONDUCT.md b/skills/effective-html/references/html-effectiveness/CODE_OF_CONDUCT.md similarity index 100% rename from skills/html-diagram/references/html-effectiveness/CODE_OF_CONDUCT.md rename to skills/effective-html/references/html-effectiveness/CODE_OF_CONDUCT.md diff --git a/skills/html-diagram/references/html-effectiveness/LICENSE b/skills/effective-html/references/html-effectiveness/LICENSE similarity index 100% rename from skills/html-diagram/references/html-effectiveness/LICENSE rename to skills/effective-html/references/html-effectiveness/LICENSE diff --git a/skills/html-diagram/references/html-effectiveness/README.md b/skills/effective-html/references/html-effectiveness/README.md similarity index 100% rename from skills/html-diagram/references/html-effectiveness/README.md rename to skills/effective-html/references/html-effectiveness/README.md diff --git a/skills/html-diagram/references/html-effectiveness/SECURITY.md b/skills/effective-html/references/html-effectiveness/SECURITY.md similarity index 100% rename from skills/html-diagram/references/html-effectiveness/SECURITY.md rename to skills/effective-html/references/html-effectiveness/SECURITY.md diff --git a/skills/html-diagram/references/html-effectiveness/index.html b/skills/effective-html/references/html-effectiveness/index.html similarity index 100% rename from skills/html-diagram/references/html-effectiveness/index.html rename to skills/effective-html/references/html-effectiveness/index.html diff --git a/skills/html-diagram/SKILL.md b/skills/html-diagram/SKILL.md deleted file mode 100644 index e21ecc2..0000000 --- a/skills/html-diagram/SKILL.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -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 ---- - -# HTML Diagram - -Review the SVG diagrams used throughout `references/html-effectiveness/`. - -There are a bunch in there, and some of them are focused on architecture and whatnot. - -After reviewing them, create an HTML file that is strictly for visualizing the architecture and understanding the stack. - -It should not be prose-heavy. It should simplify more into a full-screen diagram and whatnot. - -Build a high-quality diagram in SVG. Take your time iterating on the diagram more than anything. - -If it makes sense, make the diagram interactive and able to visualize and animate different sequences of system behavior. - -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). - -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. diff --git a/skills/html-diagram/agents/openai.yaml b/skills/html-diagram/agents/openai.yaml deleted file mode 100644 index 171a409..0000000 --- a/skills/html-diagram/agents/openai.yaml +++ /dev/null @@ -1,7 +0,0 @@ -interface: - display_name: "HTML Diagram" - short_description: "Create effective standalone HTML diagrams" - default_prompt: "Use $html-diagram to create a polished architecture diagram." - -policy: - allow_implicit_invocation: false diff --git a/skills/html-plan/SKILL.md b/skills/html-plan/SKILL.md deleted file mode 100644 index fbd3b66..0000000 --- a/skills/html-plan/SKILL.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -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 ---- - -# HTML Plan - -Review the files throughout `references/html-effectiveness/`. - -After reviewing them, create an HTML file for the plan in a similar style. - -Keep it pragmatic and simple. - -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`). diff --git a/skills/html-plan/agents/openai.yaml b/skills/html-plan/agents/openai.yaml deleted file mode 100644 index 6a17c9d..0000000 --- a/skills/html-plan/agents/openai.yaml +++ /dev/null @@ -1,7 +0,0 @@ -interface: - display_name: "HTML Plan" - short_description: "Create pragmatic visual HTML plans" - default_prompt: "Use $html-plan to create a pragmatic 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.
-
-
- - - -
- - - - 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

- -
-
- - -
-
-
In progress
-

Carrying into next week

- -
-
- - -
-
-
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

- -
- 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
-
-
-
- - -
- -
- - - - 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

-
- -
- - -
-

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 -
-
-
-
- - - -
- - 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 -
- -
-
- - - -
- - 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

- - -

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
-
-
- -
- - - -
- - - - 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/SKILL.md b/skills/html/SKILL.md deleted file mode 100644 index f2a2e27..0000000 --- a/skills/html/SKILL.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -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 ---- - -# HTML - -Review the files throughout `references/html-effectiveness/`. - -Create an HTML file for whatever the user is describing. Use the references as best you can to match alignment — style, density, and tone. - -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`). diff --git a/skills/html/agents/openai.yaml b/skills/html/agents/openai.yaml deleted file mode 100644 index 3a5df66..0000000 --- a/skills/html/agents/openai.yaml +++ /dev/null @@ -1,7 +0,0 @@ -interface: - display_name: "HTML" - short_description: "Create effective standalone HTML artifacts" - default_prompt: "Use $html to create a polished standalone HTML artifact." - -policy: - allow_implicit_invocation: false 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

- -
- -
-

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.
-
-
- - - -
- - - - 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

- -
-
- - -
-
-
In progress
-

Carrying into next week

- -
-
- - -
-
-
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

- -
- 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
-
-
-
- - -
- -
- - - - 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

-
- -
- - -
-

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 -
-
-
-
- - - -
- - 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 -
- -
-
- - - -
- - 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

- - -

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
-
-
- -
- - - -
- - - - 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. -

- -
- - - -
- -