haac-aikit 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -9
- package/catalog/commands/decide.md +24 -0
- package/catalog/commands/docs.md +27 -0
- package/catalog/release-notes.json +24 -0
- package/catalog/skills/tier1/docs.md +81 -0
- package/catalog/skills/tier2/decide.md +52 -0
- package/catalog/templates/decide/template.html +244 -0
- package/catalog/templates/docs/starter.html +99 -0
- package/dist/cli.mjs +91 -336
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
- package/catalog/commands/html.md +0 -61
- package/catalog/docs/html-design-system.html +0 -178
- package/catalog/skills/tier1/html-artifacts.md +0 -205
- package/catalog/templates/html-artifacts/01-exploration-code-approaches.html +0 -453
- package/catalog/templates/html-artifacts/02-exploration-visual-designs.html +0 -515
- package/catalog/templates/html-artifacts/03-code-review-pr.html +0 -638
- package/catalog/templates/html-artifacts/04-code-understanding.html +0 -491
- package/catalog/templates/html-artifacts/05-design-system.html +0 -629
- package/catalog/templates/html-artifacts/06-component-variants.html +0 -605
- package/catalog/templates/html-artifacts/07-prototype-animation.html +0 -455
- package/catalog/templates/html-artifacts/08-prototype-interaction.html +0 -396
- package/catalog/templates/html-artifacts/09-slide-deck.html +0 -596
- package/catalog/templates/html-artifacts/10-svg-illustrations.html +0 -495
- package/catalog/templates/html-artifacts/11-status-report.html +0 -528
- package/catalog/templates/html-artifacts/12-incident-report.html +0 -596
- package/catalog/templates/html-artifacts/13-flowchart-diagram.html +0 -396
- package/catalog/templates/html-artifacts/14-research-feature-explainer.html +0 -381
- package/catalog/templates/html-artifacts/15-research-concept-explainer.html +0 -368
- package/catalog/templates/html-artifacts/16-implementation-plan.html +0 -703
- package/catalog/templates/html-artifacts/17-pr-writeup.html +0 -595
- package/catalog/templates/html-artifacts/18-editor-triage-board.html +0 -573
- package/catalog/templates/html-artifacts/19-editor-feature-flags.html +0 -663
- package/catalog/templates/html-artifacts/20-editor-prompt-tuner.html +0 -722
- package/catalog/templates/html-artifacts/MANIFEST.json +0 -182
- package/catalog/templates/html-artifacts/README.md +0 -88
- package/catalog/templates/html-artifacts/index.html +0 -822
package/README.md
CHANGED
|
@@ -6,13 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
One command drops a working AI-coding setup into any repo — rules, skills, safety hooks, subagents, MCP stub, CI templates — for Claude Code, Cursor, Copilot, Windsurf, Aider, Gemini CLI, and Codex.
|
|
8
8
|
|
|
9
|
-
> [!TIP]
|
|
10
|
-
> **Just want HTML output from Claude Code?** Skip the full kit and install only the html-artifacts skill + 20 templates:
|
|
11
|
-
>
|
|
12
|
-
> ```bash
|
|
13
|
-
> npx haac-aikit init html
|
|
14
|
-
> ```
|
|
15
|
-
|
|
16
9
|
## Quickstart
|
|
17
10
|
|
|
18
11
|
```bash
|
|
@@ -46,7 +39,8 @@ npx haac-aikit --yes --tools=claude,cursor,copilot --preset=standard
|
|
|
46
39
|
- **14 agents** in `.claude/agents/` — planner, reviewer, debugger, pr-describer, and more.
|
|
47
40
|
- **Safety hooks** — blocks force-push to main, secret commits, `rm -rf`, reads of `.env*` / `.ssh*` / `.aws*`. Fires before the tool call, doesn't rely on the model cooperating.
|
|
48
41
|
- **Rule observability hooks** — logs which rules load and which get violated, feeds `aikit doctor --rules`.
|
|
49
|
-
-
|
|
42
|
+
- **`/docs` skill** — keeps a small HTML documentation tree at `docs/` current. Section-bounded updates so the agent reads/edits one block, not the whole file.
|
|
43
|
+
- **`/decide` skill (opt-in)** — generates one rich HTML tradeoff page per decision under `docs/decisions/`. Plain-language pros/cons, recommended option marked, written so a non-engineer stakeholder can scan it.
|
|
50
44
|
- CI workflows: gitleaks, standard CI, optional `@claude` PR responder.
|
|
51
45
|
|
|
52
46
|
### Everything scope adds
|
|
@@ -61,6 +55,23 @@ Dev container, OTel exporter, plugin wrapper, auto-sync CI, shape-specific agent
|
|
|
61
55
|
|
|
62
56
|
**Learn from your PR history.** `aikit learn --limit=30` mines merged PR review comments for repeated corrections and proposes them as new rules. No ML — just regex, a stopword list, and Jaccard similarity. → [docs/learn.md](docs/learn.md)
|
|
63
57
|
|
|
58
|
+
## Why the HTML side stays small (one starter, not 20 templates)
|
|
59
|
+
|
|
60
|
+
An earlier version of this kit shipped 20 HTML templates — PR reviews, slide decks, design systems, prototype animations, feature-flag editors, prompt tuners. Beautiful catalog. **We deleted it.** Here's the honest reason:
|
|
61
|
+
|
|
62
|
+
- **Developers don't browse a 20-template catalog.** They open the skill, see the wall of patterns, scroll past it, and write whatever HTML they were going to write anyway. Most of those templates were never reached for in practice. A library nobody borrows from is just shelves.
|
|
63
|
+
- **A 205-line always-on skill is expensive to keep around.** Every agent invocation paid for that context, even when the user wasn't generating HTML at all. We were taxing every conversation to support a rare action.
|
|
64
|
+
- **Two real jobs, not twenty edge cases.** When we asked what people actually needed HTML for, two patterns kept surfacing: (1) **living project docs** they could share for handover, and (2) **tradeoff pages** when there's a decision to make. Everything else was a curated showcase, not a tool.
|
|
65
|
+
|
|
66
|
+
So `/html` got split into two focused skills:
|
|
67
|
+
|
|
68
|
+
- **`/docs`** — always-on, ~80-line skill, one starter HTML template. Maintains an HTML doc tree at `docs/` with section-bounded surgical updates.
|
|
69
|
+
- **`/decide`** — opt-in tier2, ~50-line skill, one rich tradeoff template. Each call writes a new dated file under `docs/decisions/`.
|
|
70
|
+
|
|
71
|
+
Both lean on the marker engine for section-level reads/writes (HTML stays cheap because the agent never reloads the whole file). The skill files together are smaller than the old single skill alone. **Less to read, less to maintain, more actual usage.**
|
|
72
|
+
|
|
73
|
+
If you want the deleted templates back, fork the previous release (`git checkout v0.10.0 -- catalog/templates/html-artifacts/`) — they're forks of [github.com/ThariqS/html-effectiveness](https://github.com/ThariqS/html-effectiveness) and still useful as reference material.
|
|
74
|
+
|
|
64
75
|
## Commands
|
|
65
76
|
|
|
66
77
|
```
|
|
@@ -90,7 +101,7 @@ aikit learn --limit=30 propose rules from your PR review history
|
|
|
90
101
|
|
|
91
102
|
## Status
|
|
92
103
|
|
|
93
|
-
0.
|
|
104
|
+
0.11.0. Holding 1.0 until at least three external teams have used the observability loop on real PRs. Until then, expect breaking changes between minor versions.
|
|
94
105
|
|
|
95
106
|
Looking for teams to try it — feedback shapes 1.0. Comment on [issue #1](https://github.com/Hamad-Center/haac-aikit/issues/1).
|
|
96
107
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Generate a single rich HTML decision page using the `decide` skill.
|
|
2
|
+
|
|
3
|
+
## Usage
|
|
4
|
+
`/decide <topic>`
|
|
5
|
+
|
|
6
|
+
Example: `/decide auth strategy: session cookies vs JWT vs Clerk`.
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. **Confirm the options** with the user before writing. Say back: *"Decision page on `<topic>` with options `A`, `B`, `C` — okay? My pick will be `<X>` because `<one-sentence reason>`."* Wait for yes.
|
|
11
|
+
|
|
12
|
+
2. **Read the template** at `.aikit/templates/decide/template.html`. Copy its structure verbatim — design tokens, layout grid, callout patterns, voice + a11y conventions.
|
|
13
|
+
|
|
14
|
+
3. **Gather concrete inputs** for each option: real cost numbers, real performance figures, real code snippets if relevant. Don't fill cards with hand-waved pros/cons — use facts.
|
|
15
|
+
|
|
16
|
+
4. **Apply the voice rule** when writing prose: plain-language verb + concrete object, jargon in `<code>` chips not the reading path. Explain the technical bit like the reader is 15.
|
|
17
|
+
|
|
18
|
+
5. **Write the file** to `docs/decisions/YYYY-MM-DD-<slug>.html` (today's date, kebab-case slug).
|
|
19
|
+
|
|
20
|
+
6. **Report.** Print the file path and suggest `open docs/decisions/YYYY-MM-DD-<slug>.html` (macOS) / `xdg-open` (Linux).
|
|
21
|
+
|
|
22
|
+
## Fallback
|
|
23
|
+
|
|
24
|
+
If `.aikit/templates/decide/template.html` is missing, run `aikit sync` first.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Update the project's HTML documentation in `docs/` using the `docs` skill.
|
|
2
|
+
|
|
3
|
+
## Usage
|
|
4
|
+
`/docs [optional intent]`
|
|
5
|
+
|
|
6
|
+
With args: use them as the change to document (e.g. `/docs the new auth refresh flow`).
|
|
7
|
+
Without args: infer from the last 5-10 turns of conversation what's worth documenting.
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
1. **Decide what changed.** Identify (a) the doc file (`docs/<slug>.html`) and (b) the section id inside it (`overview`, `flow`, `gotchas`, etc). If no doc fits, propose creating one.
|
|
12
|
+
|
|
13
|
+
2. **Read only the affected section.** Use `readSection(content, id, filePath)` from `src/render/markers` — never load the whole file.
|
|
14
|
+
|
|
15
|
+
3. **Propose before writing.** One sentence in chat:
|
|
16
|
+
> *"I'll update `<section>` in `docs/<file>.html` to reflect <change>. Okay?"*
|
|
17
|
+
Wait for explicit yes. No silent edits.
|
|
18
|
+
|
|
19
|
+
4. **Write through the marker engine.** `writeSection` to replace, `appendSection` for new sections. Anything outside markers is preserved verbatim.
|
|
20
|
+
|
|
21
|
+
5. **Update `docs/index.html`** if you created a new doc or materially changed an existing one — refresh the matching `summary-<slug>` section.
|
|
22
|
+
|
|
23
|
+
6. **Report.** Print the modified file paths and one-line summary of what changed.
|
|
24
|
+
|
|
25
|
+
## Fallback
|
|
26
|
+
|
|
27
|
+
If `.aikit/templates/docs/starter.html` is missing (project synced before this kit version), run `aikit sync` first.
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
3
|
"releases": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.11.0",
|
|
6
|
+
"date": "2026-05-13",
|
|
7
|
+
"headline": "/html replaced by /docs + /decide — fewer templates, sharper jobs",
|
|
8
|
+
"highlights": [
|
|
9
|
+
"NEW `/docs` skill (tier1, ~80 lines) — maintains an HTML documentation tree at `docs/` with section-bounded surgical updates",
|
|
10
|
+
"NEW `/decide` skill (tier2, ~50 lines) — single rich tradeoff page per decision, written to `docs/decisions/YYYY-MM-DD-<slug>.html`",
|
|
11
|
+
"NEW marker engine helpers `readSection`, `writeSection`, `appendSection` for `<!-- BEGIN:haac-aikit:section:<id> -->` blocks (round-trip tested)",
|
|
12
|
+
"REMOVED `/html` skill (was 205 lines, 9 patterns, 20 templates) and `aikit scaffold html` CLI",
|
|
13
|
+
"REMOVED `aikit init html` scope and `docs/aikit-html-design-system.html` shipped doc"
|
|
14
|
+
],
|
|
15
|
+
"breaking": [
|
|
16
|
+
"`/html` slash command is gone — use `/docs` for living docs and `/decide` for tradeoff pages",
|
|
17
|
+
"`aikit init html` scope removed — use `aikit init --scope minimal` (or standard) instead",
|
|
18
|
+
"`aikit scaffold html` removed — agents read templates directly from `.aikit/templates/`"
|
|
19
|
+
],
|
|
20
|
+
"migration": [
|
|
21
|
+
"Run `aikit sync` to pull new `/docs` and `/decide` templates into `.aikit/templates/`",
|
|
22
|
+
"Delete the orphaned `.aikit/templates/html-artifacts/` and `docs/aikit-html-design-system.html` if you have no local edits worth keeping"
|
|
23
|
+
],
|
|
24
|
+
"links": {
|
|
25
|
+
"changelog": "https://github.com/Hamad-Center/haac-aikit/blob/main/CHANGELOG.md#0110---2026-05-13"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
4
28
|
{
|
|
5
29
|
"version": "0.9.0",
|
|
6
30
|
"date": "2026-05-12",
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docs
|
|
3
|
+
description: Use when the project's documentation is out of sync with the code or conversation just established a new architectural fact, feature, or gotcha worth recording. Maintains an HTML documentation tree at `docs/` — many small per-area files plus a rolled-up `docs/index.html`. Reads and writes single sections through marker-bounded `<!-- BEGIN:haac-aikit:section:<id> -->` blocks so updates are surgical and cheap.
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
source: haac-aikit
|
|
6
|
+
license: MIT
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## When to use
|
|
10
|
+
|
|
11
|
+
- User runs `/docs` explicitly.
|
|
12
|
+
- Conversation just produced a documentable fact: a new feature was built, a module was refactored, a gotcha surfaced, an architectural decision was made and you've already used `/decide` to capture the choice itself.
|
|
13
|
+
- A doc is visibly stale (filename or section name appeared in conversation but the file's content contradicts what was just discussed).
|
|
14
|
+
|
|
15
|
+
Do **not** use for one-off explanations — those belong in chat, not docs.
|
|
16
|
+
|
|
17
|
+
## File layout
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
docs/
|
|
21
|
+
index.html ← rolled-up overview: short summary per linked doc + link
|
|
22
|
+
architecture.html ← one HTML file per area or feature
|
|
23
|
+
auth.html
|
|
24
|
+
db.html
|
|
25
|
+
features/<slug>.html ← per-feature deep dives (optional sub-folder)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Every HTML file uses the marker engine for sectioning:
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<!-- BEGIN:haac-aikit:section:overview -->
|
|
32
|
+
<section id="overview"><h2>Overview</h2>... </section>
|
|
33
|
+
<!-- END:haac-aikit:section:overview -->
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Section IDs are kebab-case alphanumeric (`overview`, `data-flow`, `gotchas`, `adr-001`). They're stable across updates so the agent can find them.
|
|
37
|
+
|
|
38
|
+
## Update protocol — follow exactly
|
|
39
|
+
|
|
40
|
+
1. **Identify what changed.** From the recent conversation, name (a) the doc that's affected (`auth.html`, etc.) and (b) the section ID inside it (`overview`, `flow`, etc.). If the doc doesn't exist yet, plan to create it.
|
|
41
|
+
2. **Read only the section you'll edit.** Use the marker engine's `readSection(content, id, filePath)` — never load the whole file.
|
|
42
|
+
3. **Propose the change to the user in chat before writing.** One sentence: *"I'll update `<section>` in `docs/<file>.html` to reflect <change>. Okay?"* Wait for explicit confirmation. No silent writes.
|
|
43
|
+
4. **Write through the marker engine.** Use `writeSection` for replacing an existing section. Use `appendSection` to add a new one. Anything outside markers (user-authored prose, hand-edited content) is preserved automatically.
|
|
44
|
+
5. **Update `docs/index.html`** if you created a new file or materially changed an existing doc's purpose. Replace the matching summary inside its `<!-- BEGIN:haac-aikit:section:summary-<slug> -->` block.
|
|
45
|
+
|
|
46
|
+
## Starter template
|
|
47
|
+
|
|
48
|
+
When a doc doesn't exist yet, scaffold from `.aikit/templates/docs/starter.html` (synced from the catalog). The starter has:
|
|
49
|
+
|
|
50
|
+
- Design tokens in `:root` (`--clay`, `--slate`, `--ivory`, `--oat`, `--olive`, `--gray-*`)
|
|
51
|
+
- Landmark roles (`<main>`, `<nav>`, `<aside>`)
|
|
52
|
+
- One example sectioned block to copy
|
|
53
|
+
- A11y baseline: `<title>`, heading hierarchy, native form controls only
|
|
54
|
+
|
|
55
|
+
Don't invent HTML structure from scratch — read the starter first.
|
|
56
|
+
|
|
57
|
+
## index.html maintenance
|
|
58
|
+
|
|
59
|
+
`docs/index.html` is the navigation hub. Each linked doc gets one summary card inside its own section:
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<!-- BEGIN:haac-aikit:section:summary-auth -->
|
|
63
|
+
<a href="auth.html"><h3>Authentication</h3>
|
|
64
|
+
<p>How sign-in, session, and token refresh work. 1-paragraph summary kept in sync with auth.html.</p></a>
|
|
65
|
+
<!-- END:haac-aikit:section:summary-auth -->
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
When you update `auth.html`'s overview, also update the matching `summary-auth` section in `index.html` so the rollup stays accurate.
|
|
69
|
+
|
|
70
|
+
## Visual content
|
|
71
|
+
|
|
72
|
+
HTML allows inline SVG diagrams, code samples, and graphs when they earn their weight. Default to prose; add a diagram only when it explains something prose can't (a flow, a topology, a sequence).
|
|
73
|
+
|
|
74
|
+
## Anti-patterns to avoid
|
|
75
|
+
|
|
76
|
+
- **Loading the whole file to edit one section.** Defeats the token-cost mitigation; always use `readSection` / `writeSection`.
|
|
77
|
+
- **Silent writes.** Every update gets one-sentence confirmation in chat first. Docs are project-facing; surprise edits erode trust.
|
|
78
|
+
- **Editing content outside the markers.** That's user-authored prose; preserve it verbatim.
|
|
79
|
+
- **Inventing HTML from scratch.** Read the starter template first.
|
|
80
|
+
- **Drifting `index.html`.** When a doc's purpose changes, its summary in `index.html` MUST change too — same commit.
|
|
81
|
+
- **One giant doc.** Split per area; the rollup gives the single-page view if the user wants it.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: decide
|
|
3
|
+
description: Use when the user is about to make a non-trivial choice with 2-4 viable options and wants the tradeoffs visualized as a single rich HTML page they can scan, share, and commit to the project's decision log. Generates one self-contained HTML file per decision under `docs/decisions/YYYY-MM-DD-<slug>.html`. Opt-in only — do not invoke without user request.
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
source: haac-aikit
|
|
6
|
+
license: MIT
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## When to use
|
|
10
|
+
|
|
11
|
+
Explicit invocation only: `/decide <topic>`, "use the decide skill", "make me a decision page on X".
|
|
12
|
+
|
|
13
|
+
Do not invoke proactively. The user picks the moment they need a tradeoff laid out — silent generation creates noise.
|
|
14
|
+
|
|
15
|
+
## Structure of a decision page
|
|
16
|
+
|
|
17
|
+
Every page has the same five blocks. Order matters: decision-makers should never have to scroll to find what they're approving.
|
|
18
|
+
|
|
19
|
+
1. **Decision needed callout** — the question in one sentence at the top. Recommended option marked with `★`.
|
|
20
|
+
2. **Option cards (2-4)** — each card has: title, one-line summary, pros (olive dots), cons (clay dots), how-it-works in 2-3 plain-language sentences.
|
|
21
|
+
3. **Comparison row** — a small table or chip grid putting the options side by side on the dimensions that matter (cost, complexity, reversibility, performance — pick what's relevant).
|
|
22
|
+
4. **Technical bit, explained 15-year-old simple** — one paragraph per option. Plain verbs + concrete objects. Jargon goes in `<code>` chips, not the reading path.
|
|
23
|
+
5. **Recommendation + reasoning** — clay-bordered callout. State the pick, the one-sentence reason, the conditions under which the recommendation flips.
|
|
24
|
+
|
|
25
|
+
## Output
|
|
26
|
+
|
|
27
|
+
- Path: `docs/decisions/YYYY-MM-DD-<slug>.html` (today's date, kebab-case slug from the topic)
|
|
28
|
+
- Template: `.aikit/templates/decide/template.html` — read first, copy structure verbatim, fill placeholders
|
|
29
|
+
- Self-contained: pure HTML/CSS, no CDNs, no build step
|
|
30
|
+
- Committed to git (permanent decision log)
|
|
31
|
+
|
|
32
|
+
## Voice rule (non-negotiable)
|
|
33
|
+
|
|
34
|
+
- One concept per sentence.
|
|
35
|
+
- Plain-language verb + concrete object: *"Load images only when the reader scrolls to them"* beats *"Implement lazy-loading via IntersectionObserver."*
|
|
36
|
+
- Jargon lives in `<code>` chips or collapsed `<details>`, never in main prose.
|
|
37
|
+
- Concrete first, abstract term in parens: *"Make sure failed requests retry safely (idempotent)"*.
|
|
38
|
+
|
|
39
|
+
## A11y baseline (every decision page)
|
|
40
|
+
|
|
41
|
+
- `<title>`, exactly one `<h1>`, heading hierarchy never skips levels.
|
|
42
|
+
- Landmarks: `<main>`, `<nav>` if linking to other decisions, `<aside>` for the recommendation callout.
|
|
43
|
+
- Color contrast ≥ 4.5:1 for body text — design tokens already meet this; don't override.
|
|
44
|
+
- Inline SVG diagrams get `<title>` + `aria-labelledby`. Decorative icons get `aria-hidden="true"`.
|
|
45
|
+
|
|
46
|
+
## Anti-patterns
|
|
47
|
+
|
|
48
|
+
- **More than 4 options.** Decision pages with 5+ options become catalogs; pre-narrow the field.
|
|
49
|
+
- **Recommendation buried below the fold.** First paint must show the recommendation.
|
|
50
|
+
- **Jargon-heavy prose.** If a non-technical stakeholder can't read it, rewrite it.
|
|
51
|
+
- **Silent generation.** This skill is opt-in. Wait for explicit `/decide`.
|
|
52
|
+
- **Skipping the date in the filename.** The decision log sorts chronologically; dates are required.
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>{{TITLE}}</title>
|
|
7
|
+
<meta name="description" content="{{ONE_LINE_DECISION}}">
|
|
8
|
+
<meta name="aikit-doc-type" content="decision">
|
|
9
|
+
<style>
|
|
10
|
+
:root {
|
|
11
|
+
--clay: #D97757;
|
|
12
|
+
--slate: #141413;
|
|
13
|
+
--ivory: #FAF9F5;
|
|
14
|
+
--oat: #E3DACC;
|
|
15
|
+
--olive: #788C5D;
|
|
16
|
+
--gray-150: #F0EEE6;
|
|
17
|
+
--gray-300: #D1CFC5;
|
|
18
|
+
--gray-500: #87867F;
|
|
19
|
+
--gray-700: #3D3D3A;
|
|
20
|
+
--white: #FFFFFF;
|
|
21
|
+
--serif: ui-serif, Georgia, "Times New Roman", serif;
|
|
22
|
+
--mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
|
|
23
|
+
--sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
24
|
+
}
|
|
25
|
+
* { box-sizing: border-box; }
|
|
26
|
+
body {
|
|
27
|
+
margin: 0;
|
|
28
|
+
background: var(--ivory);
|
|
29
|
+
color: var(--slate);
|
|
30
|
+
font-family: var(--sans);
|
|
31
|
+
line-height: 1.55;
|
|
32
|
+
-webkit-font-smoothing: antialiased;
|
|
33
|
+
}
|
|
34
|
+
main { max-width: 1080px; margin: 0 auto; padding: 48px 24px 96px; }
|
|
35
|
+
|
|
36
|
+
h1, h2, h3 { font-family: var(--serif); margin: 0 0 8px; }
|
|
37
|
+
h1 { font-size: clamp(28px, 4vw, 38px); }
|
|
38
|
+
h2 { font-size: clamp(20px, 2.4vw, 26px); margin-top: 48px; }
|
|
39
|
+
h3 { font-size: 17px; margin: 0 0 6px; }
|
|
40
|
+
|
|
41
|
+
.eyebrow {
|
|
42
|
+
font-family: var(--mono);
|
|
43
|
+
font-size: 11px;
|
|
44
|
+
text-transform: uppercase;
|
|
45
|
+
letter-spacing: 0.08em;
|
|
46
|
+
color: var(--gray-500);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.decision-needed {
|
|
50
|
+
background: var(--white);
|
|
51
|
+
border: 1px solid var(--gray-300);
|
|
52
|
+
border-left: 4px solid var(--clay);
|
|
53
|
+
border-radius: 6px;
|
|
54
|
+
padding: 20px 24px;
|
|
55
|
+
margin: 24px 0 36px;
|
|
56
|
+
box-shadow: 0 1px 3px rgba(20, 20, 19, 0.06);
|
|
57
|
+
}
|
|
58
|
+
.decision-needed .question {
|
|
59
|
+
font-family: var(--serif);
|
|
60
|
+
font-size: 22px;
|
|
61
|
+
margin: 6px 0 12px;
|
|
62
|
+
}
|
|
63
|
+
.option-chips { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
64
|
+
.option-chips .chip {
|
|
65
|
+
font-family: var(--mono);
|
|
66
|
+
font-size: 12px;
|
|
67
|
+
background: var(--oat);
|
|
68
|
+
color: var(--slate);
|
|
69
|
+
padding: 4px 10px;
|
|
70
|
+
border-radius: 999px;
|
|
71
|
+
}
|
|
72
|
+
.option-chips .chip.recommended { background: var(--olive); color: var(--white); }
|
|
73
|
+
|
|
74
|
+
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; margin-top: 16px; }
|
|
75
|
+
.card {
|
|
76
|
+
background: var(--white);
|
|
77
|
+
border: 1px solid var(--gray-300);
|
|
78
|
+
border-radius: 6px;
|
|
79
|
+
padding: 18px;
|
|
80
|
+
}
|
|
81
|
+
.card.recommended { border-color: var(--olive); border-width: 2px; }
|
|
82
|
+
.card .summary { color: var(--gray-700); margin: 4px 0 14px; }
|
|
83
|
+
.card ul { list-style: none; padding: 0; margin: 8px 0; font-size: 14px; }
|
|
84
|
+
.card li { padding-left: 18px; position: relative; margin: 4px 0; }
|
|
85
|
+
.card li.pro::before {
|
|
86
|
+
content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--olive);
|
|
87
|
+
position: absolute; left: 2px; top: 8px;
|
|
88
|
+
}
|
|
89
|
+
.card li.con::before {
|
|
90
|
+
content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--clay);
|
|
91
|
+
position: absolute; left: 2px; top: 8px;
|
|
92
|
+
}
|
|
93
|
+
.card .how {
|
|
94
|
+
background: var(--gray-150); padding: 10px 12px; border-radius: 4px;
|
|
95
|
+
font-size: 13px; margin-top: 12px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
table { width: 100%; border-collapse: collapse; margin-top: 12px; font-size: 14px; }
|
|
99
|
+
th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--gray-300); }
|
|
100
|
+
th { background: var(--gray-150); font-weight: 600; font-family: var(--mono); font-size: 12px; text-transform: uppercase; }
|
|
101
|
+
|
|
102
|
+
.tech-block { background: var(--white); border: 1px solid var(--gray-300); border-radius: 6px; padding: 18px; margin-top: 12px; }
|
|
103
|
+
.tech-block h3 { color: var(--gray-700); }
|
|
104
|
+
|
|
105
|
+
.recommendation {
|
|
106
|
+
background: var(--white);
|
|
107
|
+
border: 1px solid var(--olive);
|
|
108
|
+
border-left: 4px solid var(--olive);
|
|
109
|
+
border-radius: 6px;
|
|
110
|
+
padding: 20px 24px;
|
|
111
|
+
margin-top: 32px;
|
|
112
|
+
}
|
|
113
|
+
.recommendation .pick {
|
|
114
|
+
font-family: var(--serif); font-size: 22px; margin: 0 0 8px;
|
|
115
|
+
}
|
|
116
|
+
.recommendation .reason { color: var(--gray-700); }
|
|
117
|
+
.recommendation .flip {
|
|
118
|
+
margin-top: 12px; font-size: 13px; color: var(--gray-500); font-style: italic;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
code { font-family: var(--mono); font-size: 0.9em; background: var(--gray-150); padding: 1px 5px; border-radius: 3px; }
|
|
122
|
+
a { color: var(--clay); text-underline-offset: 2px; }
|
|
123
|
+
a:focus-visible { outline: 2px solid var(--clay); outline-offset: 2px; border-radius: 2px; }
|
|
124
|
+
|
|
125
|
+
footer.provenance {
|
|
126
|
+
margin-top: 48px; padding-top: 16px; border-top: 1px solid var(--gray-300);
|
|
127
|
+
font-family: var(--mono); font-size: 11px; color: var(--gray-500);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@media (max-width: 720px) {
|
|
131
|
+
main { padding: 24px 16px 64px; }
|
|
132
|
+
.cards { grid-template-columns: 1fr; }
|
|
133
|
+
}
|
|
134
|
+
</style>
|
|
135
|
+
</head>
|
|
136
|
+
<body>
|
|
137
|
+
|
|
138
|
+
<main>
|
|
139
|
+
|
|
140
|
+
<header>
|
|
141
|
+
<p class="eyebrow">Decision · {{DATE}}</p>
|
|
142
|
+
<h1>{{TITLE}}</h1>
|
|
143
|
+
</header>
|
|
144
|
+
|
|
145
|
+
<aside class="decision-needed" aria-labelledby="decision-question">
|
|
146
|
+
<p class="eyebrow">Decision needed</p>
|
|
147
|
+
<p id="decision-question" class="question">{{ONE_LINE_DECISION_QUESTION}}</p>
|
|
148
|
+
<div class="option-chips" role="list">
|
|
149
|
+
<span class="chip" role="listitem">A — {{OPTION_A_NAME}}</span>
|
|
150
|
+
<span class="chip recommended" role="listitem">B — {{OPTION_B_NAME}} ★</span>
|
|
151
|
+
<span class="chip" role="listitem">C — {{OPTION_C_NAME}}</span>
|
|
152
|
+
</div>
|
|
153
|
+
</aside>
|
|
154
|
+
|
|
155
|
+
<section id="options" aria-labelledby="options-heading">
|
|
156
|
+
<h2 id="options-heading">Options</h2>
|
|
157
|
+
<div class="cards">
|
|
158
|
+
|
|
159
|
+
<article class="card">
|
|
160
|
+
<h3>A — {{OPTION_A_NAME}}</h3>
|
|
161
|
+
<p class="summary">{{OPTION_A_SUMMARY}}</p>
|
|
162
|
+
<ul aria-label="Pros and cons of option A">
|
|
163
|
+
<li class="pro">{{OPTION_A_PRO_1}}</li>
|
|
164
|
+
<li class="pro">{{OPTION_A_PRO_2}}</li>
|
|
165
|
+
<li class="con">{{OPTION_A_CON_1}}</li>
|
|
166
|
+
</ul>
|
|
167
|
+
<div class="how"><strong>How it works:</strong> {{OPTION_A_HOW}}</div>
|
|
168
|
+
</article>
|
|
169
|
+
|
|
170
|
+
<article class="card recommended" aria-label="Recommended option">
|
|
171
|
+
<h3>B — {{OPTION_B_NAME}} <span aria-hidden="true">★</span></h3>
|
|
172
|
+
<p class="summary">{{OPTION_B_SUMMARY}}</p>
|
|
173
|
+
<ul aria-label="Pros and cons of option B">
|
|
174
|
+
<li class="pro">{{OPTION_B_PRO_1}}</li>
|
|
175
|
+
<li class="pro">{{OPTION_B_PRO_2}}</li>
|
|
176
|
+
<li class="con">{{OPTION_B_CON_1}}</li>
|
|
177
|
+
</ul>
|
|
178
|
+
<div class="how"><strong>How it works:</strong> {{OPTION_B_HOW}}</div>
|
|
179
|
+
</article>
|
|
180
|
+
|
|
181
|
+
<article class="card">
|
|
182
|
+
<h3>C — {{OPTION_C_NAME}}</h3>
|
|
183
|
+
<p class="summary">{{OPTION_C_SUMMARY}}</p>
|
|
184
|
+
<ul aria-label="Pros and cons of option C">
|
|
185
|
+
<li class="pro">{{OPTION_C_PRO_1}}</li>
|
|
186
|
+
<li class="con">{{OPTION_C_CON_1}}</li>
|
|
187
|
+
<li class="con">{{OPTION_C_CON_2}}</li>
|
|
188
|
+
</ul>
|
|
189
|
+
<div class="how"><strong>How it works:</strong> {{OPTION_C_HOW}}</div>
|
|
190
|
+
</article>
|
|
191
|
+
|
|
192
|
+
</div>
|
|
193
|
+
</section>
|
|
194
|
+
|
|
195
|
+
<section id="comparison" aria-labelledby="comparison-heading">
|
|
196
|
+
<h2 id="comparison-heading">Side by side</h2>
|
|
197
|
+
<table>
|
|
198
|
+
<thead>
|
|
199
|
+
<tr>
|
|
200
|
+
<th>Dimension</th>
|
|
201
|
+
<th>A — {{OPTION_A_NAME}}</th>
|
|
202
|
+
<th>B — {{OPTION_B_NAME}}</th>
|
|
203
|
+
<th>C — {{OPTION_C_NAME}}</th>
|
|
204
|
+
</tr>
|
|
205
|
+
</thead>
|
|
206
|
+
<tbody>
|
|
207
|
+
<tr><td>Cost</td><td>{{A_COST}}</td><td>{{B_COST}}</td><td>{{C_COST}}</td></tr>
|
|
208
|
+
<tr><td>Complexity</td><td>{{A_COMPLEXITY}}</td><td>{{B_COMPLEXITY}}</td><td>{{C_COMPLEXITY}}</td></tr>
|
|
209
|
+
<tr><td>Reversibility</td><td>{{A_REVERSIBILITY}}</td><td>{{B_REVERSIBILITY}}</td><td>{{C_REVERSIBILITY}}</td></tr>
|
|
210
|
+
</tbody>
|
|
211
|
+
</table>
|
|
212
|
+
</section>
|
|
213
|
+
|
|
214
|
+
<section id="technical" aria-labelledby="technical-heading">
|
|
215
|
+
<h2 id="technical-heading">The technical bit (in plain language)</h2>
|
|
216
|
+
<div class="tech-block">
|
|
217
|
+
<h3>A — {{OPTION_A_NAME}}</h3>
|
|
218
|
+
<p>{{OPTION_A_TECH_PLAIN}}</p>
|
|
219
|
+
</div>
|
|
220
|
+
<div class="tech-block">
|
|
221
|
+
<h3>B — {{OPTION_B_NAME}}</h3>
|
|
222
|
+
<p>{{OPTION_B_TECH_PLAIN}}</p>
|
|
223
|
+
</div>
|
|
224
|
+
<div class="tech-block">
|
|
225
|
+
<h3>C — {{OPTION_C_NAME}}</h3>
|
|
226
|
+
<p>{{OPTION_C_TECH_PLAIN}}</p>
|
|
227
|
+
</div>
|
|
228
|
+
</section>
|
|
229
|
+
|
|
230
|
+
<aside class="recommendation" aria-labelledby="recommendation-heading">
|
|
231
|
+
<p class="eyebrow" id="recommendation-heading">Recommendation</p>
|
|
232
|
+
<p class="pick">★ Pick {{RECOMMENDED_LETTER}} — {{RECOMMENDED_NAME}}</p>
|
|
233
|
+
<p class="reason">{{RECOMMENDATION_REASON}}</p>
|
|
234
|
+
<p class="flip"><strong>Flip to a different option if:</strong> {{FLIP_CONDITION}}</p>
|
|
235
|
+
</aside>
|
|
236
|
+
|
|
237
|
+
<footer class="provenance">
|
|
238
|
+
Sources: {{SOURCES}} — generated {{ISO_TIMESTAMP}}
|
|
239
|
+
</footer>
|
|
240
|
+
|
|
241
|
+
</main>
|
|
242
|
+
|
|
243
|
+
</body>
|
|
244
|
+
</html>
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>{{TITLE}}</title>
|
|
7
|
+
<meta name="description" content="{{DESCRIPTION}}">
|
|
8
|
+
<meta name="aikit-doc-type" content="reference">
|
|
9
|
+
<style>
|
|
10
|
+
:root {
|
|
11
|
+
--clay: #D97757;
|
|
12
|
+
--slate: #141413;
|
|
13
|
+
--ivory: #FAF9F5;
|
|
14
|
+
--oat: #E3DACC;
|
|
15
|
+
--olive: #788C5D;
|
|
16
|
+
--gray-150: #F0EEE6;
|
|
17
|
+
--gray-300: #D1CFC5;
|
|
18
|
+
--gray-500: #87867F;
|
|
19
|
+
--gray-700: #3D3D3A;
|
|
20
|
+
--white: #FFFFFF;
|
|
21
|
+
--serif: ui-serif, Georgia, "Times New Roman", serif;
|
|
22
|
+
--mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
|
|
23
|
+
--sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
* { box-sizing: border-box; }
|
|
27
|
+
html { scroll-behavior: smooth; }
|
|
28
|
+
body {
|
|
29
|
+
margin: 0;
|
|
30
|
+
background: var(--ivory);
|
|
31
|
+
color: var(--slate);
|
|
32
|
+
font-family: var(--sans);
|
|
33
|
+
line-height: 1.55;
|
|
34
|
+
-webkit-font-smoothing: antialiased;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
main {
|
|
38
|
+
max-width: 880px;
|
|
39
|
+
margin: 0 auto;
|
|
40
|
+
padding: 48px 24px 96px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
h1, h2, h3 { font-family: var(--serif); margin: 0 0 12px; }
|
|
44
|
+
h1 { font-size: clamp(28px, 4vw, 40px); }
|
|
45
|
+
h2 { font-size: clamp(22px, 3vw, 28px); margin-top: 40px; }
|
|
46
|
+
h3 { font-size: 18px; margin-top: 24px; }
|
|
47
|
+
|
|
48
|
+
section { scroll-margin-top: 28px; }
|
|
49
|
+
section + section { margin-top: 32px; }
|
|
50
|
+
|
|
51
|
+
a { color: var(--clay); text-decoration: underline; text-underline-offset: 2px; }
|
|
52
|
+
a:hover { text-decoration-thickness: 2px; }
|
|
53
|
+
a:focus-visible { outline: 2px solid var(--clay); outline-offset: 2px; border-radius: 2px; }
|
|
54
|
+
|
|
55
|
+
code { font-family: var(--mono); font-size: 0.92em; background: var(--gray-150); padding: 1px 5px; border-radius: 3px; }
|
|
56
|
+
pre { background: var(--gray-150); padding: 16px; border-radius: 6px; overflow-x: auto; }
|
|
57
|
+
|
|
58
|
+
.eyebrow {
|
|
59
|
+
font-family: var(--mono);
|
|
60
|
+
font-size: 11px;
|
|
61
|
+
text-transform: uppercase;
|
|
62
|
+
letter-spacing: 0.08em;
|
|
63
|
+
color: var(--gray-500);
|
|
64
|
+
margin-bottom: 8px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@media (max-width: 720px) {
|
|
68
|
+
main { padding: 24px 16px 64px; }
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
71
|
+
</head>
|
|
72
|
+
<body>
|
|
73
|
+
|
|
74
|
+
<main>
|
|
75
|
+
|
|
76
|
+
<header>
|
|
77
|
+
<p class="eyebrow">{{DOC_TYPE}}</p>
|
|
78
|
+
<h1>{{TITLE}}</h1>
|
|
79
|
+
<p>{{ONE_LINE_DESCRIPTION}}</p>
|
|
80
|
+
</header>
|
|
81
|
+
|
|
82
|
+
<!--
|
|
83
|
+
EXAMPLE SECTIONED BLOCK — copy this pattern for each section.
|
|
84
|
+
The agent reads/writes by section id; the marker pair is load-bearing.
|
|
85
|
+
-->
|
|
86
|
+
|
|
87
|
+
<!-- BEGIN:haac-aikit:section:overview -->
|
|
88
|
+
<section id="overview" aria-labelledby="overview-heading">
|
|
89
|
+
<h2 id="overview-heading">Overview</h2>
|
|
90
|
+
<p>One paragraph: what this doc covers, who it's for, when to read it.</p>
|
|
91
|
+
</section>
|
|
92
|
+
<!-- END:haac-aikit:section:overview -->
|
|
93
|
+
|
|
94
|
+
<!-- Add more sections below by duplicating the pattern with a new id. -->
|
|
95
|
+
|
|
96
|
+
</main>
|
|
97
|
+
|
|
98
|
+
</body>
|
|
99
|
+
</html>
|