@mmerterden/multi-agent-pipeline 20.6.0 → 20.7.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 (69) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/docs/facts.json +1 -1
  3. package/manifest.json +71 -71
  4. package/package.json +1 -1
  5. package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
  6. package/pipeline/scripts/_notices.mjs +11 -0
  7. package/pipeline/scripts/gen-skills-index.mjs +1 -1
  8. package/pipeline/skills/.skill-manifest.json +39 -39
  9. package/pipeline/skills/shared/README.md +1 -1
  10. package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
  11. package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
  12. package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
  13. package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
  14. package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
  15. package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
  16. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
  17. package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
  18. package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
  19. package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
  20. package/pipeline/skills/shared/external/council/SKILL.md +1 -0
  21. package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
  22. package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
  23. package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
  24. package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
  25. package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
  26. package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
  27. package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
  28. package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
  29. package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
  30. package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
  31. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
  32. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
  33. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
  34. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
  35. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
  36. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
  37. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
  38. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
  39. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
  40. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
  41. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
  42. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
  43. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
  44. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
  45. package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
  46. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
  47. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
  48. package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
  49. package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
  50. package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
  51. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
  52. package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
  53. package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
  54. package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
  55. package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
  56. package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
  57. package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
  58. package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
  59. package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
  60. package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
  61. package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
  62. package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
  63. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
  64. package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
  65. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
  66. package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
  67. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
  68. package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
  69. package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
@@ -12,14 +12,12 @@
12
12
  <!-- /toc -->
13
13
 
14
14
  A design audit that reads a screen top to bottom and reports what looks wrong
15
- finds about one defect per element: the wrong font on a label, and not that same
16
- label's wrong colour and wrong inset. This file is the catalog, and the three
15
+ catches roughly a single defect per element: it spots a label's wrong font and
16
+ misses the wrong colour and wrong inset on that very label. This file is the catalog, and the three
17
17
  mechanisms that turn "I looked at it" into a countable result.
18
18
 
19
- Derived generically from an upstream corporate screen-QA tool (recorded in
20
- `derivedSkillSources`). The doctrine is portable. Its vendored design-token
21
- catalogs and product examples are not, and were not taken - section 7 says what
22
- replaces them.
19
+ The doctrine is generic. It carries no design-token catalog and no product
20
+ examples - section 7 says what stands in for them.
23
21
 
24
22
  Consumers: `/multi-agent:design-check` (the runner), Phase 3 review when a UI
25
23
  diff is under review, and `features/visual-evidence.md` when a capture has to
@@ -27,10 +25,9 @@ prove a fix. Gate: `smoke-design-conformance.sh`.
27
25
 
28
26
  ## 0. Why this runs as a gate
29
27
 
30
- `design-check` existed as a command for a while with no phase invoking it, so the only
31
- thing standing between a build and visual drift was the user opening the app and
32
- looking. On one run that produced 16pt padding where the frame said `Spacing/12`, and a
33
- full sheet rebuild afterwards.
28
+ A conformance check that no phase invokes leaves the user opening the app as the
29
+ only barrier between a build and visual drift: 16pt padding where the frame says
30
+ `Spacing/12` ships, and is found after the fact.
34
31
 
35
32
  The reason it cannot be advice is structural, not historical: a reviewer reading a diff
36
33
  cannot see spacing. Every other Phase 4 check reads text and reasons about text; this
@@ -49,8 +46,8 @@ once, before any comparison:
49
46
  into its parent.
50
47
  2. For each row, pre-fill the design side of every rule that applies and leave
51
48
  the implementation side blank.
52
- 3. Fill every blank. **A blank cell is a fail-to-verify, not a pass**, and it is
53
- reported as one.
49
+ 3. Complete every empty cell. **Any blank cell is a fail-to-verify** (never a pass),
50
+ and the report lists it that way.
54
51
 
55
52
  The inventory is the coverage guarantee; the rule groups in section 5 are the
56
53
  per-cell recipe. A truncated inventory makes the denominator wrong, so it is
@@ -74,15 +71,15 @@ and safe-area insets are not in it.
74
71
  ## 3. Adaptive per-component convergence
75
72
 
76
73
  One pass over a component catches roughly one defect on it. So each component is
77
- re-checked until **two consecutive attempts find nothing new on it**.
74
+ checked again and again, stopping once **two consecutive attempts find nothing new** there.
78
75
 
79
- - Soft cap: reaching attempt 8 without two consecutive clean attempts stops that
80
- component with a `did-not-converge` warning. There is never a ninth attempt.
76
+ - Soft cap: if attempt 8 arrives and the last two attempts were not both clean, the
77
+ component ends with a `did-not-converge` warning. A ninth attempt never runs.
81
78
  - A component with a font, a margin and a colour defect needs about three
82
79
  finding attempts plus two clean ones. A correct component needs the two clean
83
80
  attempts and nothing more.
84
- - The screen is done when **every** inventoried component has reached two
85
- consecutive clean attempts or its cap with a warning. Not when the walk
81
+ - The screen is finished once **each** component in the inventory has either two
82
+ clean attempts in a row or has hit its cap and carries the warning. Not when the walk
86
83
  reached the bottom.
87
84
 
88
85
  On a fixing run, each attempt that found something is fixed, re-captured, and
@@ -94,37 +91,37 @@ what each attempt changed rather than one undifferentiated diff.
94
91
  | Tag | Meaning |
95
92
  |---|---|
96
93
  | `[MEASURE]` | Verified in the primary capture: design value against measured pixels or resolved code value (section 2) |
97
- | `[CAPTURE+]` | Needs an extra capture pass - a second appearance, a mirrored layout, another width, another state. Skipping one is allowed only if the skip is logged |
94
+ | `[CAPTURE+]` | Requires one more capture - a second appearance, a mirrored layout, a different width or state. A pass may be skipped, provided the log records the skip |
98
95
  | `[A11Y]` | Accessibility lane: the platform accessibility tree (labels, element frames) plus contrast math |
99
- | `[DYNAMIC]` | Behavioural or temporal; a static capture cannot show it. Verify by driving the device, or report `not verified (dynamic)`. **Never silently pass a `[DYNAMIC]` item** |
96
+ | `[DYNAMIC]` | Behavioural or temporal; a static capture cannot show it. Drive the device to verify it, or report `not verified (dynamic)`. **Never silently pass a `[DYNAMIC]` item**; it is either exercised or reported |
100
97
 
101
98
  ## 5. The catalog
102
99
 
103
100
  Run every applicable item for **every** component, then every gap through
104
- group 2, then the whole-screen passes (17, 21, 22, 24, 25). A check that was not
105
- run is a fail-to-verify.
101
+ group 2, then the whole-screen passes (17, 21, 22, 24, 25). Any check left unrun
102
+ counts as a fail-to-verify.
106
103
 
107
- **1. Layout** `[MEASURE]` - x relative to container (never absolute y: the status
108
- bar offsets it), y relative to an in-content span, L/R/T/B margin to parent,
104
+ **1. Layout** `[MEASURE]` - x measured from the container (y is never taken as an
105
+ absolute value, since the status bar shifts it), y relative to an in-content span, L/R/T/B margin to parent,
109
106
  centring, baseline alignment across a row, shared leading edge for siblings,
110
107
  label-left/value-right rows aligned at both ends, safe-area and system-bar
111
108
  clearance.
112
109
 
113
110
  > **Horizontal-inset lane** - the most-skipped one. For every element record
114
111
  > **both** sides of the leading inset: the design value and the measured
115
- > implementation value. One side filled is a fail-to-verify. Then two cheap
116
- > catches that need no per-element math: (a) **leading rail** - every loose,
117
- > non-carded text in a vertical group must share one leading x; if the
118
- > implementation puts a subtitle at the card's outer edge while the design insets
119
- > it, the rail is broken; (b) **sibling consistency** - when sibling screens
120
- > exist, diff the same element's inset across them; the outlier is usually the
121
- > bug. A different text-wrap point is a symptom of a different margin, not only
122
- > of a different font.
112
+ > implementation value. If only one of the two is filled, that is a fail-to-verify.
113
+ > Two inexpensive checks follow that require no per-element arithmetic:
114
+ > (a) **leading rail** - loose text outside any card, stacked vertically, lines up
115
+ > on a single leading x; a subtitle the implementation places on the card's outer
116
+ > edge, where the design indents it, breaks the rail; (b) **sibling consistency** -
117
+ > if the screen has siblings, compare the inset of one element across all of them;
118
+ > the one that differs is usually the defect. Text that wraps at another point
119
+ > often signals a changed margin, and not only a changed font.
123
120
 
124
121
  **2. Spacing** `[MEASURE]` - outer margins, inner padding, screen edge margin
125
122
  (L=R symmetric), text-to-icon and icon-to-button and card-to-card and
126
123
  section-to-section gaps, list/grid/row spacing, the vertical gap **between**
127
- adjacent components (`next.y - (prev.y + prev.h)` against the stack spacing), and
124
+ neighbouring components (compute `next.y - (prev.y + prev.h)` and compare it with the stack spacing), and
128
125
  every gap resolving to a spacing token - an off-scale value is a deviation.
129
126
 
130
127
  **3. Size** `[MEASURE]` - width and height against the design (measured), min and
@@ -166,23 +163,23 @@ single-tint template is a defect), and vector crispness.
166
163
 
167
164
  **11. Buttons** `[MEASURE]` - width and **measured height** (from the rendered
168
165
  fill rect, never a frame token), L/R/T/B spacing with L=R symmetry, the inner
169
- label's font/weight/colour/alignment **as its own row**, the inner icon
166
+ label as a **separate row** (font, weight, colour, alignment), the inner icon
170
167
  (presence, size, colour, side, spacing), centring, fill and border and text
171
168
  colour for the current state, `[CAPTURE+]` the state set (group 21).
172
169
 
173
170
  > A button instance matches no text, icon or field kind, so an inventory built by
174
171
  > kind drops it silently - and with it the button height and its nested label.
175
- > The button is its own row and its children are exploded into their own rows.
172
+ > So each button gets a row, and each child inside it gets a row of its own too.
176
173
 
177
174
  **12. Input fields** `[MEASURE]` - **measured height** (the rendered field box,
178
175
  never a frame or size token, because internal padding is not in the token),
179
176
  width, border, radius, placeholder text and its colour and alignment, background
180
- shade (read-only vs editable), prefix or affix and its colour, cursor and
177
+ shade (editable vs read-only), the prefix or affix with its colour, cursor and
181
178
  selection colour, character counter behaviour, `[CAPTURE+]` focus/error/disabled/
182
179
  filled states with the error message's colour, position and icon, `[DYNAMIC]`
183
180
  keyboard type.
184
181
 
185
- **13. Card** `[MEASURE]` - padding, radius, background, border, shadow, and
182
+ **13. Card** `[MEASURE]` - radius, padding, border, background, shadow, and
186
183
  content grouping: **sample the pixel behind every text block** - is it inside a
187
184
  card or bare on the page background? A design block in a card that the
188
185
  implementation renders bare (or the reverse) is a wrong-container finding
@@ -192,7 +189,7 @@ side is code-verifiable (inside a card helper vs placed bare in a stack with
192
189
  padding). Never infer this from a glance.
193
190
 
194
191
  **14. Lists** `[MEASURE]` - item height and internal padding, divider colour and
195
- thickness and insets, inter-item spacing, section header grouping and order,
192
+ thickness and insets, spacing between items, how section headers group and order,
196
193
  `[DYNAMIC]` scroll behaviour and lazy loading.
197
194
 
198
195
  **15. Navigation / header** `[MEASURE]` - bar height, title text and alignment,
@@ -200,8 +197,8 @@ back affordance present and correct and mirrored under RTL, right-side actions
200
197
  present and ordered, bottom navigation items with icons, labels and selected
201
198
  state, `[DYNAMIC]` transition style.
202
199
 
203
- **16. Scroll** - `[DYNAMIC]` smooth scroll, bounce, overscroll, sticky header,
204
- scroll indicator; `[MEASURE]` the pinned header or footer position, which is the
200
+ **16. Scroll** - `[DYNAMIC]` scroll smoothness, bounce and overscroll, a sticky
201
+ header, the scroll indicator; `[MEASURE]` the pinned header or footer position, which is the
205
202
  static part a capture can check.
206
203
 
207
204
  **17. Responsive** `[CAPTURE+]` - small, medium and large phone widths, tablet,
@@ -214,23 +211,23 @@ width rather than reasoning about it.
214
211
  fade/scale/slide/rotation, loading and skeleton animation, haptics. Verify by
215
212
  recording the device or report `not verified (dynamic)`.
216
213
 
217
- **20. Visibility** `[CAPTURE+]` - hidden vs visible renders correctly; collapse
218
- and expand states captured separately.
214
+ **20. Visibility** `[CAPTURE+]` - both the visible and the hidden variant render as
215
+ designed; the expanded and collapsed states each get their own capture.
219
216
 
220
217
  **21. States** `[CAPTURE+]` per interactive component - default, pressed, focus,
221
218
  selected, active, disabled (colour, opacity, and genuinely not tappable),
222
219
  loading, empty, error, success.
223
220
 
224
- > **State fidelity gate**: the captured implementation must be in the exact state
225
- > the design frame depicts - the same toggle position, the same filled or empty
221
+ > **State fidelity gate**: before comparing, put the implementation into precisely
222
+ > the state shown by the design frame - the same toggle position, the same filled or empty
226
223
  > content, the same validation result. A capture in the wrong state is redone,
227
224
  > not compared.
228
225
 
229
226
  **22. Accessibility** `[A11Y]` - contrast at least 4.5:1 computed from sampled
230
227
  colours, tap target at least 44x44pt / 48x48dp from the accessibility tree,
231
228
  screen-reader label present and meaningful plus a meaningful hint, correct
232
- traits, an accessibility identifier on every interactive element, and a logical
233
- focus order. Whether to also audit scaled text sizes depends on the project: a
229
+ traits, an accessibility identifier on each element a user can interact with, and
230
+ a logical focus order. Whether to also audit scaled text sizes depends on the project: a
234
231
  design system with fixed, non-scaling typography makes a forced-scale render
235
232
  meaningless noise, so state which of the two the project is instead of assuming.
236
233
 
@@ -258,31 +255,31 @@ overflow. The value itself (a name, a number, a masked field) is not under test.
258
255
  **27. Component presence and order - hard gate** - the group the whole walk
259
256
  exists for.
260
257
 
261
- > Mechanical, not a glance. Number every element of the design list - text **and**
262
- > every icon, avatar, badge, **and every button** - and for each write its
263
- > implementation counterpart or `MISSING`. Report the count explicitly: "N design
264
- > components -> N implementation counterparts". "Complete" may not be concluded
258
+ > Done mechanically, never by eye. Give a number to each element in the design
259
+ > list - the text **and** each icon, avatar and badge, **and each button** - and
260
+ > beside it name the matching implementation element, or write `MISSING`. State
261
+ > the totals outright: "N design components -> N implementation counterparts". "Complete" may not be concluded
265
262
  > without that list. A button and the label nested inside it are two presence
266
263
  > checks, not one.
267
264
  >
268
- > - **Icons are the most-missed presence class.** For every icon in the design
269
- > list, locate it in the render by measuring its coloured bounding box. A design
265
+ > - **Presence checks miss icons more than anything else.** Find each design-list
266
+ > icon in the render by measuring the bounding box of its coloured pixels. A design
270
267
  > icon with roughly no matching pixels is a missing-element finding.
271
- > - **Recurse into nested blocks.** The gate applies to rows inside cards - masked
272
- > rows, list rows, key/value rows - not only to top-level sections. "That card
273
- > looks right" is not a pass.
268
+ > - **Descend into nested blocks.** Rows within cards (masked, list, key/value)
269
+ > fall under the gate just as top-level sections do. A card that "seems fine"
270
+ > has not passed.
274
271
  > - **Bidirectional, and code-side too.** Diff design-to-implementation
275
272
  > (`MISSING`) *and* implementation-to-design (`EXTRA`). The most-missed extra is
276
273
  > a neutral decoration the implementation adds - a trailing chevron, an
277
274
  > underline, a strikethrough - which a colour-based, one-directional comparison
278
275
  > cannot see. Diff the implementation's explicit decoration modifiers against
279
276
  > the design's own decoration nodes, independently of the string.
280
- > - **A localization gap does not short-circuit this gate.** Raw keys are one
277
+ > - **Missing localization never ends this gate early.** Raw keys form a single
281
278
  > finding; presence, icon, decoration and structure checks still run, because
282
279
  > they read code and spec rather than the rendered string.
283
280
 
284
- Findings: `MISSING` · `EXTRA` · `MISSING-BETWEEN` (dropped from the middle of the
285
- sequence) · `REORDERED` · `WRONG-STATE` · `WRONG-CONTAINER` (present but grouped
281
+ Findings: `MISSING` · `EXTRA` · `MISSING-BETWEEN` (absent from inside the sequence,
282
+ not at its ends) · `REORDERED` · `WRONG-STATE` · `WRONG-CONTAINER` (present but grouped
286
283
  differently, loose vs carded).
287
284
 
288
285
  **28. Keyboard and input behaviour** `[DYNAMIC]` - keyboard avoidance with the
@@ -291,17 +288,18 @@ correct field.
291
288
 
292
289
  **29. Analytics** - out of visual scope; checked only when the spec requires it.
293
290
 
294
- **30. Cross-check matrix** - per component confirm x, y, w, h, the four margins,
295
- the four paddings, font family/size/weight, line height, letter spacing, text
296
- colour, background colour, border width/radius/colour, shadow, opacity, icon
297
- size/colour/position, image size/crop, divider, alignment, responsive, state,
291
+ **30. Cross-check matrix** - for each component confirm x, y, w and h, all four
292
+ margins and all four paddings, the font's family, size and weight, letter spacing,
293
+ line height, text colour, background colour, the border's width, radius and
294
+ colour, shadow, opacity, icon size, colour and position, image crop and size,
295
+ divider, alignment, responsive behaviour, state,
298
296
  animation, safe area, and overflow. **Mark only deviations** on the image;
299
297
  matches belong in the report text.
300
298
 
301
299
  ## 6. Output
302
300
 
303
- Mark only problems on the image, with thin lines. Everything else goes in the
304
- report, whose section keys are stable and whose prose follows `outputLanguage`:
301
+ Draw thin lines on the image around problems and nothing else. All other
302
+ content belongs in the report, whose section keys are stable and whose prose follows `outputLanguage`:
305
303
 
306
304
  | Key | Content |
307
305
  |---|---|
@@ -309,7 +307,7 @@ report, whose section keys are stable and whose prose follows `outputLanguage`:
309
307
  | `localization` | Raw keys, missing keys, hardcoded strings |
310
308
  | `matches` | What was checked and agreed |
311
309
  | `ignored` | What was deliberately out of scope, with the reason |
312
- | `not_verified` | **Every** `[DYNAMIC]` and `[CAPTURE+]` item that was not run, so the coverage gap is explicit rather than absent |
310
+ | `not_verified` | **Every** `[DYNAMIC]` and `[CAPTURE+]` item left unrun, which makes the coverage gap visible instead of silent |
313
311
 
314
312
  Each finding is `[what] + [why] + [how]` with `file:line` wherever the
315
313
  implementation side is code-resolvable. A finding without a file reference is
@@ -158,3 +158,14 @@ export function unnamedUpstreams(externalDir) {
158
158
  }
159
159
  return out;
160
160
  }
161
+
162
+ /**
163
+ * Skills under shared/external with no `metadata.source`. Every skill that ships
164
+ * into a stack plugin states where it came from: `multi-agent-pipeline` when it
165
+ * was written here, `"<upstream> (<license>)"` when it is vendored.
166
+ */
167
+ export function sourcelessSkills(externalDir) {
168
+ return skillDirs(externalDir).filter(
169
+ (s) => !metadataSource(readFileSync(join(externalDir, s, "SKILL.md"), "utf8")),
170
+ );
171
+ }
@@ -81,7 +81,7 @@ md += `Single source of truth for skills delivered to both Claude Code (\`~/.cla
81
81
  md += `**Total:** ${total} skills (${breakdown}). Auto-generated by \`scripts/gen-skills-index.mjs\` - do not edit by hand.\n\n`;
82
82
  md += `## Directory layout\n\n`;
83
83
  md += `- **\`core/\`** - ${counts.core} \`multi-agent*\` orchestration skills that are pipeline-critical. Edits here are core-code changes.\n`;
84
- md += `- **\`external/\`** - ${counts.external} iOS / Android / generic skills imported from the upstream skill library. Mirrors of third-party guidance.\n`;
84
+ md += `- **\`external/\`** - ${counts.external} iOS / Android / generic skills that ship into the stack plugins. Each names its origin in \`metadata.source\`: \`multi-agent-pipeline\` when written here, or the upstream and license a \`NOTICE-*.md\` in this directory covers.\n`;
85
85
  md += `- Install destinations (ADR-0009): Claude Code gets NO local copy of \`external/\` - it loads those skills from the \`multi-agent-plugins\` marketplace, namespaced (\`ai-<stack>-toolkit:<name>\`); only the two compliance catalogs from \`core/\` land in \`~/.claude/skills/\`. Copilot CLI and Codex CLI receive a flat copy filtered to the enabled stacks. \`external/\` remains the single authoring source that \`build-stack-plugins.mjs\` publishes from.\n\n`;
86
86
  md += `Source layout is logical grouping only - skill discovery at runtime is unchanged.\n\n`;
87
87
  md += `## Categories\n\n`;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-09-26T13:39:28Z",
3
+ "generatedAt": "2026-09-26T16:00:24Z",
4
4
  "skillCount": 218,
5
5
  "entries": [
6
6
  {
@@ -265,7 +265,7 @@
265
265
  },
266
266
  {
267
267
  "path": "shared/external/agent-introspection-debugging/SKILL.md",
268
- "sha256": "7a93e115f86092408d0b653968b396276243b49c5dc1543f7c2689c861719767"
268
+ "sha256": "8506e5cfede72a7d59ae79f108608e84054617c43a9101692a7e97fcea1a5d0a"
269
269
  },
270
270
  {
271
271
  "path": "shared/external/alarmkit/SKILL.md",
@@ -273,7 +273,7 @@
273
273
  },
274
274
  {
275
275
  "path": "shared/external/android-architecture/SKILL.md",
276
- "sha256": "5a3b13a2376378ce4977d1df14003a8f65e2d1ef1561ae8c40f10e3e1759c204"
276
+ "sha256": "71f6af966558767378d0605fae9a280fdf05eeba3379835170ee4a274f1846a4"
277
277
  },
278
278
  {
279
279
  "path": "shared/external/android-build-quality-gates/SKILL.md",
@@ -297,11 +297,11 @@
297
297
  },
298
298
  {
299
299
  "path": "shared/external/android-performance/SKILL.md",
300
- "sha256": "5cb7429516fbaccee318af0e3071df631c56381b6857ef4bbd921eb213adef64"
300
+ "sha256": "1e578cbb63244d461eb3a5ad78d2cff675eb3a5a18a5b5ddb7da60bdbe2d6391"
301
301
  },
302
302
  {
303
303
  "path": "shared/external/android-security/SKILL.md",
304
- "sha256": "9d528fbed56fb1b40a34015bbd16b818a4ccccae61e0ab667ad9436efc4ccafa"
304
+ "sha256": "43c5ef4c6367eb1349b07673fbd3b0bf6922d7c3a2eff18edc48c5c74499bf92"
305
305
  },
306
306
  {
307
307
  "path": "shared/external/api-patterns/SKILL.md",
@@ -353,7 +353,7 @@
353
353
  },
354
354
  {
355
355
  "path": "shared/external/backlog/SKILL.md",
356
- "sha256": "abb3b1d9f0efa8413ea73fc969c22caeadfa8f02d0d9f5395259befccdcda7ea"
356
+ "sha256": "f48d35654410bb800ab477c87b7ce6db8e758671cbb733c36429d8435b7d250f"
357
357
  },
358
358
  {
359
359
  "path": "shared/external/callkit-voip/SKILL.md",
@@ -361,7 +361,7 @@
361
361
  },
362
362
  {
363
363
  "path": "shared/external/ci-cd-pipelines/SKILL.md",
364
- "sha256": "8776746817fea8f67bd12354822f674473fdad7018078766e420cef724b086fc"
364
+ "sha256": "753a90d54c392d0a120c4e36ab34d7a43f9e0fe63609e65154c9c1da6d824763"
365
365
  },
366
366
  {
367
367
  "path": "shared/external/clean-code/SKILL.md",
@@ -373,15 +373,15 @@
373
373
  },
374
374
  {
375
375
  "path": "shared/external/compose-components/SKILL.md",
376
- "sha256": "756e0c44643b0688295bd8b896f12dd37f7c30447b3e3a4e08223dfd74f9473e"
376
+ "sha256": "03ad58d5552b37480978462907539fe1070eeafce80a2a3c943d1c3880983f3f"
377
377
  },
378
378
  {
379
379
  "path": "shared/external/compose-navigation/SKILL.md",
380
- "sha256": "2b2ca56d7f61f334cc9089483597453dd16b67378e2f8fa9b3c440fd89cf91e8"
380
+ "sha256": "5be0bc654b17eb1c81b44ca2eb5273be4e935f6f59043c54157041a0a18926b5"
381
381
  },
382
382
  {
383
383
  "path": "shared/external/compose-testing/SKILL.md",
384
- "sha256": "002c9420e063defc5cea13e59a4146bfb4e96075f2e5acb19aaa14bd215c6564"
384
+ "sha256": "e20c1c3e281778f5a11bbed04d4d42e9ba1c23a857b32d34a98806ed695e2c50"
385
385
  },
386
386
  {
387
387
  "path": "shared/external/contacts-framework/SKILL.md",
@@ -413,7 +413,7 @@
413
413
  },
414
414
  {
415
415
  "path": "shared/external/council/SKILL.md",
416
- "sha256": "3556c03e41605785e4dad4e450511043e9c399100cc470587021359bae66e837"
416
+ "sha256": "6d69ba7de8cbfa06f94f551601b5517c91350f6dd09901df68acf979d3803134"
417
417
  },
418
418
  {
419
419
  "path": "shared/external/cryptokit/SKILL.md",
@@ -421,11 +421,11 @@
421
421
  },
422
422
  {
423
423
  "path": "shared/external/css-modern/SKILL.md",
424
- "sha256": "355a6bb67131dcf52cf51fc4fb015ada15705234f5ca5f03124f25cc916b0d4d"
424
+ "sha256": "911a7f371b24ef43790568e358a941f8ff67c8cb6fa57b5daa1a388964d03310"
425
425
  },
426
426
  {
427
427
  "path": "shared/external/database-patterns/SKILL.md",
428
- "sha256": "948044e98af068c315cfc1649f6f7769767a0c43f5f2e3ce3b04c2715d94f98b"
428
+ "sha256": "1551a9a5d505fd99cb1a618cfe6d64ade566f2935f09fec6d986274f1ddba98b"
429
429
  },
430
430
  {
431
431
  "path": "shared/external/debugging-instruments/SKILL.md",
@@ -453,11 +453,11 @@
453
453
  },
454
454
  {
455
455
  "path": "shared/external/evidence-github/SKILL.md",
456
- "sha256": "9cc24e73cb8b66a7495567f83df4bca932d90c1de4dbf3b97b1dd59378dbb75b"
456
+ "sha256": "cdcd157ecb3579b0a664716b4f6099a17d43361157c28124e44622afb5b1af68"
457
457
  },
458
458
  {
459
459
  "path": "shared/external/evidence-registry/SKILL.md",
460
- "sha256": "97d4cceb1a8c52ae15597312c14c54d84b6b55ab9fb007e1a203492c4bf1b046"
460
+ "sha256": "139a98ede546d2ac60e71ffa0b571fda714d0f5c266e248b3e527265c340ae37"
461
461
  },
462
462
  {
463
463
  "path": "shared/external/fastapi-pro/SKILL.md",
@@ -473,7 +473,7 @@
473
473
  },
474
474
  {
475
475
  "path": "shared/external/gradle-kotlin-dsl/SKILL.md",
476
- "sha256": "b0eb32ef4fece08d58e89eebb20e906646be9525ae86261f4c02dd8e4acfb9c3"
476
+ "sha256": "af7b1e30e2448f43b5100b2a935bbaadde86ccd490844c901736c9270f8cc3ce"
477
477
  },
478
478
  {
479
479
  "path": "shared/external/healthkit/SKILL.md",
@@ -521,11 +521,11 @@
521
521
  },
522
522
  {
523
523
  "path": "shared/external/html-semantic/SKILL.md",
524
- "sha256": "00c19304fb6195069d8fd42fe2ead8aeb03e9d01845bc17df17100cd814c829a"
524
+ "sha256": "43e05d6bf99d59fda858cef3c8c4837ae17e91826ffd1cd517612300cafff739"
525
525
  },
526
526
  {
527
527
  "path": "shared/external/humanizer/SKILL.md",
528
- "sha256": "febdbb9843f6e5606d5f5aa9faa556edbc7a5fc387fc85a80aaa831789ea0092"
528
+ "sha256": "25097784b1724423aebb35fcee60ba6c458a4ff5aa2bb7f45eccfc810a63a192"
529
529
  },
530
530
  {
531
531
  "path": "shared/external/ios-accessibility/SKILL.md",
@@ -533,7 +533,7 @@
533
533
  },
534
534
  {
535
535
  "path": "shared/external/ios-coding-standard/SKILL.md",
536
- "sha256": "e70a537cf4dd26fd9537d85bd997eaff307b7b2c26ec7004e88aa82c945cd17f"
536
+ "sha256": "43a0e7d7c87b6abc9db15c38be5984e79e551bc5d7957394ad802ba50ea3b713"
537
537
  },
538
538
  {
539
539
  "path": "shared/external/ios-debugger-agent/SKILL.md",
@@ -545,7 +545,7 @@
545
545
  },
546
546
  {
547
547
  "path": "shared/external/ios-module-structure/SKILL.md",
548
- "sha256": "3a79c225026be7aaf8302be0c9bdf3cce1d54ac445c8a5085b6845a4f26c4a83"
548
+ "sha256": "abb85b305ffeb1f3cd5015fe630311b22a6914c88c59b8d4b71691496235f7b9"
549
549
  },
550
550
  {
551
551
  "path": "shared/external/ios-networking/SKILL.md",
@@ -553,7 +553,7 @@
553
553
  },
554
554
  {
555
555
  "path": "shared/external/ios-security/SKILL.md",
556
- "sha256": "691c1bcc74e7e6445a4786c6ce7e94e5706d8dea725423e68089d37e1cfc7dc4"
556
+ "sha256": "48924d4faea93fdf435851cbc77ba26cb33f3f8256954787af539f410f64d5c0"
557
557
  },
558
558
  {
559
559
  "path": "shared/external/ios-simulator/SKILL.md",
@@ -569,7 +569,7 @@
569
569
  },
570
570
  {
571
571
  "path": "shared/external/localization-reuse-map/SKILL.md",
572
- "sha256": "26ace50f907bc0c25afc323387e79d2eeaacc998c93b50456a5dab2ddc146152"
572
+ "sha256": "565fa80ffa729f49cb4a54fb8f1da98397de5aaf7fb308753d261b5dc9f51f46"
573
573
  },
574
574
  {
575
575
  "path": "shared/external/macos-menubar-tuist-app/SKILL.md",
@@ -601,7 +601,7 @@
601
601
  },
602
602
  {
603
603
  "path": "shared/external/nextjs-app-router/SKILL.md",
604
- "sha256": "6fa24c3362f2b84c0e57390aac7e3c9e9dc69e9a937d260feb55584e5f224731"
604
+ "sha256": "a6948eb7d1feb1940b222e671d092c8e56e105dc580f009143ea863f0130922e"
605
605
  },
606
606
  {
607
607
  "path": "shared/external/nodejs-backend-patterns/SKILL.md",
@@ -633,7 +633,7 @@
633
633
  },
634
634
  {
635
635
  "path": "shared/external/play-store-review/SKILL.md",
636
- "sha256": "30694b29888502dfa3a18626732f5b590f810d871a8ca1ffed136369e362993d"
636
+ "sha256": "8cfe6ac9c1c078089b92252f1600917f77b01dba80ae7e55f2fd347c409f64e1"
637
637
  },
638
638
  {
639
639
  "path": "shared/external/push-notifications/SKILL.md",
@@ -641,11 +641,11 @@
641
641
  },
642
642
  {
643
643
  "path": "shared/external/python-patterns/SKILL.md",
644
- "sha256": "0e7af701790a10dcde9ef2d23f9b4f13a2658b400b093c08c2fda0c7b91b3071"
644
+ "sha256": "debcbd749acabf8f947b2e0bd1ae52126fdb0263f347b32b69281e6811f2cf99"
645
645
  },
646
646
  {
647
647
  "path": "shared/external/react-best-practices/SKILL.md",
648
- "sha256": "c563e28cd54a07301b69147ab421999f67145c8e3989eccc7c2a116506749c0d"
648
+ "sha256": "6a629cefd6ed3186fbd475df3eef3ffaa0ebeaa62eb6a30c0af5f99b53fe7950"
649
649
  },
650
650
  {
651
651
  "path": "shared/external/realitykit-ar/SKILL.md",
@@ -653,19 +653,19 @@
653
653
  },
654
654
  {
655
655
  "path": "shared/external/rest-api-design/SKILL.md",
656
- "sha256": "97ff96b96ca400bdb0a45c66e825afa4fded9230349972c1a4c1a61690f473b1"
656
+ "sha256": "23b6f35b17680b0e42af6123f063140e3a853d2b7847d4445fe6ddbd0a48f5e1"
657
657
  },
658
658
  {
659
659
  "path": "shared/external/retrofit-networking/SKILL.md",
660
- "sha256": "9550ba78f34440019fa030a74ba42f8402fa2c8d9858fc2c9d805f2bfe641bb3"
660
+ "sha256": "b3991cb24b790e6bc159c9082ff21c6a276ceb0e7516f53111ecb6c5dd4094f0"
661
661
  },
662
662
  {
663
663
  "path": "shared/external/room-database/SKILL.md",
664
- "sha256": "0cb50a75676df1e3e5e3f68781d9d5bede06d4ae8156266dac41ad7ed94705fd"
664
+ "sha256": "45fe377469f1fb4036431194d3b525d3caaa79231808625f643468863c6e814a"
665
665
  },
666
666
  {
667
667
  "path": "shared/external/search-first/SKILL.md",
668
- "sha256": "02310dc0325efe94cdb3d3c20ccb3f75558550f7798b71d1abcbfe8665d43eed"
668
+ "sha256": "c9d5ffb698bbfb76a89da6a35dfc0f1d72a31d2b4a0e9e9f3e027be7a8fddfde"
669
669
  },
670
670
  {
671
671
  "path": "shared/external/security-review/SKILL.md",
@@ -677,11 +677,11 @@
677
677
  },
678
678
  {
679
679
  "path": "shared/external/signal-community/SKILL.md",
680
- "sha256": "7d1b3030b3c139932cf983a200c82500800a2fa0a837c955ccda2d4f9c1ee63f"
680
+ "sha256": "0660107c2bf0e65847e72708a196b672ae7b9469bd98ec70793c988351024298"
681
681
  },
682
682
  {
683
683
  "path": "shared/external/skill-creator/SKILL.md",
684
- "sha256": "edba3e08babf6993090edc4b8f3309c43e5a786864d4267b46620fac5297f241"
684
+ "sha256": "f80c5f74dc285240d0213a4e6e0c178a9f38142f0eb7d6956d7c89c061009b71"
685
685
  },
686
686
  {
687
687
  "path": "shared/external/speech-recognition/SKILL.md",
@@ -813,11 +813,11 @@
813
813
  },
814
814
  {
815
815
  "path": "shared/external/tailwind-css/SKILL.md",
816
- "sha256": "2b71f2cf0f82292cf0ff9459378ea32faf8bb36cfa9193e3d8451ce1bec7ed4e"
816
+ "sha256": "9eda0a871962f52e381781b95c948128626984a82ddbd47be53ea869cd250b7e"
817
817
  },
818
818
  {
819
819
  "path": "shared/external/testing-backend/SKILL.md",
820
- "sha256": "5f4c8d5b7e630b640e737aa73bfd0912a9d395ad62004d067ad2b6fdadf5d6ef"
820
+ "sha256": "d3eea1c6d1e2a40a0b66bc6460194ee313e17fc2af8f75047030b7840c2db857"
821
821
  },
822
822
  {
823
823
  "path": "shared/external/tipkit/SKILL.md",
@@ -825,7 +825,7 @@
825
825
  },
826
826
  {
827
827
  "path": "shared/external/typescript-patterns/SKILL.md",
828
- "sha256": "45aea58d2f405f584358a73a71aff12d92410f29c50f38d6e57a41b9fd70214c"
828
+ "sha256": "784d294aa6ba09ff29bc7ec0f106eb512a006e79c96a01ec92d1699bfa122077"
829
829
  },
830
830
  {
831
831
  "path": "shared/external/vision-framework/SKILL.md",
@@ -833,7 +833,7 @@
833
833
  },
834
834
  {
835
835
  "path": "shared/external/vue-composition/SKILL.md",
836
- "sha256": "13468da149715aa2127a1b9fbcaa9a92fee5033107598a4e46b4635b0b11e349"
836
+ "sha256": "429115ba7c4fdecd134e9ea546840d6341312d348f359a8bf35690cd113c1201"
837
837
  },
838
838
  {
839
839
  "path": "shared/external/weatherkit/SKILL.md",
@@ -841,15 +841,15 @@
841
841
  },
842
842
  {
843
843
  "path": "shared/external/web-accessibility/SKILL.md",
844
- "sha256": "9e7f6371f8bc691ba6a385385d0e3dd3c1e4ec94976cbe34adcc297db23852b5"
844
+ "sha256": "a1cd782292982a3c37fd8d1eedaae85f860886f492b2666b73735c6261025594"
845
845
  },
846
846
  {
847
847
  "path": "shared/external/web-performance/SKILL.md",
848
- "sha256": "53ef0855f094f214dd57aa24bc20ff30e1f2d75860dd5b9530569d5963920e03"
848
+ "sha256": "b9983bb39f9a65daad5aca4fb97c88ecbd7c0639b39023dc5c7c6784c4c1c868"
849
849
  },
850
850
  {
851
851
  "path": "shared/external/web-testing/SKILL.md",
852
- "sha256": "f5ba76d7bdd45b8f8a1e6953e3ede67e95cde29487ce4d63d8acda479e954119"
852
+ "sha256": "3120db537a687adfbf396e500f4e146880e4b1a00ab339f85ab526853c947447"
853
853
  },
854
854
  {
855
855
  "path": "shared/external/widgetkit/SKILL.md",
@@ -7,7 +7,7 @@ Single source of truth for skills delivered to both Claude Code (`~/.claude/skil
7
7
  ## Directory layout
8
8
 
9
9
  - **`core/`** - 64 `multi-agent*` orchestration skills that are pipeline-critical. Edits here are core-code changes.
10
- - **`external/`** - 154 iOS / Android / generic skills imported from the upstream skill library. Mirrors of third-party guidance.
10
+ - **`external/`** - 154 iOS / Android / generic skills that ship into the stack plugins. Each names its origin in `metadata.source`: `multi-agent-pipeline` when written here, or the upstream and license a `NOTICE-*.md` in this directory covers.
11
11
  - Install destinations (ADR-0009): Claude Code gets NO local copy of `external/` - it loads those skills from the `multi-agent-plugins` marketplace, namespaced (`ai-<stack>-toolkit:<name>`); only the two compliance catalogs from `core/` land in `~/.claude/skills/`. Copilot CLI and Codex CLI receive a flat copy filtered to the enabled stacks. `external/` remains the single authoring source that `build-stack-plugins.mjs` publishes from.
12
12
 
13
13
  Source layout is logical grouping only - skill discovery at runtime is unchanged.
@@ -7,6 +7,7 @@ description: |
7
7
  progress, tool calls keep erroring, or you are about to retry without a new
8
8
  hypothesis.
9
9
  metadata:
10
+ source: multi-agent-pipeline
10
11
  version: 1.0.0
11
12
  ---
12
13
 
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: android-architecture
3
3
  description: "Design and implement Clean Architecture with multi-module structure on Android. Covers domain/data/presentation layers, Hilt dependency injection with @Module/@Provides/@Binds, UseCase pattern with operator invoke, Repository pattern with Kotlin Flow, and mapper pattern between layers. Use when structuring a new Android project, adding feature modules, setting up DI, or reviewing architecture compliance."
4
+ metadata:
5
+ source: multi-agent-pipeline
4
6
  ---
5
7
 
6
8
  # Android Clean Architecture
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: android-performance
3
3
  description: "Optimize Android app performance with Baseline Profiles for startup, Compose stability annotations (@Stable, @Immutable, strong skipping), recomposition debugging (Layout Inspector, recomposition counts), R8 optimization, LeakCanary memory leak detection, Macrobenchmark startup tracing, Coil image loading best practices, and LazyColumn/LazyGrid key-based performance. Use when diagnosing slow startup, janky scrolling, excessive recomposition, memory leaks, or optimizing release builds."
4
+ metadata:
5
+ source: multi-agent-pipeline
4
6
  ---
5
7
 
6
8
  # Android Performance