Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
7c06aee
ANN-19: M4 provider config storage + budget cap + redaction + event log
kurtstohrer May 12, 2026
97903ad
ANN-23: Tabbed Settings overlay + polished Providers panel
kurtstohrer May 12, 2026
f053340
feat(embedded-agents): in-shell agent runtime + CLI providers + init …
kurtstohrer May 17, 2026
a078ab5
demo: add marketing playground (AI first-draft state)
kurtstohrer May 19, 2026
00fbe35
demo: polish marketing page to final state
kurtstohrer May 19, 2026
748e08d
demo: add reset/restore scripts, transcript, and npm scripts
kurtstohrer May 19, 2026
e409587
demo: add screenshots, recording scripts, and captured segments
kurtstohrer May 19, 2026
d0ead88
demo: re-capture screenshots from marketing playground, fix init wiza…
kurtstohrer May 19, 2026
d3c57c0
demo: use vue-vite Solar System Explorer for marketing screenshots
kurtstohrer May 19, 2026
3984834
demo: add recording prompt for testreel + edge-tts init wizard demo
kurtstohrer May 19, 2026
91f96e2
demo: rewrite init wizard outline with natural voiceover and richer flow
kurtstohrer May 19, 2026
2fe254e
feat: embedded local-CLI agents — safe-by-default permissions, robust…
kurtstohrer Jun 4, 2026
49835a6
feat(embedded-agents): server-side run registry + O(1) thread flush
kurtstohrer Jun 4, 2026
bf3ee61
fix(review): P1 breakers, security hardening, all-4-CLI parity, MCP g…
kurtstohrer Jun 10, 2026
ee28791
docs(wireframe): handoff to grow the wireframe tool into a full desig…
kurtstohrer Jun 10, 2026
153e617
feat(server): design-session journal, file-snapshot engine, and agent…
kurtstohrer Jun 11, 2026
ab33ddc
feat(shell): journal-backed change buffer, design-session panel, and …
kurtstohrer Jun 11, 2026
eb7f9ad
docs: design-session apply loop and snapshot-wireframe pivot handoff
kurtstohrer Jun 11, 2026
829c8fd
feat(wireframe): W1 snapshot capture + static canvas
kurtstohrer Jun 11, 2026
c567460
feat(wireframe): W2 canvas manipulation + W3 anchored directions apply
kurtstohrer Jun 11, 2026
602e8b8
feat(wireframe): W4 polish — explode, snap, multi-select, nudge, GC, …
kurtstohrer Jun 11, 2026
1019b60
fix(wireframe): explode keeps the container's styling as a shell back…
kurtstohrer Jun 11, 2026
bffb2e8
feat(wireframe): D1 — remove the Reposition tool everywhere
kurtstohrer Jun 11, 2026
97b05a9
fix(bridge): D2 — preview:component snapshots on the app's real surface
kurtstohrer Jun 11, 2026
f0d6363
feat(data): D3 — wireframe data-binding foundation, shape endpoint, p…
kurtstohrer Jun 11, 2026
d0baebc
feat(wireframe): D4 — generate-component flow replaces the blind pale…
kurtstohrer Jun 11, 2026
e64ad96
feat(wireframe): D5 — sections become wireframe sketch material; Anno…
kurtstohrer Jun 11, 2026
a05b1e0
feat(wireframe): D6 — add directions carry md + bindings; playbook + …
kurtstohrer Jun 11, 2026
c845ce6
fix(wireframe): review fixes — 22 confirmed findings from the D1–D6 a…
kurtstohrer Jun 11, 2026
d71fbf9
fix(wireframe): capture stragglers outside the content root
kurtstohrer Jun 11, 2026
c8cebbf
docs: wireframe data-binding + tool-consolidation kickoff handoff
kurtstohrer Jun 11, 2026
c3d5e1c
feat(playground): /planets controls move into a side rail; stray Butt…
kurtstohrer Jun 11, 2026
600b513
test(e2e): adapt the wireframe suite to the redesigned /planets + res…
kurtstohrer Jun 11, 2026
f1080cd
feat(playground): marketing page gets a live data source for the wire…
kurtstohrer Jun 11, 2026
c703d26
chore(demo): hero reset script — restore HEAD sources, clear sketch/s…
kurtstohrer Jun 12, 2026
57a0303
docs(demo): demo plan v2 — wireframe hero on the marketing page
kurtstohrer Jun 12, 2026
9c13b4c
fix(server): tolerate wrong-shape tasks.json instead of crashing the …
kurtstohrer Jun 12, 2026
ecc6ff7
feat(demo): hero recording pipeline — 'Freeze. Sketch. Real.' take sc…
kurtstohrer Jun 12, 2026
ea287f0
feat(wireframe): place-first component config + apply-lifecycle harde…
kurtstohrer Jun 17, 2026
5083cd7
chore(release): v0.3.0
kurtstohrer Jun 17, 2026
327e730
chore: remove internal working/plan docs from the repo
kurtstohrer Jun 19, 2026
e3011b1
fix(apply,agent): close apply/undo lifecycle wedges and harden the em…
kurtstohrer Jun 22, 2026
95f44ac
feat(wireframe): gate data-binding + explode for the reduced release …
kurtstohrer Jun 22, 2026
332653e
docs(release): security disclosure, changelog, and accuracy sweep; ci…
kurtstohrer Jun 22, 2026
8dc4217
docs: accuracy sweep against current code (remove dangling refs, fix …
kurtstohrer Jun 22, 2026
3716e0f
chore(deps): clear 46 of 47 dependency advisories (critical + all high)
kurtstohrer Jun 22, 2026
edc06a8
chore(release): v0.4.0
kurtstohrer Jun 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
77 changes: 77 additions & 0 deletions .agents/skills/annotask-apply/A11Y_RULES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# A11Y Rules

Read this file for `a11y_fix` tasks. If you are applying a batch of a11y tasks, read it once for the batch, not once per task.

## Task context

The `a11y_fix` task `context` contains:

- `rule`: axe rule ID, or Annotask's synthetic `tab-order` rule
- `impact`, `help`, `helpUrl`
- `elements[]`: offending elements with `html`, `selector`, `fix`, source `file` / `line` / `component`
- `elements[i].a11y`: computed accessibility metadata for the specific element

```text
elements[i].a11y = {
accessible_name, name_source,
role, role_source,
tabindex, focusable,
focus_indicator,
contrast,
aria_attrs,
}
```

If `screenshot_meta` is present, retrieve it via `annotask_get_screenshot` before proposing visual changes such as contrast or focus-ring fixes.

## Rule playbook

Match on `context.rule`.

| Rule(s) | Fix layer | What to do |
|---|---|---|
| `color-contrast`, `color-contrast-enhanced` | Design tokens first | See **Color contrast playbook** below. |
| `label`, `form-field-multiple-labels` | Markup | Wrap input in `<label>` or add `aria-labelledby` that points at visible text. If `name_source === 'placeholder'`, the input still has no real label. |
| `button-name`, `link-name`, `input-button-name` | Markup | Add visible text or `aria-label`. For icon-only buttons, add a visually hidden label (`sr-only` or the project equivalent). Do not rely on `title`. |
| `image-alt`, `role-img-alt`, `svg-img-alt` | Markup | Use `alt=""` for decorative imagery and descriptive `alt` for informational imagery. For SVG icons paired with visible text, use `aria-hidden="true"`. |
| `landmark-one-main`, `region`, `landmark-no-duplicate-banner`, `landmark-no-duplicate-contentinfo` | Layout component | Wrap the page's primary content in `<main>`. Add `role="region"` + `aria-label` to top-level layout containers. These usually live in layout/root files, not leaf components. |
| `heading-order`, `page-has-heading-one`, `empty-heading` | Content/layout | Insert or promote `<h1>`, then renumber subsequent heading levels so the outline is contiguous. Usually a layout or section change. |
| `aria-allowed-attr`, `aria-required-attr`, `aria-valid-attr-value`, `aria-roles`, `aria-required-children`, `aria-required-parent` | Markup | Read `elements[i].a11y.role` and `aria_attrs` to see exactly what is set. Use `helpUrl` to confirm the role's allowed and required attributes, then remove or add attributes accordingly. |
| `aria-hidden-focus`, `aria-hidden-body` | Markup | An element with `aria-hidden="true"` cannot contain focusable descendants. Remove `aria-hidden`, move the focusable elements out, or make them unfocusable with `tabindex="-1"` if appropriate. |
| `tabindex`, `tab-order` | Markup | Remove positive `tabindex`; use `0` for normal DOM-order focus or `-1` for programmatic focus only. For synthetic `tab-order`, inspect `context.tab_order.flag` (`positive`, `unreachable`, `reorder`) and make DOM order match visual order. |
| `meta-viewport`, `html-has-lang`, `html-lang-valid`, `document-title`, `meta-refresh` | Document head | Fix the framework's document-level source of truth: `index.html`, `app/layout.tsx`, `src/routes/+layout.svelte`, or the equivalent root document. |
| `focus-order-semantics`, `nested-interactive` | Markup | Use semantic interactive elements (`<button>`, `<a href>`, `<input>`) instead of clickable `<div>` or `<span>`. Do not nest interactive elements. |
| `bypass`, `skip-link` | Layout component | Add a "Skip to main content" link as the first focusable element in the layout. Use the project's visually-hidden pattern that becomes visible on `:focus`. |
| `duplicate-id`, `duplicate-id-active`, `duplicate-id-aria` | Markup | Search the codebase for hardcoded `id="..."` values and rename one. If the id is generated, make the generation key unique per instance. |
| `frame-title`, `iframe-title` | Markup | Add `title="..."` describing the iframe's purpose. |

## Color contrast playbook

Use this when `context.rule` is `color-contrast` or `color-contrast-enhanced`. The goal is to land **one token-level edit** that fixes the violation on the first try, without spraying inline overrides or hardcoded hex into component CSS.

1. **Read the structured contrast block first.** `elements[i].a11y.contrast` gives you `foreground`, `background`, and `ratio` as actual computed hex. Treat these as facts; do not re-derive from screenshots.
2. **Open the source at `elements[i].file:line` and locate the failing CSS rule.** Identify how `color` and `background`/`background-color` are set:
- `var(--token-name)` → token-level fix (preferred).
- hardcoded hex / `rgb()` / `hsl()` → component-level fix.
- inline `style={…}` / `style="…"` → component-level fix on that one instance.
- Tailwind / utility class (e.g. `bg-blue-500 text-white`) → swap utility classes or extend the project's theme config; do not add ad-hoc inline overrides.
3. **For the token path** — the common case in design-system playgrounds:
- Find the variable's definition (typically a `:root` / `:root[data-theme="*"]` block in `tokens.css`, `globals.css`, `theme.css`, or equivalent). Use `grep` for `--token-name:` if you have to.
- Edit the variable **at its definition**, inside the theme block that matches the current `color_scheme` on the task (`dark` vs `light`). Do not redefine the variable on the component selector — that bypasses the design system and breaks every other consumer.
- If both themes look like they fail, fix the variable in each theme block separately, computing per-theme.
4. **Pick which token to move.** When both `color` and `background` are tokens, default to:
- **Brand background + white/near-white text (`--accent` + `--text-on-accent`):** keep the white text token, darken the brand token. Brand tokens earn their lightness; light text on brand is almost always the intended pattern, and darkening the brand by ~10–20% luminance is usually the smallest visible change.
- **Muted text on neutral surface (`--text-muted`, `--text-subtle` on `--surface*`):** lighten the text token, do not darken the surface. Surface tokens drive layout perception and many components consume them.
- **Disabled/placeholder text:** if the project intentionally uses a low-contrast token, keep the rule failure scoped to that pattern and fix only the offending public-facing instance, not the token.
5. **Choose the new value by luminance, not by eye.** For text vs. opaque background, target ≥4.5:1 (normal text) or ≥3:1 (large/bold ≥18pt or 14pt+700). Move the token in **one direction only** (darken bg *or* lighten fg) — do not split the fix across both ends. After editing, the diff should be one line in the tokens file.
6. **Sanity-check sibling tokens.** If you darken `--accent`, glance at `--accent-strong` (the hover/pressed variant) and `--accent-soft` (low-opacity surfaces). If `--accent-strong` is already darker than your new `--accent` value, leave it. If it's now lighter, slide it darker by the same delta so the brand ramp stays monotonic.
7. **Do not touch the component CSS.** A clean token fix has no edits in the component file. If you find yourself opening the component to override the variable, stop — you are about to re-introduce the instance-level pattern the playbook is trying to prevent.

The agent should also confirm the re-render passes after applying: the user's a11y panel re-scans automatically once the file saves, and the violation should drop off. If it doesn't, the wrong token was moved or the change landed in the wrong theme block.

## General rules

- Prefer pattern fixes over instance fixes. If many entries point at the same file or component, fix the source component once.
- For synthetic `tab-order`, the offending element is in `elements[0].a11y.eid` and the failure type is in `context.tab_order.flag`. There is no axe `helpUrl`; use the WCAG page in `context.helpUrl`.
- When `a11y.accessible_name` is empty and `a11y.focusable` is true, naming is usually the highest-priority fix.
- Layout and document-head rules usually belong in root or layout files, not the selected leaf component.
40 changes: 40 additions & 0 deletions .agents/skills/annotask-apply/ERROR_FIX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Error fix tasks

`error_fix` tasks come from the Errors tab in the Annotask shell. Each task
captures one or more console errors with their stack traces, the route where
they happened, and the number of occurrences.

## Read order

1. **`task.context.level`** — `'error'` or `'warn'`. Errors block; warnings
often don't. Don't suppress warnings into errors and don't downgrade
errors into warnings just to make the panel quieter.
2. **`task.context.errorId`** — stable hash. Use it to confirm you're
fixing what the user saw, not a sibling error from the same file.
3. **`task.context.occurrences`** — when this is high (>50), the error is
firing on every render or interaction. Prioritize root-cause fixes over
try/catch wrappers.
4. **Stack trace** — read the top frame to locate the throw, but read the
second and third frames to understand who called it. The fix usually
lives at the caller, not the throw site.

## Fix patterns

- **Undefined property access** (`Cannot read properties of undefined`) —
fix the producer, not the consumer. Adding `?.` everywhere hides the
real defect.
- **Hydration mismatch** (React/Vue/Svelte SSR) — the server and client
rendered different output. Find the divergent branch (often
`typeof window !== 'undefined'`) and align them.
- **Network errors** — surface to the user; don't swallow with a generic
toast unless the user explicitly asked for one.

## Don't

- Don't add `try/catch` around the call site just to silence the error.
- Don't add `console.error` suppressions or noise filters.
- Don't change the error to a warning to clear the panel.

When you finish, set `status: 'review'` with a one-line resolution that
states (a) the root cause and (b) the file you touched. The user will
verify in the Errors tab that the count stays at zero.
57 changes: 57 additions & 0 deletions .agents/skills/annotask-apply/PERF_FIX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Performance fix tasks

`perf_fix` tasks come from the Perf tab. Each task points at one finding:
a Web Vital that regressed, a heavy resource group, a heavy bundle
package, or long main-thread tasks captured during a recording.

## Read order

1. **`task.context.category`** — what kind of finding this is:
`'vital' | 'resource' | 'long-task' | 'bundle'`. The fix surface
varies dramatically by category; don't apply a vitals recipe to a
bundle task.
2. **`task.context.metric`** — present **only on `vital` findings**: the
uppercase Web Vital name (`'LCP'`, `'CLS'`, `'INP'`, `'TTFB'`,
`'FCP'`). Non-vital findings have no `metric`; key off `category`
and `findingId` instead.
3. **`task.context.findingId`** — stable id that also encodes the
offender: `vital:LCP`, `resource:heavy-script`,
`bundle:lodash`, `blocking:long-tasks`.
4. **`task.context.value`** + **`unit`** — the observed value (`'ms'`
for vitals and long tasks, `'bytes'` for resource/bundle findings,
empty unit for CLS which is unitless). Use this to verify your fix
in the Perf tab post-edit.
5. **`task.context.severity`** — the Web Vitals rating scale:
`'good' | 'needs-improvement' | 'poor'`. `poor` CLS (>0.25) usually
means a single layout shift you can squash; `needs-improvement` may
be unfixable without redesign.
6. **`task.context.detail`** / **`resources`** — human-readable summary,
and (on `resource` findings) the offending URLs with sizes and
durations. `context.metrics` carries the full snapshot when one was
captured.

## Fix patterns

- **LCP** — defer or preload the largest contentful element. Drop hero
images to the right format/size; preconnect to the right origins.
- **CLS** — explicit dimensions on images, reserved space for async
content (banners, ads, late-loaded fonts).
- **INP** — break long tasks, debounce input handlers, move work off the
main thread. `blocking:long-tasks` findings give you Total Blocking
Time and pair naturally with INP work.
- **Resource / bundle size** — confirm the offender lives in user code,
not a vendor chunk. Tree-shake or lazy-load instead of swapping
libraries; the `bundle:<package>` finding's detail may already
suggest a lighter alternative.

## Don't

- Don't suppress the metric by changing what gets counted (e.g. excluding
a route from RUM).
- Don't ship a "fix" that improves the metric in dev but regresses in
prod (e.g. removing `import.meta.hot` blocks).
- Don't refactor unrelated code in a perf task.

Set `status: 'review'` with a resolution that names the finding and the
post-fix expected value (`'CLS dropped from 0.31 to ~0.05 — reserved space
for hero image'`). The user re-runs the Perf scan to confirm.
Loading
Loading