@olegkoval/agent-skills 1.38.3 → 1.40.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.
Files changed (29) hide show
  1. package/.github/copilot-instructions.md +1 -0
  2. package/.github/prompts/veto-routing.prompt.md +65 -0
  3. package/.kiro/steering/veto-routing.md +64 -0
  4. package/.windsurf/rules/veto-routing.md +63 -0
  5. package/README.md +3 -2
  6. package/adapters/claude/olko-skill-meta/skills/veto-routing/SKILL.md +76 -0
  7. package/adapters/codex/olko-skill-meta/README.md +1 -0
  8. package/adapters/cursor/olko-skill-meta/skills/veto-routing/SKILL.md +76 -0
  9. package/adapters/grok/olko-skill-meta/skills/veto-routing/SKILL.md +76 -0
  10. package/catalog/skills.json +23 -0
  11. package/package.json +1 -1
  12. package/plugins/olko-apple-kit/.claude-plugin/plugin.json +1 -1
  13. package/plugins/olko-creative/.claude-plugin/plugin.json +1 -1
  14. package/plugins/olko-garmin-kit/.claude-plugin/plugin.json +1 -1
  15. package/plugins/olko-git-tools/.claude-plugin/plugin.json +1 -1
  16. package/plugins/olko-github-pr/.claude-plugin/plugin.json +1 -1
  17. package/plugins/olko-obsidian/.claude-plugin/plugin.json +1 -1
  18. package/plugins/olko-product/.claude-plugin/plugin.json +1 -1
  19. package/plugins/olko-reflection/.claude-plugin/plugin.json +1 -1
  20. package/plugins/olko-release/.claude-plugin/plugin.json +1 -1
  21. package/plugins/olko-skill-meta/.claude-plugin/plugin.json +1 -1
  22. package/plugins/olko-skill-meta/skills/veto-routing/SKILL.md +75 -0
  23. package/plugins/olko-web-ops/.claude-plugin/plugin.json +1 -1
  24. package/scripts/lib/catalog.mjs +1 -1
  25. package/site/assets/catalog.css +1064 -0
  26. package/site/assets/catalog.js +232 -0
  27. package/site/build.mjs +218 -166
  28. package/site/assets/paperbag.css +0 -707
  29. package/site/assets/paperbag.js +0 -218
@@ -1,218 +0,0 @@
1
- /*
2
- * paperbag.js: progressive enhancement only. With JS off the page is a
3
- * complete, readable, fully linked catalog; everything below just adds the
4
- * p2output-era cursor theatrics and client-side filtering.
5
- */
6
- (() => {
7
- "use strict";
8
-
9
- const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
10
- const finePointer = window.matchMedia("(hover: hover) and (pointer: fine)");
11
-
12
- /* ------------------------------------------------ cursor-lit lettering */
13
-
14
- // Radius of the pointer's influence, in CSS pixels.
15
- const RADIUS = 130;
16
-
17
- const glyphs = [];
18
-
19
- const splitIntoGlyphs = (el) => {
20
- const text = el.textContent;
21
- // Keep the accessible name intact; the per-character spans are decorative.
22
- el.setAttribute("aria-label", text.trim());
23
- const frag = document.createDocumentFragment();
24
- // Characters are inline-block, which would otherwise let the browser break
25
- // a line mid-word. Wrapping each word keeps normal wrapping behaviour.
26
- for (const word of text.split(/(\s+)/)) {
27
- if (word === "") continue;
28
- if (/^\s+$/.test(word)) {
29
- frag.appendChild(document.createTextNode(word));
30
- continue;
31
- }
32
- const wrap = document.createElement("span");
33
- wrap.className = "w";
34
- wrap.setAttribute("aria-hidden", "true");
35
- for (const ch of word) {
36
- const span = document.createElement("span");
37
- span.className = "g";
38
- span.textContent = ch;
39
- wrap.appendChild(span);
40
- }
41
- frag.appendChild(wrap);
42
- }
43
- el.textContent = "";
44
- el.appendChild(frag);
45
- el.classList.add("reactive");
46
- };
47
-
48
- const measure = () => {
49
- for (const glyph of glyphs) {
50
- const r = glyph.el.getBoundingClientRect();
51
- // Page coordinates so scrolling never invalidates the cache.
52
- glyph.x = r.left + r.width / 2 + window.scrollX;
53
- glyph.y = r.top + r.height / 2 + window.scrollY;
54
- glyph.visible = r.width > 0;
55
- }
56
- };
57
-
58
- const initGlyphs = () => {
59
- if (!finePointer.matches) return;
60
- document.querySelectorAll("[data-reactive]").forEach((el) => {
61
- splitIntoGlyphs(el);
62
- el.querySelectorAll(".g").forEach((span) => {
63
- glyphs.push({ el: span, x: 0, y: 0, lit: 0, visible: true });
64
- });
65
- });
66
- if (glyphs.length) measure();
67
- };
68
-
69
- let pointerX = -9999;
70
- let pointerY = -9999;
71
- let queued = false;
72
-
73
- const paint = () => {
74
- queued = false;
75
- const top = window.scrollY - RADIUS;
76
- const bottom = window.scrollY + window.innerHeight + RADIUS;
77
-
78
- for (const glyph of glyphs) {
79
- let next = 0;
80
- if (glyph.visible && glyph.y > top && glyph.y < bottom) {
81
- const dx = glyph.x - pointerX;
82
- const dy = glyph.y - pointerY;
83
- const d = Math.hypot(dx, dy);
84
- if (d < RADIUS) {
85
- // Ease-out so the falloff reads as a soft brush, not a hard disc.
86
- const t = 1 - d / RADIUS;
87
- next = Math.round(t * t * 100) / 100;
88
- }
89
- }
90
- if (next !== glyph.lit) {
91
- glyph.lit = next;
92
- if (next === 0) glyph.el.style.removeProperty("--h");
93
- else glyph.el.style.setProperty("--h", String(next));
94
- }
95
- }
96
- };
97
-
98
- const onPointerMove = (event) => {
99
- pointerX = event.clientX + window.scrollX;
100
- pointerY = event.clientY + window.scrollY;
101
- document.body.style.setProperty("--mx", `${event.clientX}px`);
102
- document.body.style.setProperty("--my", `${event.clientY}px`);
103
- if (!queued && glyphs.length) {
104
- queued = true;
105
- requestAnimationFrame(paint);
106
- }
107
- };
108
-
109
- if (finePointer.matches && !reduceMotion.matches) {
110
- document.body.classList.add("pointer-fine");
111
- initGlyphs();
112
- window.addEventListener("pointermove", onPointerMove, { passive: true });
113
- window.addEventListener("resize", measure);
114
- }
115
-
116
- /* -------------------------------------------------------- catalog filter */
117
-
118
- const q = document.getElementById("q");
119
- const grid = document.getElementById("grid");
120
-
121
- if (q && grid) {
122
- const cards = Array.from(grid.querySelectorAll(".card"));
123
- const chips = Array.from(document.querySelectorAll(".chip"));
124
- const countEl = document.getElementById("count");
125
- const emptyEl = document.getElementById("empty");
126
- const active = { category: null, adapter: null };
127
-
128
- const apply = () => {
129
- const needle = q.value.trim().toLowerCase();
130
- let shown = 0;
131
-
132
- for (const card of cards) {
133
- const matchesText = !needle || card.dataset.search.includes(needle);
134
- const matchesCat =
135
- !active.category || card.dataset.category === active.category;
136
- const matchesAdapter =
137
- !active.adapter ||
138
- card.dataset.adapters.split(" ").includes(active.adapter);
139
- const visible = matchesText && matchesCat && matchesAdapter;
140
- card.hidden = !visible;
141
- if (visible) shown += 1;
142
- }
143
-
144
- countEl.textContent =
145
- shown === cards.length
146
- ? `${cards.length} skills`
147
- : `${shown} of ${cards.length} skills`;
148
- emptyEl.hidden = shown !== 0;
149
-
150
- // Cards moved, so the glyph rect cache is stale.
151
- if (glyphs.length) requestAnimationFrame(measure);
152
- };
153
-
154
- q.addEventListener("input", apply);
155
-
156
- for (const chip of chips) {
157
- chip.addEventListener("click", () => {
158
- const kind = chip.dataset.kind;
159
- const value = chip.dataset.value;
160
- const isOn = active[kind] === value;
161
- active[kind] = isOn ? null : value;
162
- for (const other of chips) {
163
- if (other.dataset.kind !== kind) continue;
164
- other.setAttribute(
165
- "aria-pressed",
166
- String(!isOn && other.dataset.value === value),
167
- );
168
- }
169
- apply();
170
- });
171
- }
172
-
173
- // Deep links like /?q=release or /?category=marketing.
174
- const params = new URLSearchParams(window.location.search);
175
- if (params.get("q")) q.value = params.get("q");
176
- for (const kind of ["category", "adapter"]) {
177
- const value = params.get(kind);
178
- if (!value) continue;
179
- const chip = chips.find(
180
- (c) => c.dataset.kind === kind && c.dataset.value === value,
181
- );
182
- if (chip) {
183
- active[kind] = value;
184
- chip.setAttribute("aria-pressed", "true");
185
- }
186
- }
187
- apply();
188
- }
189
-
190
- /* ------------------------------------------------------- copy buttons */
191
-
192
- document.querySelectorAll(".copy").forEach((button) => {
193
- const idle = button.textContent;
194
- let resetTimer = 0;
195
-
196
- button.addEventListener("click", async () => {
197
- const pre = button.closest(".slab").querySelector("pre");
198
- try {
199
- await navigator.clipboard.writeText(pre.textContent.trim());
200
- button.textContent = "copied";
201
- // A second click before the first timer fires would otherwise capture
202
- // "copied" as the label to restore, wedging the button in that state.
203
- clearTimeout(resetTimer);
204
- resetTimer = setTimeout(() => {
205
- button.textContent = idle;
206
- }, 1400);
207
- } catch {
208
- // Clipboard blocked (insecure context, denied permission): select the
209
- // text so the reader can copy it by hand.
210
- const range = document.createRange();
211
- range.selectNodeContents(pre);
212
- const selection = window.getSelection();
213
- selection.removeAllRanges();
214
- selection.addRange(range);
215
- }
216
- });
217
- });
218
- })();