@mmerterden/multi-agent-pipeline 20.5.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 (81) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +10 -0
  3. package/docs/facts.json +5 -4
  4. package/install/_dev-only-files.mjs +1 -0
  5. package/manifest.json +84 -82
  6. package/package.json +4 -3
  7. package/pipeline/lib/confusables.json +100 -0
  8. package/pipeline/lib/normalize-text.mjs +48 -0
  9. package/pipeline/lib/outbound-gate.mjs +10 -1
  10. package/pipeline/lib/redact.mjs +4 -1
  11. package/pipeline/lib/vercel-deploy.sh +5 -7
  12. package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
  13. package/pipeline/scripts/_notices.mjs +11 -0
  14. package/pipeline/scripts/agent-guard.py +30 -1
  15. package/pipeline/scripts/gen-skills-index.mjs +1 -1
  16. package/pipeline/scripts/pre-commit-check.sh +59 -16
  17. package/pipeline/scripts/pre-push-check.sh +3 -3
  18. package/pipeline/scripts/run-ui-tests.sh +5 -5
  19. package/pipeline/scripts/website-deploy-commit.sh +3 -2
  20. package/pipeline/skills/.skill-manifest.json +39 -39
  21. package/pipeline/skills/shared/README.md +1 -1
  22. package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
  23. package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
  24. package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
  25. package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
  26. package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
  27. package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
  28. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
  29. package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
  30. package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
  31. package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
  32. package/pipeline/skills/shared/external/council/SKILL.md +1 -0
  33. package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
  34. package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
  35. package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
  36. package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
  37. package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
  38. package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
  39. package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
  40. package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
  41. package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
  42. package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
  43. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
  44. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
  45. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
  46. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
  47. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
  48. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
  49. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
  50. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
  51. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
  52. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
  53. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
  54. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
  55. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
  56. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
  57. package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
  58. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
  59. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
  60. package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
  61. package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
  62. package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
  63. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
  64. package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
  65. package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
  66. package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
  67. package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
  68. package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
  69. package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
  70. package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
  71. package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
  72. package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
  73. package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
  74. package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
  75. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
  76. package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
  77. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
  78. package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
  79. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
  80. package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
  81. package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
@@ -174,6 +174,19 @@ scan_file() {
174
174
 
175
175
  [ -z "$content" ] && return 0
176
176
 
177
+ # A token written with an invisible character or a look-alike letter: scan a
178
+ # folded copy too. Only non-ASCII content pays for the node call.
179
+ if printf '%s' "$content" | LC_ALL=C grep -q '[^ -~[:space:]]' 2>/dev/null \
180
+ && command -v node >/dev/null 2>&1 \
181
+ && [ -f "$PRE_COMMIT_DIR/../lib/normalize-text.mjs" ]; then
182
+ local folded
183
+ folded=$(printf '%s' "$content" | node "$PRE_COMMIT_DIR/../lib/normalize-text.mjs" 2>/dev/null) || folded=""
184
+ if [ -n "$folded" ] && [ "$folded" != "$content" ]; then
185
+ content="$content
186
+ $folded"
187
+ fi
188
+ fi
189
+
177
190
  # API keys / tokens (key = "long_string" pattern)
178
191
  if echo "$content" | grep -qiE '(api[_-]?key|api[_-]?secret|access[_-]?token|auth[_-]?token|secret[_-]?key)\s*[:=]\s*["'"'"'][A-Za-z0-9+/=_-]{20,}'; then
179
192
  echo "BLOCKED: Possible API key/token in $file" >&2
@@ -261,28 +274,58 @@ scan_file() {
261
274
  # repo-root-relative, so the full path can be anchored.
262
275
  if ! echo "$file" | grep -qiE '(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|Podfile\.lock|Cartfile\.resolved|Package\.resolved|\.lock$|\.map$|__snapshots__|\.snap$|\.min\.(js|css)$)' \
263
276
  && ! echo "$file" | grep -qE '^pipeline/scripts/smoke-pre-commit\.sh$'; then
264
- candidates=$(echo "$content" | grep -oE '[A-Za-z0-9+/=_-]{40,}' || true)
277
+ # Staged and working-tree content arrives as diff lines, so the leading "+"
278
+ # is stripped first: it is in the candidate class and would otherwise glue
279
+ # onto a token that starts at column 0 and defeat every shape check below.
280
+ candidates=$(echo "$content" | sed 's/^+//' | grep -oE '[A-Za-z0-9+/=_-]{40,}' || true)
265
281
  if [ -n "$candidates" ]; then
266
282
  entropy_hit=$(printf '%s\n' "$candidates" | awk '
283
+ # Word-shaped identifier: letters and _ or - only, split into segments at
284
+ # separators and case boundaries (UIApplication -> UI, Application), where
285
+ # the segments read like words: average length 4+, none longer than 24,
286
+ # and at least 70 percent carrying a vowel. Random letters-only tokens
287
+ # flip case every one or two characters, so their segments average about
288
+ # two characters with few vowels; a long lowercase run is one oversized
289
+ # segment. Neither shape passes.
290
+ function wordlike(t, n, i, c, p, nx, seg, nseg, total, maxlen, voweled, split_here) {
291
+ if (t !~ /^[A-Za-z_-]+$/) return 0;
292
+ n = length(t); seg = ""; nseg = 0; total = 0; maxlen = 0; voweled = 0;
293
+ for (i = 1; i <= n + 1; i++) {
294
+ c = (i <= n) ? substr(t, i, 1) : "_";
295
+ split_here = 0;
296
+ if (c == "_" || c == "-") split_here = 1;
297
+ else if (seg != "" && c ~ /[A-Z]/) {
298
+ p = substr(seg, length(seg), 1);
299
+ nx = (i < n) ? substr(t, i + 1, 1) : "";
300
+ if (p ~ /[a-z]/ || (nx ~ /[a-z]/ && length(seg) > 1)) split_here = 1;
301
+ }
302
+ if (split_here && seg != "") {
303
+ nseg++; total += length(seg);
304
+ if (length(seg) > maxlen) maxlen = length(seg);
305
+ if (tolower(seg) ~ /[aeiouy]/) voweled++;
306
+ seg = "";
307
+ }
308
+ if (c != "_" && c != "-") seg = seg c;
309
+ }
310
+ if (nseg == 0) return 0;
311
+ return (total / nseg >= 4 && maxlen <= 24 && voweled * 10 >= nseg * 7);
312
+ }
267
313
  {
268
314
  s=$0;
269
315
  # Scoring the joined string measures the variety of a whole SENTENCE
270
316
  # rather than of any token in it, so an ordinary doc path like
271
- # "claude/commands/multi-agent/review-jira/SKILL" scores 4.35 and was
272
- # blocked as a possible credential. 47 of the 400 committed markdown
273
- # files in this repo carried such a path, so each was un-editable - and
274
- # the gate only fired once such a file was staged, which is why it
275
- # stayed invisible.
317
+ # "claude/commands/multi-agent/review-jira/SKILL" scores 4.35 and would
318
+ # be blocked as a possible credential, making every doc that cites
319
+ # such a path un-editable.
276
320
  #
277
- # The reduction is applied ONLY to path-shaped candidates. An earlier
278
- # version of this fix scored the longest slash-free segment for every
279
- # candidate containing a slash, which structurally exempted any secret
280
- # with a slash in it: the canonical 40-char AWS documentation-example
281
- # secret access key (two slashes, full-match H=4.663, blocked before)
282
- # reduced to an 18-char segment and sailed through, and roughly half
283
- # of `openssl rand -base64 32` outputs contain a "/". It is not
284
- # reproduced here on purpose - this gate flags credential-shaped
285
- # strings in comments too, and it is right to.
321
+ # The reduction is applied ONLY to path-shaped candidates. Scoring the
322
+ # longest slash-free segment for every candidate containing a slash
323
+ # would structurally exempt any secret with a slash in it: the
324
+ # canonical 40-char AWS documentation-example secret access key (two
325
+ # slashes, full-match H=4.663) reduces to an 18-char segment, and
326
+ # roughly half of `openssl rand -base64 32` outputs contain a "/". The
327
+ # key is not reproduced here on purpose - this gate flags
328
+ # credential-shaped strings in comments too, and it is right to.
286
329
  # No other check here catches that key: the key-name regex above does
287
330
  # not match "secret_access_key", and the AKIA pattern only covers the
288
331
  # key ID, not the secret.
@@ -299,7 +342,7 @@ scan_file() {
299
342
  if (s ~ /^[0-9]+$/) next; # pure digits
300
343
  if (s ~ /^[0-9a-f]+$/) next; # lowercase hex (git sha / md5 / sha-*)
301
344
  if (s ~ /^[0-9A-F]+$/) next; # uppercase hex
302
- if (s ~ /^([A-Z][a-z]+)+[A-Z]*$/) next; # CamelCase words only (label key / type name), never a credential
345
+ if (wordlike(s)) next; # identifier made of words (plist key / type name), never a credential
303
346
  delete freq;
304
347
  for (i = 1; i <= n; i++) { c = substr(s, i, 1); freq[c]++ }
305
348
  H = 0;
@@ -21,9 +21,9 @@
21
21
  #
22
22
  # Two modes, because a gate that runs INSIDE the push is a gate that breaks
23
23
  # pushes. Git opens the connection to the remote before this hook fires, so a
24
- # six-minute run idles that connection until the server drops it: the first two
25
- # attempts to push the v15.12.0 rename died on a broken pipe with every gate
26
- # green. The work has to happen outside the network window.
24
+ # six-minute run idles that connection until the server drops it, and the push
25
+ # dies on a broken pipe with every gate green. The work has to happen outside
26
+ # the network window.
27
27
  #
28
28
  # pre-push-check.sh --run run every gate and stamp the tree as green
29
29
  # pre-push-check.sh verify the stamp only; refuse the push if absent
@@ -277,11 +277,11 @@ EOF
277
277
  fi
278
278
  }
279
279
 
280
- # Web had no arm here at all until v17.1.0, which meant a repo with a full
281
- # Playwright suite reported "no UI test target" and every downstream consumer
282
- # believed it: the evidence probe closed tier 1, the PR body said UI tests were
283
- # not run, and the reason it gave was true of the runner rather than of the repo.
284
- # That is the failure mode this file exists to avoid, and it was shipped for web.
280
+ # Without a web arm, a repo with a full Playwright suite reports "no UI test
281
+ # target" and every downstream consumer believes it: the evidence probe closes
282
+ # tier 1, the PR body says UI tests were not run, and the reason it gives is
283
+ # true of the runner rather than of the repo. That is the failure mode this file
284
+ # exists to avoid.
285
285
  web_spec_files() {
286
286
  find "$REPO" \
287
287
  -name ".*" -type d -prune -o \
@@ -7,8 +7,9 @@
7
7
  # refuses to build a commit whose author is not a contributor on the project. The
8
8
  # push still succeeds, the deployment is created and sits at UNKNOWN with a 0ms
9
9
  # build (API `readyState: BLOCKED`), and the live site keeps serving the previous
10
- # version. v16.4.0 and v16.5.0 were both pushed that way and neither was built,
11
- # while the sync reported the website as synced both times.
10
+ # version. A successful push is therefore not evidence of a deploy, so the script
11
+ # pins the author before committing and reads the deployment state back after
12
+ # pushing instead of reporting the website as synced on the push alone.
12
13
  #
13
14
  # Usage:
14
15
  # website-deploy-commit.sh <identity-name> <identity-email> <version> [repo-dir]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-09-25T16:25:54Z",
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
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: android-security
3
3
  description: "Secure Android apps with ProGuard/R8 obfuscation, OkHttp certificate pinning, BiometricPrompt authentication, EncryptedSharedPreferences, Play Integrity API, root detection, secure network communication, and API key protection via local.properties and BuildConfig. Use when implementing security features, auditing app security, handling sensitive data, or preparing for production release."
4
+ metadata:
5
+ source: multi-agent-pipeline
4
6
  ---
5
7
 
6
8
  # Android Security
@@ -1,6 +1,6 @@
1
1
  # Backlog
2
2
 
3
- Deferred-but-approved work, kept whole. Entries move `deferred` -> `ready` -> `in-progress` -> `done` and are never deleted. The full spec travels verbatim from when the job was deferred.
3
+ Deferred-but-approved work, kept whole. Entries move `deferred` -> `ready` -> `in-progress` -> `done`. An entry leaves only when a re-audit finds its subject gone, or when it is done and its lesson lives in the skill or doc that owns that area. The full spec travels verbatim from when the job was deferred.
4
4
 
5
5
  ## Ready
6
6
 
@@ -1,54 +1,77 @@
1
1
  ---
2
2
  name: backlog
3
- description: "The engineering backlog registry for deferred-but-approved work: each deferred job lands here with its spec, origin and unblock condition. Use when the user says 'defer it', 'add it to the list', 'later' or 'not now', asks what is on the backlog, says 'pick up {id}', or completes an item. BACKLOG.md is the registry; entries move deferred, ready, in-progress, done, and a re-audit deletes rotted ones."
3
+ description: "Registry and routine for approved but postponed engineering work: each item keeps its full spec, origin and unblock condition, and moves through deferred, ready, in-progress and done. Use when the user postpones work ('later', 'not now', 'put it on the list', 'backlog this'), asks what is on the backlog or still owed, works the backlog, picks up an item by id or the next one, finishes an item, or when a rename, a deleted subject or a doubted claim calls for a re-audit. Not for Jira or GitHub tickets, and never for summarising or rewriting a deferred spec."
4
4
  user-invocable: true
5
5
  argument-hint: [list | add | pick <id> | done <id> | re-audit]
6
6
  allowed-tools: Read, Grep, Glob, Edit, Write
7
7
  metadata:
8
8
  version: 1.0.0
9
+ source: multi-agent-pipeline
9
10
  ---
10
11
 
11
- # backlog - deferred work, kept whole
12
+ # backlog - postponed work without context loss
12
13
 
13
- > **Layer:** workflow - the deterministic registry routine for deferred jobs.
14
- > **Bundled:** [BACKLOG.md](BACKLOG.md) - the registry. The heart of this skill.
15
- > **Iron rule:** moving a job onto this list is a MOVE, never a rewrite - the FULL spec
16
- > travels verbatim. A compressed one-liner is a loss; the point of the backlog is that
17
- > deferring costs nothing later. The registry stays honest in the other direction too:
18
- > entries are re-audited against live code, and an entry whose named types or premises
19
- > no longer exist is DELETED, never left readable as live.
14
+ > **Layer:** workflow in practice: a fixed routine over one registry file.
15
+ > **Registry:** [BACKLOG.md](BACKLOG.md), bundled with this skill. Every operation below reads or edits it.
20
16
 
21
- ## When to load
17
+ ## Why it exists
18
+ Work that gets postponed as a single line tends to die there. By the time someone returns to it, the reasoning, the constraints and the edge cases are gone, and the job is either re-derived from scratch or quietly dropped. This registry pays the cost of "later" once, at the moment of deferral, by storing the job exactly as it was understood then.
22
19
 
23
- - The user defers work: "defer it", "add it to the list", "later", "not now", "backlog this".
24
- - The user asks about it: "what's on the backlog", "what's on the list", "what's owed".
25
- - The user works it: "work the backlog", "pick up <id>", "do the next one".
26
- - An item completes: mark it done, and retire the record once what it taught has a home.
27
- - A staleness signal arrives (a rename, a deleted subject, a doubted claim): re-audit.
20
+ ## Two rules
21
+ 1. **Deferral moves the spec; it does not edit it.** The full description goes into the entry word for word. Shortening it to one line is data loss, even when the line reads well.
22
+ 2. **The registry must stay true.** Entries are checked against the live code. One whose named types, files or premises have disappeared is deleted, not kept around looking actionable.
28
23
 
29
- ## The registry contract
24
+ ## Entry fields
25
+ | Field | Content |
26
+ |---|---|
27
+ | `id` | short, stable kebab-case slug, assigned when the entry is added and never changed |
28
+ | `title` | one line |
29
+ | `state` | `deferred`, `ready`, `in-progress` or `done` |
30
+ | `origin` | the task, PR, review finding or conversation that produced the job |
31
+ | `spec` | the complete description, verbatim, as a block literal; never a summary |
32
+ | `unblock` | the dependency, decision or date that makes it actionable |
33
+
34
+ The file layout (sections Ready, Deferred, In progress, Done, and the entry template) is fixed in `BACKLOG.md`: each item is a heading with its id and title, followed by bullets for state, origin, unblock and spec.
30
35
 
31
- Every entry in `BACKLOG.md` carries, verbatim:
36
+ ## State machine
37
+ `deferred` -> `ready` -> `in-progress` -> `done`. States only move forward.
32
38
 
33
- - **id** - short stable slug (`kebab-case`), assigned on add.
34
- - **title** - one line.
35
- - **state** - `deferred` -> `ready` -> `in-progress` -> `done`. Entries move forward; they leave the registry only by the two rules below (rot, or a re-homed done record), never by being quietly rewritten.
36
- - **origin** - where it came from (the task/PR/finding/conversation that spawned it).
37
- - **spec** - the FULL description, verbatim from when it was deferred. Not a summary.
38
- - **unblock** - the condition that makes it actionable (a dependency, a decision, a date). `deferred` items without an unblock condition are just `ready`.
39
+ An entry marked `deferred` with no unblock condition is not waiting for anything, so it is `ready`.
39
40
 
40
- Prefer an append-only markdown table or section list in `BACKLOG.md`; never overwrite an entry's spec on a state change - only its `state` line moves.
41
+ Storage is append-only in spirit: when the state changes, only the state line (and the section the entry sits under) changes. The spec is never overwritten.
41
42
 
42
43
  ## Operations
43
44
 
44
- | Command | Action |
45
- |---|---|
46
- | `list` | Show entries grouped by state (ready first, then deferred, then in-progress; done collapsed). |
47
- | `add` | Capture the deferred job with its full spec + origin + unblock condition. Assign an id. |
48
- | `pick <id>` | Move `ready`/`deferred` -> `in-progress`; surface the full spec so work resumes with zero context loss. |
49
- | `done <id>` | Move -> `done` with the evidence (PR/commit + date). The record RETIRES from the registry once what it taught is written into the skill or doc that owns it - git history is the archive of what was owed and delivered. A done entry kept past that point is a second place for the same truth to rot. |
50
- | `re-audit` | Verify every entry's named types, paths and claims against LIVE code (binary-safe: `LC_ALL=C grep -a`, so a repo with binary blobs does not silently return nothing). A subject that no longer exists deletes its entry; a changed fact restates it. **Numbers move by measurement, never by edit** - a count adjusted to match an impression reads as evidence and is worse than no count. |
45
+ ### `list`
46
+ Group entries by state in the order ready, deferred, in-progress. Show done entries collapsed, as a count or a one-line list of ids.
47
+
48
+ ### `add`
49
+ Take the complete spec as it stands, the origin and the unblock condition. Derive an id. Write the entry under the section that matches its state (`ready` when nothing blocks it).
50
+
51
+ ### `pick <id>`
52
+ Find the entry, which must be `ready` or `deferred`. Change its state to `in-progress`, move it to that section, and print the full spec so the work can resume with nothing to reconstruct.
53
+
54
+ ### `done <id>`
55
+ Set the state to `done` and record the evidence: the PR or commit, and the date. The record is temporary. Once the lesson it carries has been written into the skill or document that owns that area, delete the entry: git history keeps the original, and a done entry left in place becomes a second copy of the truth that drifts from the real one.
56
+
57
+ ### `re-audit`
58
+ For each entry, check every type, path and factual claim it names against the live repository. Use a binary-safe search so repos that contain binary blobs do not make grep silently skip files:
59
+
60
+ ```bash
61
+ LC_ALL=C grep -rIa --line-number '<TypeOrPath>' .
62
+ ```
63
+
64
+ (`LC_ALL=C` avoids locale decoding failures; `-a` treats every file as text.) Then:
65
+ - subject gone: delete the entry;
66
+ - a fact changed: restate that fact in the entry;
67
+ - a number in the entry: measure it again and write the measured value.
68
+
69
+ ## Leaving the registry
70
+ An entry is removed for exactly two reasons: its subject rotted away (found by re-audit), or it is done and its lesson now lives in the owning skill or doc. Nothing leaves by being rewritten until it no longer says what it said.
51
71
 
52
- ## Why keep it whole
72
+ ## Numbers
73
+ A count in an entry changes only when it is measured again. Editing a number to match an impression makes it look like evidence when it is not.
53
74
 
54
- The failure mode this skill prevents: an agent defers a job with a one-line note, the surrounding context evaporates, and picking it up later means re-deriving the spec (or silently dropping it). Storing the full spec at defer-time makes deferral safe - the cost of "later" is paid once, up front, not lost.
75
+ ## Not for
76
+ - Work items that belong in the team's issue tracker (Jira, GitHub issues): file them there.
77
+ - Condensing, paraphrasing or "cleaning up" a deferred spec.
@@ -2,6 +2,7 @@
2
2
  name: ci-cd-pipelines
3
3
  description: "CI/CD pipelines: GitHub Actions workflows, Docker multi-stage builds, environment management, secret management, deployment strategies. Use when setting up or fixing a build, test or deploy pipeline."
4
4
  metadata:
5
+ source: multi-agent-pipeline
5
6
  tags: [ci-cd, github-actions, docker, deployment, devops, backend]
6
7
  version: "2025.1"
7
8
  ---
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: compose-components
3
3
  description: "Build Material 3 UI components and custom composables with Jetpack Compose. Covers TopAppBar, Scaffold, BottomSheet, SnackbarHost, slot-based API patterns, MaterialTheme customization, dynamic color, custom color schemes, shape/typography/color token mapping, and modifier ordering best practices. Use when building Compose UI, creating custom components, setting up theming, or reviewing Compose code."
4
+ metadata:
5
+ source: multi-agent-pipeline
4
6
  ---
5
7
 
6
8
  # Jetpack Compose Components