@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.
- package/CHANGELOG.md +42 -0
- package/README.md +10 -6
- package/README.tr.md +143 -0
- package/docs/architecture.md +23 -8
- package/docs/ecosystem.md +237 -0
- package/install/_plugin-skills.mjs +16 -2
- package/install/codex.mjs +9 -4
- package/install/templates/copilot-instructions.md +12 -9
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/analysis/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/autopilot/SKILL.md +6 -2
- package/pipeline/commands/multi-agent/channels/SKILL.md +15 -4
- package/pipeline/commands/multi-agent/create-jira/SKILL.md +4 -4
- package/pipeline/commands/multi-agent/dev/SKILL.md +10 -23
- package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +10 -2
- package/pipeline/commands/multi-agent/dev-local/SKILL.md +10 -24
- package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +10 -3
- package/pipeline/commands/multi-agent/jira/SKILL.md +13 -2
- package/pipeline/commands/multi-agent/language/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/local/SKILL.md +6 -2
- package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +6 -2
- package/pipeline/commands/multi-agent/log/SKILL.md +7 -1
- package/pipeline/commands/multi-agent/ship/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/sync/SKILL.md +3 -3
- package/pipeline/commands/multi-agent/update/SKILL.md +1 -1
- package/pipeline/lib/extract-conventions.sh +44 -15
- package/pipeline/lib/fetch-figma-annotations.sh +8 -1
- package/pipeline/lib/fetch-fortify.sh +23 -8
- package/pipeline/lib/figma-screenshot.sh +11 -1
- package/pipeline/lib/issue-fetcher.sh +76 -9
- package/pipeline/lib/md2confluence-v3.py +16 -2
- package/pipeline/lib/plan-todos.sh +5 -2
- package/pipeline/lib/post-pr-review.sh +8 -6
- package/pipeline/lib/shadow-git.sh +50 -9
- package/pipeline/lib/submodule-detector.sh +8 -1
- package/pipeline/multi-agent-refs/_input-parser.md +1 -1
- package/pipeline/multi-agent-refs/channels/confluence.md +3 -0
- package/pipeline/multi-agent-refs/channels/issue-comment.md +2 -2
- package/pipeline/multi-agent-refs/channels/jira.md +13 -2
- package/pipeline/multi-agent-refs/channels/pr-review-actions.md +1 -1
- package/pipeline/multi-agent-refs/channels/pr.md +20 -0
- package/pipeline/multi-agent-refs/channels/wiki.md +1 -1
- package/pipeline/multi-agent-refs/cross-cli-contract.md +3 -3
- package/pipeline/multi-agent-refs/features/worktree-finalize.md +1 -1
- package/pipeline/multi-agent-refs/generate-issue.md +2 -2
- package/pipeline/multi-agent-refs/issue-jira-triad.md +3 -3
- package/pipeline/multi-agent-refs/payload-contracts.md +67 -0
- package/pipeline/multi-agent-refs/phases/modes.md +20 -0
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +1 -1
- package/pipeline/multi-agent-refs/phases/phase-6-commit.md +8 -40
- package/pipeline/multi-agent-refs/phases/phase-7-report.md +5 -3
- package/pipeline/multi-agent-refs/phases.md +6 -0
- package/pipeline/multi-agent-refs/rules.md +2 -0
- package/pipeline/schemas/prefs.schema.json +1 -1
- package/pipeline/scripts/audit-log-rotate.sh +10 -0
- package/pipeline/scripts/build-stack-plugins.mjs +8 -1
- package/pipeline/scripts/check-derived-drift.mjs +13 -1
- package/pipeline/scripts/diff-explain.mjs +41 -3
- package/pipeline/scripts/diff-risk-score.mjs +72 -8
- package/pipeline/scripts/gen-mode-dispatch.mjs +1 -1
- package/pipeline/scripts/learning-curve.mjs +8 -2
- package/pipeline/scripts/output-quality-check.sh +15 -4
- package/pipeline/scripts/phase-tracker.sh +21 -8
- package/pipeline/scripts/pre-commit-check.sh +69 -22
- package/pipeline/scripts/render-agent-log-cost.sh +8 -3
- package/pipeline/scripts/render-cost-summary.sh +42 -22
- package/pipeline/scripts/render-work-summary.sh +47 -13
- package/pipeline/scripts/review-scope.mjs +1 -1
- package/pipeline/scripts/run-aggregator.mjs +38 -14
- package/pipeline/scripts/smoke-schema-validation.sh +5 -1
- package/pipeline/scripts/test-gap-scan.mjs +45 -6
- package/pipeline/scripts/uninstall.mjs +39 -4
- package/pipeline/scripts/update-issue-progress.sh +12 -16
- package/pipeline/scripts/worktree-finalize.sh +23 -2
- package/pipeline/skills/.skills-index.json +11 -2
- package/pipeline/skills/shared/README.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +4 -0
- package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +4 -17
- package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +8 -0
- package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +5 -18
- package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +8 -0
- package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +4 -0
- package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +4 -0
- package/pipeline/skills/shared/core/multi-agent-ship/SKILL.md +4 -0
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +2 -2
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +302 -0
- package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +144 -0
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +156 -0
- package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +108 -0
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +175 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +865 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +335 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +344 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +130 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +264 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +298 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +529 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +187 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +171 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +184 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +26 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +173 -0
- 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
|
-
**
|
|
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
|
|
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. |
|