@mmerterden/multi-agent-pipeline 14.2.1 → 14.2.2

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 (106) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +10 -6
  3. package/README.tr.md +143 -0
  4. package/docs/architecture.md +23 -8
  5. package/docs/ecosystem.md +237 -0
  6. package/install/_plugin-skills.mjs +16 -2
  7. package/install/codex.mjs +9 -4
  8. package/install/templates/copilot-instructions.md +12 -9
  9. package/package.json +1 -1
  10. package/pipeline/commands/multi-agent/SKILL.md +2 -2
  11. package/pipeline/commands/multi-agent/analysis/SKILL.md +2 -2
  12. package/pipeline/commands/multi-agent/autopilot/SKILL.md +6 -2
  13. package/pipeline/commands/multi-agent/channels/SKILL.md +15 -4
  14. package/pipeline/commands/multi-agent/create-jira/SKILL.md +4 -4
  15. package/pipeline/commands/multi-agent/dev/SKILL.md +10 -23
  16. package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +10 -2
  17. package/pipeline/commands/multi-agent/dev-local/SKILL.md +10 -24
  18. package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +10 -3
  19. package/pipeline/commands/multi-agent/jira/SKILL.md +13 -2
  20. package/pipeline/commands/multi-agent/language/SKILL.md +1 -1
  21. package/pipeline/commands/multi-agent/local/SKILL.md +6 -2
  22. package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +6 -2
  23. package/pipeline/commands/multi-agent/log/SKILL.md +7 -1
  24. package/pipeline/commands/multi-agent/ship/SKILL.md +5 -1
  25. package/pipeline/commands/multi-agent/sync/SKILL.md +3 -3
  26. package/pipeline/commands/multi-agent/update/SKILL.md +1 -1
  27. package/pipeline/lib/extract-conventions.sh +44 -15
  28. package/pipeline/lib/fetch-figma-annotations.sh +8 -1
  29. package/pipeline/lib/fetch-fortify.sh +23 -8
  30. package/pipeline/lib/figma-screenshot.sh +11 -1
  31. package/pipeline/lib/issue-fetcher.sh +76 -9
  32. package/pipeline/lib/md2confluence-v3.py +16 -2
  33. package/pipeline/lib/plan-todos.sh +5 -2
  34. package/pipeline/lib/post-pr-review.sh +8 -6
  35. package/pipeline/lib/shadow-git.sh +50 -9
  36. package/pipeline/lib/submodule-detector.sh +8 -1
  37. package/pipeline/multi-agent-refs/_input-parser.md +1 -1
  38. package/pipeline/multi-agent-refs/channels/confluence.md +3 -0
  39. package/pipeline/multi-agent-refs/channels/issue-comment.md +2 -2
  40. package/pipeline/multi-agent-refs/channels/jira.md +13 -2
  41. package/pipeline/multi-agent-refs/channels/pr-review-actions.md +1 -1
  42. package/pipeline/multi-agent-refs/channels/pr.md +20 -0
  43. package/pipeline/multi-agent-refs/channels/wiki.md +1 -1
  44. package/pipeline/multi-agent-refs/cross-cli-contract.md +3 -3
  45. package/pipeline/multi-agent-refs/features/worktree-finalize.md +1 -1
  46. package/pipeline/multi-agent-refs/generate-issue.md +2 -2
  47. package/pipeline/multi-agent-refs/issue-jira-triad.md +3 -3
  48. package/pipeline/multi-agent-refs/payload-contracts.md +67 -0
  49. package/pipeline/multi-agent-refs/phases/modes.md +20 -0
  50. package/pipeline/multi-agent-refs/phases/phase-0-init.md +1 -1
  51. package/pipeline/multi-agent-refs/phases/phase-6-commit.md +8 -40
  52. package/pipeline/multi-agent-refs/phases/phase-7-report.md +5 -3
  53. package/pipeline/multi-agent-refs/phases.md +6 -0
  54. package/pipeline/multi-agent-refs/rules.md +2 -0
  55. package/pipeline/schemas/prefs.schema.json +1 -1
  56. package/pipeline/scripts/audit-log-rotate.sh +10 -0
  57. package/pipeline/scripts/build-stack-plugins.mjs +8 -1
  58. package/pipeline/scripts/check-derived-drift.mjs +13 -1
  59. package/pipeline/scripts/diff-explain.mjs +41 -3
  60. package/pipeline/scripts/diff-risk-score.mjs +72 -8
  61. package/pipeline/scripts/gen-mode-dispatch.mjs +1 -1
  62. package/pipeline/scripts/learning-curve.mjs +8 -2
  63. package/pipeline/scripts/output-quality-check.sh +15 -4
  64. package/pipeline/scripts/phase-tracker.sh +21 -8
  65. package/pipeline/scripts/pre-commit-check.sh +69 -22
  66. package/pipeline/scripts/render-agent-log-cost.sh +8 -3
  67. package/pipeline/scripts/render-cost-summary.sh +42 -22
  68. package/pipeline/scripts/render-work-summary.sh +47 -13
  69. package/pipeline/scripts/review-scope.mjs +1 -1
  70. package/pipeline/scripts/run-aggregator.mjs +38 -14
  71. package/pipeline/scripts/smoke-schema-validation.sh +5 -1
  72. package/pipeline/scripts/test-gap-scan.mjs +45 -6
  73. package/pipeline/scripts/uninstall.mjs +39 -4
  74. package/pipeline/scripts/update-issue-progress.sh +12 -16
  75. package/pipeline/scripts/worktree-finalize.sh +23 -2
  76. package/pipeline/skills/.skills-index.json +11 -2
  77. package/pipeline/skills/shared/README.md +1 -1
  78. package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +4 -0
  79. package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +1 -1
  80. package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +4 -17
  81. package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +8 -0
  82. package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +5 -18
  83. package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +8 -0
  84. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +1 -1
  85. package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +4 -0
  86. package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +4 -0
  87. package/pipeline/skills/shared/core/multi-agent-ship/SKILL.md +4 -0
  88. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +2 -2
  89. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +302 -0
  90. package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +144 -0
  91. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +156 -0
  92. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +108 -0
  93. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +175 -0
  94. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +865 -0
  95. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +335 -0
  96. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +344 -0
  97. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +130 -0
  98. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +264 -0
  99. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +298 -0
  100. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +529 -0
  101. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +187 -0
  102. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +171 -0
  103. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +184 -0
  104. package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +26 -0
  105. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +173 -0
  106. package/pipeline/skills/skills-index.md +3 -2
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env python3
2
+ """Fidelity check - cross-verify a mapping against the REAL sources before publishing.
3
+
4
+ The map can drift from reality (stale keys parsed from an old doc, hallucinated keys,
5
+ a wired key that never made it into a row, an empty value). This script reconciles the
6
+ mapping JSON against the live repos and reports what doesn't hold up - so the page you
7
+ publish reflects the code, not a guess. Read-only.
8
+
9
+ Checks (each reported, never auto-fixed):
10
+ 1. newKey ∈ screen code - every row's `newKey` should appear as a wired
11
+ `LocalizationStringKey.<...>` call site (or `"Key".localized`, or a web
12
+ `t('Key')` / `$t('Key')` i18n call) in --screen-path.
13
+ Component-owned keys (`(owned by ...)` / `(DS bileşen...)`) are exempt (they live in the
14
+ component, not the screen file) and listed separately.
15
+ 2. code keys ∉ map - `LocalizationStringKey.<...>` wired in the screen but with no
16
+ row → missing coverage (add a row or confirm it's out of scope).
17
+ 3. value gaps - `new.tr` empty (verdict≠new), or legacy entirely empty where
18
+ the verdict claims reuse/review.
19
+ 4. untranslated - a row whose `new.tr` == `new.en` (flag, as the renderer does).
20
+ 5. resources (optional) - with --resources-root, the new key's Suggested/<Key>.json exists.
21
+
22
+ Exit code 2 when any hard fidelity issue is found (unverified non-component key, code key
23
+ missing from the map, or a reuse/review row with no legacy value), so it can gate a run.
24
+ """
25
+ import argparse
26
+ import json
27
+ import os
28
+ import re
29
+ import sys
30
+
31
+ EXTS = (".swift", ".kt", ".kts", ".xml", ".ts", ".tsx", ".js", ".jsx", ".vue")
32
+ RE_LSK = re.compile(r"LocalizationStringKey\.([A-Za-z0-9_]+(?:\.[A-Za-z0-9_]+)+)")
33
+ RE_LITERAL = re.compile(r'"([A-Za-z0-9_.]+)"\s*\.\s*localized')
34
+ # Web (react-i18next / next-intl `t('key')`; vue-i18n `$t('key')`)
35
+ RE_WEB_T = re.compile(r"(?<!\$)\bt\(\s*['\"]([A-Za-z0-9_.\-]+)['\"]")
36
+ RE_WEB_VUE_T = re.compile(r"\$t\(\s*['\"]([A-Za-z0-9_.\-]+)['\"]")
37
+ # RE_LSK is greedy across dots, so `...StringKey.Ns.leaf.localized` captures the accessor
38
+ # too. Strip it, or no call site ever matches its mapping row and every wired key is
39
+ # reported unmapped.
40
+ RE_ACCESSOR = re.compile(r"\.localized\w*$")
41
+ MARKER = re.compile(r"\(.*(owned by|bileşen|component).*\)", re.I)
42
+
43
+
44
+ def clean_key(k):
45
+ """Strip a trailing '(owned by ...)' / '(DS bileşene ait)' marker → bare dotted key."""
46
+ return re.sub(r"\s*\(.*\)\s*$", "", (k or "")).strip()
47
+
48
+
49
+ def is_component(k):
50
+ return bool(MARKER.search(k or ""))
51
+
52
+
53
+ def norm_key(k):
54
+ return clean_key(k).lower()
55
+
56
+
57
+ def scan_code(screen_path):
58
+ """Return (set of wired dotted keys lowercased, full lowercased corpus text)."""
59
+ keys, corpus = set(), []
60
+ files = []
61
+ if os.path.isfile(screen_path):
62
+ files = [screen_path]
63
+ else:
64
+ for dp, _d, names in os.walk(screen_path):
65
+ if "/.git" in dp:
66
+ continue
67
+ files += [os.path.join(dp, n) for n in names if n.endswith(EXTS)]
68
+ for f in files:
69
+ try:
70
+ txt = open(f, encoding="utf-8", errors="replace").read()
71
+ except OSError:
72
+ continue
73
+ corpus.append(txt.lower())
74
+ for m in RE_LSK.finditer(txt):
75
+ keys.add(RE_ACCESSOR.sub("", m.group(1)).lower())
76
+ for m in RE_LITERAL.finditer(txt):
77
+ keys.add(m.group(1).lower())
78
+ for m in RE_WEB_T.finditer(txt):
79
+ keys.add(m.group(1).lower())
80
+ for m in RE_WEB_VUE_T.finditer(txt):
81
+ keys.add(m.group(1).lower())
82
+ return keys, "\n".join(corpus), len(files)
83
+
84
+
85
+ def leaf_in_corpus(key, corpus):
86
+ """Weak check: the key's last segment appears as a word in the code corpus."""
87
+ leaf = clean_key(key).split(".")[-1]
88
+ return bool(leaf) and re.search(r"\b" + re.escape(leaf.lower()) + r"\b", corpus) is not None
89
+
90
+
91
+ def main():
92
+ ap = argparse.ArgumentParser(description=__doc__,
93
+ formatter_class=argparse.RawDescriptionHelpFormatter)
94
+ ap.add_argument("--mapping", required=True)
95
+ ap.add_argument("--screen-path", required=True, help="implemented screen dir/file")
96
+ ap.add_argument("--resources-root", help="resources / snapshot root (checks Suggested/<Key>.json)")
97
+ ap.add_argument("--out", help="write the full report JSON here (default: stdout summary only)")
98
+ args = ap.parse_args()
99
+
100
+ m = json.load(open(args.mapping, encoding="utf-8"))
101
+ rows = m.get("rows", [])
102
+ code_keys, corpus, nfiles = scan_code(args.screen_path)
103
+
104
+ verified, weak, unverified, component = [], [], [], []
105
+ value_gaps, untranslated = [], []
106
+ map_keys = set()
107
+
108
+ for r in rows:
109
+ k = r.get("newKey", "")
110
+ ck = clean_key(k)
111
+ map_keys.add(norm_key(k))
112
+ # 1. newKey in code
113
+ if is_component(k) or k.startswith("(dynamic") or "dinamik" in (r.get("element", "").lower()):
114
+ component.append(k)
115
+ elif norm_key(k) in code_keys:
116
+ verified.append(k)
117
+ elif leaf_in_corpus(k, corpus):
118
+ weak.append(k)
119
+ else:
120
+ unverified.append({"key": k, "element": r.get("element")})
121
+ # 3. value gaps
122
+ nw, lg, vd = r.get("new") or {}, r.get("legacy") or {}, r.get("verdict")
123
+ if vd != "new" and not (nw.get("tr") or "").strip() and not k.startswith("(dynamic"):
124
+ value_gaps.append({"key": k, "issue": "new.tr empty"})
125
+ if vd in ("reuse", "review") and not any((lg.get(l) or "").strip() for l in ("en", "tr")):
126
+ value_gaps.append({"key": k, "issue": f"verdict={vd} but no legacy value"})
127
+ # 4. untranslated
128
+ if (nw.get("tr") or "").strip() and nw.get("tr") == nw.get("en"):
129
+ untranslated.append(k)
130
+ # 5. resources
131
+ if args.resources_root and not is_component(k) and not k.startswith("(dynamic"):
132
+ seg = ".".join(s[:1].upper() + s[1:] if s else s for s in ck.split("."))
133
+ p1 = os.path.join(args.resources_root, "Localization", "Suggested", seg + ".json")
134
+ p2 = os.path.join(args.resources_root, "Resources", "Localization",
135
+ "LocalizationStrings", "Sources", "Suggested", seg + ".json")
136
+ if not (os.path.isfile(p1) or os.path.isfile(p2)):
137
+ value_gaps.append({"key": k, "issue": "no Suggested/<Key>.json"})
138
+
139
+ # 2. code keys not in map
140
+ code_not_mapped = sorted(k for k in code_keys if k not in map_keys)
141
+
142
+ report = {
143
+ "screen": m.get("screen"), "rows": len(rows), "filesScanned": nfiles,
144
+ "newKeyInCode": {"verified": len(verified), "weak": weak,
145
+ "unverified": unverified, "component_or_dynamic": len(component)},
146
+ "codeKeysNotInMap": code_not_mapped,
147
+ "valueGaps": value_gaps, "untranslated": untranslated,
148
+ }
149
+ hard = len(unverified) + len(code_not_mapped) + sum(1 for g in value_gaps if "no legacy" in g["issue"])
150
+
151
+ if args.out:
152
+ with open(args.out, "w", encoding="utf-8") as fh:
153
+ json.dump(report, fh, ensure_ascii=False, indent=2)
154
+ fh.write("\n")
155
+ # summary to stderr (always)
156
+ sys.stderr.write(
157
+ f"# fidelity: {len(rows)} rows · {nfiles} files\n"
158
+ f"# newKey in code: {len(verified)} verified · {len(weak)} weak(leaf) · "
159
+ f"{len(unverified)} UNVERIFIED · {len(component)} component/dynamic (exempt)\n"
160
+ f"# code keys not in map: {len(code_not_mapped)}\n"
161
+ f"# value gaps: {len(value_gaps)} · untranslated(tr==en): {len(untranslated)}\n")
162
+ if unverified:
163
+ sys.stderr.write("# UNVERIFIED keys: " + ", ".join(u["key"] for u in unverified[:12]) + "\n")
164
+ if code_not_mapped:
165
+ sys.stderr.write("# wired-but-unmapped: " + ", ".join(code_not_mapped[:12]) + "\n")
166
+ if not args.out:
167
+ json.dump(report, sys.stdout, ensure_ascii=False, indent=2)
168
+ sys.stdout.write("\n")
169
+ sys.exit(2 if hard else 0)
170
+
171
+
172
+ if __name__ == "__main__":
173
+ main()
@@ -3,7 +3,7 @@
3
3
  > Auto-generated by `pipeline/scripts/build-skills-index.mjs` - do not hand-edit.
4
4
  > Regenerate with `node pipeline/scripts/build-skills-index.mjs`.
5
5
 
6
- **201 skills** across 2 groups.
6
+ **202 skills** across 2 groups.
7
7
 
8
8
  | Group | Name | Platform | Description |
9
9
  |-------|------|----------|-------------|
@@ -84,6 +84,7 @@
84
84
  | external | `ios-simulator` | - | Manages iOS Simulator devices and tests app behaviour with xcrun simctl: device lifecycle, app install and launch, push notification and loc |
85
85
  | external | `kotlin-coroutines-expert` | - | Expert patterns for Kotlin Coroutines and Flow, covering structured concurrency, error handling, and testing. Use when writing or reviewing |
86
86
  | external | `live-activities` | - | Implement, review, or improve Live Activities and Dynamic Island experiences in iOS apps using ActivityKit. Use when building real-time upda |
87
+ | external | `localization-reuse-map` | - | >- |
87
88
  | external | `macos-menubar-tuist-app` | - | Build, refactor, or review SwiftUI macOS menubar apps that use Tuist. Use when building, refactoring or reviewing a SwiftUI macOS menubar ap |
88
89
  | external | `macos-spm-app-packaging` | - | Scaffold, build, sign, and package SwiftPM macOS apps without Xcode projects. Use when a SwiftPM macOS app has to be built, signed or packag |
89
90
  | external | `mapkit-location` | - | Implement, review, or improve maps and location features in iOS/macOS apps using MapKit and CoreLocation. Use when working with Map views, a |
@@ -109,7 +110,7 @@
109
110
  | core | `multi-agent-issue` | - | List unassigned GitHub issues, pick one, auto-assign, and launch the multi-agent pipeline. Use when a GitHub issue should be picked up and s |
110
111
  | core | `multi-agent-jira` | - | List open Jira issues, pick one, and launch the multi-agent pipeline. Use when a Jira issue should be picked up and started without knowing |
111
112
  | core | `multi-agent-kill` | - | Stop the given task, then remove its worktree and branch. Asks for confirmation. Use when a running or stuck task should be stopped and its |
112
- | core | `multi-agent-language` | - | Toggle outputLanguage (assistant explanations). promptLanguage is fixed to English. External payloads stay English. Use when the assistant s |
113
+ | core | `multi-agent-language` | - | Toggle outputLanguage (assistant explanations, picker questions, PR/Jira/Confluence bodies). promptLanguage is fixed to English; commit mess |
113
114
  | core | `multi-agent-local` | - | Full pipeline in local mode - no worktree, runs directly on the current branch. Use when the full pipeline should run on the current branc |
114
115
  | core | `multi-agent-local-autopilot` | - | Full pipeline + local + autopilot - no worktree, no confirmations, all 8 phases run end-to-end on the current branch. Use when the full pi |
115
116
  | core | `multi-agent-log` | - | Show the agent-log.md for the given task. With no ID, shows the most recent task. Use when asked what a task did, or to read its log. |