@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.
- package/CHANGELOG.md +36 -0
- package/LICENSE +10 -0
- package/docs/facts.json +5 -4
- package/install/_dev-only-files.mjs +1 -0
- package/manifest.json +84 -82
- package/package.json +4 -3
- package/pipeline/lib/confusables.json +100 -0
- package/pipeline/lib/normalize-text.mjs +48 -0
- package/pipeline/lib/outbound-gate.mjs +10 -1
- package/pipeline/lib/redact.mjs +4 -1
- package/pipeline/lib/vercel-deploy.sh +5 -7
- package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
- package/pipeline/scripts/_notices.mjs +11 -0
- package/pipeline/scripts/agent-guard.py +30 -1
- package/pipeline/scripts/gen-skills-index.mjs +1 -1
- package/pipeline/scripts/pre-commit-check.sh +59 -16
- package/pipeline/scripts/pre-push-check.sh +3 -3
- package/pipeline/scripts/run-ui-tests.sh +5 -5
- package/pipeline/scripts/website-deploy-commit.sh +3 -2
- package/pipeline/skills/.skill-manifest.json +39 -39
- package/pipeline/skills/shared/README.md +1 -1
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
- package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
- package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
- package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
- package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
- package/pipeline/skills/shared/external/council/SKILL.md +1 -0
- package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
- package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
- package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
- package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
- package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
- package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
- package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
- package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
- package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
- package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
- package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
- package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
- package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
- package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
- package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
- package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md
CHANGED
|
@@ -1,156 +1,124 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Mapping format and outputs
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
> consumes, and the artifacts it produces. Input shape: [../example-mapping.json](../example-mapping.json).
|
|
3
|
+
The mapping JSON is the single source every renderer reads. The scripts add nothing of their own: what is not in the mapping does not appear in the table, the spreadsheet or the page.
|
|
5
4
|
|
|
6
|
-
##
|
|
5
|
+
## Mapping schema
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
Top level:
|
|
8
|
+
|
|
9
|
+
| Key | Required | Meaning |
|
|
9
10
|
|---|---|---|
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"verdict": "review", // reuse | review | new
|
|
44
|
-
"note": "Legacy tr 'Devam' vs new 'Devam Et'."
|
|
45
|
-
}
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
Fill `new` with `resolve-new-values.py --langs all`, `legacy` with `resolve-legacy-values.py --langs all`,
|
|
50
|
-
and `cms` from `fetch-annotations.py` (the content team's Final UX Writing TR/EN; see
|
|
51
|
-
[sources-and-recipes.md](sources-and-recipes.md)). The renderer shows **en/tr** old/new **+ CMS tr/en** in the
|
|
52
|
-
summary, and **all 8** old/new **plus every CMS language present** in the details - so keep the `new`/`legacy`
|
|
53
|
-
maps fully 8-keyed; `cms` is whatever the content team annotated (usually tr+en).
|
|
54
|
-
|
|
55
|
-
**CMS columns + drift.** `cms` is the content team's *actual* final copy and is shown additively - it does
|
|
56
|
-
**not** overwrite `new`. When a `cms` value differs from the `new` (design/resources) value for the same
|
|
57
|
-
language, the renderer marks the cell **⚠** and counts it as a CMS difference in the header.
|
|
58
|
-
Blank `cms` is expected (no annotation yet) - never invent one.
|
|
59
|
-
|
|
60
|
-
**Author `element` and `note` in the content team's own language** - pick it once (`--ui-lang` sets the
|
|
61
|
-
template chrome to match) and stay consistent. These two author-written fields are the only free text in the
|
|
62
|
-
doc, so a mixed-language run reads as half-translated. `newKey` / legacy keys and the translation values stay
|
|
63
|
-
verbatim.
|
|
64
|
-
|
|
65
|
-
## Output - artifacts (one mapping)
|
|
66
|
-
|
|
67
|
-
`build-artifact.py <mapping>.json --out <dir>` always writes these three:
|
|
68
|
-
- **`<slug>.md`** - Markdown mirror (PR / quick read).
|
|
69
|
-
- **`<slug>.confluence.xml`** - Confluence **storage format**: section Screen (`<ac:image>`), section key map (the overlay
|
|
70
|
-
`<ac:image>` when `overlay` is set), section Summary (Old en/tr · New en/tr · **CMS tr/en** + verdict, `status`
|
|
71
|
-
macros, `info`-macro legend + counts + drift note, and - when `keyshots` is set - a per-row
|
|
72
|
-
**Screenshot** cell embedding that key's red-box screenpiece by attachment filename), section Details
|
|
73
|
-
(per-element tables: all 8 langs Old/New + CMS). This is exactly the REST API's `body.storage.value`.
|
|
74
|
-
- **`<slug>.preview.html`** - standalone browser preview (open locally before upload).
|
|
75
|
-
|
|
76
|
-
Two more are **opt-in**, for handing the map to the content team as a file (not a Confluence page):
|
|
77
|
-
- **`<slug>.docx`** (`--docx`) - a Word document with the same section Screen / section Summary / section Details layout
|
|
78
|
-
(landscape, verdict-shaded cells, embedded screenshot, RTL on the Arabic rows). Generated with the
|
|
79
|
-
**Python stdlib only** - a `.docx` is a ZIP of OOXML, so there is no third-party dependency and no network.
|
|
80
|
-
- **`<slug>.pdf`** (`--pdf`) - a read-only share copy. Multilingual (Arabic + Cyrillic + Latin) PDF needs real
|
|
81
|
-
font shaping, so it is **not** hand-rolled: the script drives whatever renderer the machine has, in order
|
|
82
|
-
of table fidelity - LibreOffice `soffice` (docx→pdf) → Chrome/Chromium headless (html→pdf) → `wkhtmltopdf`.
|
|
83
|
-
If none is installed the PDF is **skipped** with a note pointing at the `.docx` / `.html` (still no pip, no
|
|
84
|
-
network). `--all` writes every format.
|
|
85
|
-
|
|
86
|
-
Layout = **summary (en/tr at a glance) + details (all 8)** - the "best of both worlds": devs scan the
|
|
87
|
-
summary, the content team works the per-element language tables. The `.docx`/`.pdf` mirror the same two levels.
|
|
88
|
-
|
|
89
|
-
## Per-key screenpieces (keyshots) - the "Screenshot" column
|
|
90
|
-
|
|
91
|
-
`scripts/render-key-shots.py --mapping <map>.json --out <dir>` renders, for **every matched row**, a cropped
|
|
92
|
-
band of the screen with a **red box around exactly that element** (ported from the web skill's
|
|
93
|
-
`render-key-shots.mjs`) - so the table shows the content team *where each key lives on screen* without
|
|
94
|
-
hunting through the full overlay. Files land in `<out>/keyshots/keyshot__<NN>__<key>.png`, where **NN is
|
|
95
|
-
the row's 1-based position in `mapping.rows`** - the same number the Summary table and the overlay cards
|
|
96
|
-
use, so shot ↔ card ↔ row always agree. A manifest (`<slug>.keyshots.manifest.json`) lists
|
|
97
|
-
`shots` (row → file) and `missing` (rows with no visible matched node - their cells render " - ", never a
|
|
98
|
-
guessed crop).
|
|
99
|
-
|
|
100
|
-
Geometry comes from the same two modes as the overlay: **REST** (walks the frame's node tree with
|
|
101
|
-
**ancestor-visibility + cumulative-opacity** filtering, so a hidden variant's stale bbox never lands the
|
|
102
|
-
red box on the wrong content) or **`--spec`** (repeatable - one per screen state; the overlay-compatible
|
|
103
|
-
spec shape, whose `image` may be a **data URL or a file path** relative to the spec file). Rows are matched
|
|
104
|
-
to nodes with the overlay's matcher (`cmsNodeId` first, else normalized value), so the three renderers can
|
|
105
|
-
never disagree about which node a key is. Set the mapping's top-level `"keyshots"` to the manifest filename
|
|
106
|
-
and `build-artifact.py` fills the **Screenshot** column in all four formats (Confluence XML by
|
|
107
|
-
attachment filename, `.md`/`.preview.html` by relative path, `.docx` embedded). No headless Chrome →
|
|
108
|
-
per-shot `.html` fallbacks (marked in the manifest; not embeddable).
|
|
109
|
-
|
|
110
|
-
## CMS import spreadsheet (Excel attachment)
|
|
111
|
-
|
|
112
|
-
`scripts/build-spreadsheet.py <mapping>.json --out <dir>` writes **`<slug>.localization.xlsx`** - the flat
|
|
113
|
-
sheet the content team imports into the CMS, attached to the Confluence page (and, being a spreadsheet, also
|
|
114
|
-
rendered inline via a `view-file` macro). It is a **real `.xlsx`**: an OOXML zip assembled with the Python
|
|
115
|
-
**stdlib only** (`zipfile` + inline-string XML) - no pip, no LibreOffice, no network, exactly like the
|
|
116
|
-
`.docx` path. `--csv` writes a UTF-8 (BOM) CSV alongside; `--csv-only` skips the xlsx when a CSV is all that's
|
|
117
|
-
wanted.
|
|
118
|
-
|
|
119
|
-
**One row per mapping row**, in this fixed column order (matches the content team's sheet):
|
|
120
|
-
|
|
121
|
-
| Column | Source | Notes |
|
|
11
|
+
| `screen` | yes | Screen name; the file slug is derived from it |
|
|
12
|
+
| `platforms` | no | e.g. `["ios", "android", "web"]` |
|
|
13
|
+
| `figmaNodes` | no | Array of frame node-ids |
|
|
14
|
+
| `figmaFileKey` | no | Enables the live annotation fetch and the REST overlay |
|
|
15
|
+
| `screenshot` | no | Screen image, relative to the mapping |
|
|
16
|
+
| `overlay` | no | Overlay PNG name |
|
|
17
|
+
| `keyshots` | no | Keyshots manifest name |
|
|
18
|
+
| `legacyKeyPrefix` | no | Prepended to legacy keys for display only |
|
|
19
|
+
| `rows` | yes | One object per UI element |
|
|
20
|
+
|
|
21
|
+
Row:
|
|
22
|
+
|
|
23
|
+
| Key | Meaning |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `element` | Human label for the UI element, in the `--ui-lang` language |
|
|
26
|
+
| `newKey` | Redesign key; may carry `(owned by <Component>)` |
|
|
27
|
+
| `new` | Eight-language map: `en`, `tr`, `ar`, `de`, `es`, `fr`, `it`, `ru` |
|
|
28
|
+
| `legacyKeyIOS`, `legacyKeyAndroid`, `legacyKeyWeb` | Legacy key per platform. Empty or omitted renders a dash. Web only when the legacy app has a web frontend. A value in parentheses such as `(nav title)` is a marker and is shown as is |
|
|
29
|
+
| `legacy` | Eight-language map; `""` where the value is only served by the backend and was not fetched |
|
|
30
|
+
| `cms` | Optional; usually `tr` and `en` from the Figma annotation |
|
|
31
|
+
| `cmsNodeId` | Optional; the annotated (or synthetic spec) node-id |
|
|
32
|
+
| `cmsSource` | Optional: `figma-rest`, `figma-mcp`, `local` or `none` |
|
|
33
|
+
| `verdict` | `reuse`, `review` or `new` |
|
|
34
|
+
| `note` | Reasoning, edge-case flags, `(owned by ...)`, "dynamic - enumerate at runtime" |
|
|
35
|
+
| `propertyGroup`, `propertyModule` | Optional spreadsheet-only overrides |
|
|
36
|
+
|
|
37
|
+
Keep `new` and `legacy` fully eight-keyed. The summary table shows old and new `en`/`tr` plus CMS `tr`/`en`; the details section shows all eight languages plus every CMS language present.
|
|
38
|
+
|
|
39
|
+
### The example
|
|
40
|
+
|
|
41
|
+
[`../example-mapping.json`](../example-mapping.json) maps a neutral "Sign Up - Account Details" screen in nine rows, with `legacyKeyPrefix: "Mobile-"`:
|
|
42
|
+
|
|
43
|
+
| # | Case | Verdict |
|
|
122
44
|
|---|---|---|
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
|
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
`
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
`
|
|
155
|
-
|
|
156
|
-
|
|
45
|
+
| 1 | Nav title with no iOS legacy key (`(nav title)` marker) | review |
|
|
46
|
+
| 2 | One shared key, identical on all three platforms | reuse |
|
|
47
|
+
| 3 | Placeholder with no legacy counterpart | new |
|
|
48
|
+
| 4 | Component-owned `PasswordField.StrengthHint` with cross-platform key drift | review |
|
|
49
|
+
| 5 | Duplicate-email error found only by the scanner; the Android key has a typo | review |
|
|
50
|
+
| 6 | CTA whose web key is namespaced (`signup.continue_button`) | review |
|
|
51
|
+
| 7 | `tr` equal to `en` in the redesign source | reuse, flagged untranslated |
|
|
52
|
+
| 8 | CMS-only `tr` that differs from `new` | new |
|
|
53
|
+
| 9 | Dynamic `Error.<field>Required` | review, "enumerate at runtime" |
|
|
54
|
+
|
|
55
|
+
## Rendered artifacts
|
|
56
|
+
|
|
57
|
+
`build-artifact.py <map>.json --out <dir>` always writes three files, and more on request:
|
|
58
|
+
|
|
59
|
+
| File | Contents |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `<slug>.md` | Title, intro, platforms and Figma nodes, screenshot, optional key-map image, summary with counts, drift note, pipe table (pipes escaped, newlines flattened, keyshot as a relative image), per-row detail tables |
|
|
62
|
+
| `<slug>.confluence.xml` | Storage format, the value of `body.storage.value`: header paragraph, an `info` macro with the legend (status macros), counts, CMS line and drift note; a Screen section (`<ac:image ac:height="500">`); a key-map section (`<ac:image ac:width="900">`); the summary table with keyshots (`<ac:image ac:width="240">`) referenced by attachment name, keys in `<code>`, status macros; per-row details with an eight-language Old / New / CMS table |
|
|
63
|
+
| `<slug>.preview.html` | Standalone page with sections 1 Screen, 2 Summary, 3 Details and coloured verdict badges. Absolute image paths become `file://` URLs; bare names stay relative |
|
|
64
|
+
| `<slug>.docx` (`--docx`) | Word document built with the standard library: landscape A4, screenshot, overlay and keyshot thumbnails, verdict-shaded cells, a pink cell for drifting CMS TR, right-to-left Arabic rows |
|
|
65
|
+
| `<slug>.pdf` (`--pdf`) | LibreOffice from the docx, then headless Chrome from the preview, then `wkhtmltopdf`. With none of them installed the PDF is skipped with a note naming the file to share instead |
|
|
66
|
+
|
|
67
|
+
`--all` means `--docx --pdf`. Summary columns in order: `#`, UI element, Screenshot, New key, Legacy iOS, Legacy Android, Legacy Web, Old en, Old tr, New en, New tr, CMS TR, CMS EN, Verdict, Note. Detail columns: Lang, Old (legacy), New (redesign), CMS. Verdict colours on Confluence: reuse Green, review Yellow, new Blue, anything else Grey.
|
|
68
|
+
|
|
69
|
+
A CMS value counts as drifting when both it and `new` are non-empty and they still differ after Unicode NFC normalisation, whitespace collapsing, stripping a trailing `.`, `:` or ellipsis, and lowercasing. Drifting cells carry a warning sign.
|
|
70
|
+
|
|
71
|
+
The `--ui-lang` switch (`en` default, `tr`) changes headings, legend, labels and column names; keys and values are never translated.
|
|
72
|
+
|
|
73
|
+
## Overlay and keyshots
|
|
74
|
+
|
|
75
|
+
- `render-overlay.py` writes `<slug>.overlay.png` (or `<slug>.overlay.html` when no Chrome, Chromium or Edge is installed) and `<slug>.overlay.manifest.json` with `screen`, `file`, `fileKey`, `nodeId`, `cardCount`, `annotatedCount`, `width`, `height`, `scale`. Pink cards carry CMS copy; gray cards show the on-screen text and await copy.
|
|
76
|
+
- `render-key-shots.py` writes `keyshots/keyshot__<NN>__<key>.png` (or `.html` crops with `"fallback": "html"`) and `<slug>.keyshots.manifest.json` with `screen`, `slug`, `pad`, `scale`, `dir`, `shots[]` (`row`, `key`, `element`, `file`, `pageNode`, `cropW`, `cropH`) and `missing[]` (`row`, `key`, `reason`).
|
|
77
|
+
|
|
78
|
+
## CMS import spreadsheet
|
|
79
|
+
|
|
80
|
+
`build-spreadsheet.py <map>.json --out <dir>` writes `<slug>.localization.xlsx`, a real Excel workbook built with the standard library (sheet `Localization`, styled and frozen header row, autofilter). `--csv` adds a UTF-8 CSV with BOM; `--csv-only` skips the xlsx. One row per key, attached to the Confluence page at publish time.
|
|
81
|
+
|
|
82
|
+
Nine fixed columns, spelled exactly like this:
|
|
83
|
+
|
|
84
|
+
`Channel`, `Property Group`, `Property Module`, `Key`, `EN Value`, `TR Value`, `AR Value`, `Anotation EN`, `Anotation TR`
|
|
85
|
+
|
|
86
|
+
- `Channel` comes from `--channel` (default `Mobile`).
|
|
87
|
+
- `Key` is `newKey` with any `(owned by ...)` suffix removed.
|
|
88
|
+
- Values come from `new.en/tr/ar`, annotations from `cms.en/tr`; missing means blank.
|
|
89
|
+
- Property Group and Module: row overrides win (each fills its own half). Otherwise the key decides, in order: contains `error` gives Errors; `lookup` gives Lookups; `validation`, `invalid` or a `.valid` ending gives Core / Validation; `field`, `placeholder`, `hint` or `label` gives Core / Fields; a first namespace segment or any word matching a domain list gives the domain group (`Domains`) and the domain name; anything else is Core / Common.
|
|
90
|
+
- Default domains: auth (auth, login, signin, sign-in, register, signup, otp, password), account (account, profile, settings, preferences), checkout (checkout, cart, payment, billing, order), search (search, filter, results). A `--taxonomy` JSON object is merged one level deep over these defaults.
|
|
91
|
+
|
|
92
|
+
## Fidelity gate
|
|
93
|
+
|
|
94
|
+
`verify-map.py --mapping <map>.json --screen-path <dir> [--resources-root <res>] [--out report.json]` is count reconciliation as a script.
|
|
95
|
+
|
|
96
|
+
| Check | Hard? |
|
|
97
|
+
|---|---|
|
|
98
|
+
| Each `newKey` is wired in the screen code (exact match), or exempt as component-owned or dynamic. A key whose last segment only appears as a word is `weak`; neither is `unverified` | unverified: hard |
|
|
99
|
+
| Keys the code wires that no row maps (`codeKeysNotInMap`) | hard |
|
|
100
|
+
| `reuse` / `review` row without any legacy `en` or `tr` value | hard |
|
|
101
|
+
| Non-`new` row with an empty `new.tr` | soft |
|
|
102
|
+
| `new.tr` equal to `new.en` (untranslated) | soft |
|
|
103
|
+
| With `--resources-root`: no `Suggested/<Key>.json` in the snapshot or the source layout | soft |
|
|
104
|
+
|
|
105
|
+
A row is dynamic-exempt when its key starts with `(dynamic`, contains a `<placeholder>`, its element mentions dynamic, or its note says "enumerate at runtime". Exit 2 when any hard issue exists; publish only after fixing them (drop or fix UNVERIFIED keys, add rows for wired-but-unmapped keys) or after a conscious, stated waiver.
|
|
106
|
+
|
|
107
|
+
## Script reference
|
|
108
|
+
|
|
109
|
+
| Script | Key flags |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `scan-screen-keys.py` | `--screen-path` (required), `--out`, `--category all/error/dynamic/static` |
|
|
112
|
+
| `resolve-new-values.py` | `--keys`, `--keys-file` (`-` for stdin), `--resources-root` or `--suggested-dir`, `--domain localization/accessibility`, `--catalog`, `--report-source`, `--langs` (default `en,tr`, or `all`) |
|
|
113
|
+
| `resolve-legacy-values.py` | `--keys` (required), `--langs`, `--snapshot-root`, `--live`, `--endpoint`, `--header K=V`, `--headers-file`, `--env`, `--status-field`, `--fail-status CODE=message`, `--timeout`, `--plist-root`, `--prefix` |
|
|
114
|
+
| `fetch-legacy-labels.py` | `--out`, `--endpoint` (both required), `--header`, `--headers-file`, `--langs` (default `all`), `--env`, `--status-field`, `--fail-status`, `--timeout` |
|
|
115
|
+
| `fetch-annotations.py` | `--file`, `--nodes`, `--mapping`, `--from-mcp`, `--local`, `--source auto/rest/mcp/local`, `--token`, `--ca-file`, `--out` |
|
|
116
|
+
| `render-overlay.py` | `--mapping` (required), `--spec`, `--file`, `--nodes`, `--scale`, `--token`, `--ca-file`, `--out`, `--slug` |
|
|
117
|
+
| `render-key-shots.py` | `--mapping` (required), `--spec` (repeatable), `--file`, `--nodes`, `--pad` (default 150), `--scale`, `--token`, `--ca-file`, `--out`, `--slug` |
|
|
118
|
+
| `build-artifact.py` | `mapping` (or `-`), `--out`, `--slug`, `--ui-lang en/tr`, `--docx`, `--pdf`, `--all`, `--print-upload` |
|
|
119
|
+
| `build-spreadsheet.py` | `mapping` (or `-`), `--out`, `--slug`, `--channel`, `--taxonomy`, `--csv`, `--csv-only` |
|
|
120
|
+
| `verify-map.py` | `--mapping`, `--screen-path` (both required), `--resources-root`, `--out` |
|
|
121
|
+
| `publish-confluence.py` | see [publish-and-snapshot](publish-and-snapshot.md) |
|
|
122
|
+
| `snapshot-resources.sh` | `<resources-root> <specs-root>` |
|
|
123
|
+
|
|
124
|
+
`all` languages means `en, tr, ar, de, es, fr, it, ru` in every script. Every script derives the same slug from `screen`: lowercase, each run of non-letter, non-digit characters becomes one `-`, leading and trailing dashes trimmed, `screen` when nothing is left. `--slug` overrides it on any script. Figma tokens resolve from `--token`, then `FIGMA_ACCESS_TOKEN`, then `FIGMA_TOKEN`, then the macOS keychain item `FIGMA_ACCESS_TOKEN`; prefer the environment or keychain, since argv is visible to other processes.
|
package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md
CHANGED
|
@@ -1,108 +1,78 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Publishing and the resources snapshot
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
> how the redesign resources get snapshotted there so the whole flow is **single-repo** (like `design-export`).
|
|
3
|
+
## One repo to read from
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
The component registry and the Suggested translations are kept in their own resources repo. So that every lookup happens in a single place, a snapshot of both is copied into the specs repo under `resources/`, beside the design export:
|
|
7
6
|
|
|
8
|
-
The skill reads four sources. Three already live in `<specs-repo>` (`design-export/`, legacy iOS/Android,
|
|
9
|
-
the live label service over the network). The fourth - the redesign **component registry** and **Suggested
|
|
10
|
-
translations** - lives in `<resources-repo>`. Snapshotting those two into `<specs-repo>`
|
|
11
|
-
(exactly as `design-export/` is a manual/CI snapshot of Figma) removes the cross-repo round-trip: every
|
|
12
|
-
read is one repo.
|
|
13
|
-
|
|
14
|
-
**Layout** (top-level, mirroring `design-export`'s convention):
|
|
15
7
|
```
|
|
16
8
|
<specs-repo>/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
│ └── keyshot__<NN>__<key>.png
|
|
30
|
-
└── screenshot.png
|
|
9
|
+
resources/
|
|
10
|
+
Figma/Components/<node>.json
|
|
11
|
+
Localization/Suggested/<Key>.json
|
|
12
|
+
Localization/Legacy/<lang>.json
|
|
13
|
+
localizations/<screen-slug>/
|
|
14
|
+
<slug>.md
|
|
15
|
+
<slug>.confluence.xml
|
|
16
|
+
<slug>.overlay.png
|
|
17
|
+
<slug>.keyshots.manifest.json
|
|
18
|
+
<slug>.localization.xlsx
|
|
19
|
+
screenshot.png
|
|
20
|
+
keyshots/ (one keyshot__<NN>__<key>.png per row)
|
|
31
21
|
```
|
|
32
22
|
|
|
33
|
-
|
|
23
|
+
### Refreshing it
|
|
24
|
+
|
|
25
|
+
The refresh has two parts. The first runs locally, the second needs the network:
|
|
26
|
+
|
|
34
27
|
```bash
|
|
35
|
-
# 1. registry + new (Suggested) values - local copy from <resources-repo> (no network)
|
|
36
28
|
scripts/snapshot-resources.sh <resources-repo-root> <specs-repo-root>
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
python3 scripts/fetch-legacy-labels.py --langs all \
|
|
30
|
+
--out <specs-repo-root>/resources/Localization/Legacy \
|
|
31
|
+
--endpoint '<label-url-with-{lang}>' --headers-file <headers.json>
|
|
39
32
|
```
|
|
40
|
-
With the snapshot in place every read is in-repo - **no live label round-trip per run**:
|
|
41
|
-
- new values: `resolve-new-values.py --resources-root <specs-repo>/resources` (Suggested lives there)
|
|
42
|
-
- legacy values: `resolve-legacy-values.py --snapshot-root <specs-repo>/resources/Localization/Legacy`
|
|
43
|
-
(offline; `--live` only to verify/refresh, `--plist-root` as last resort).
|
|
44
33
|
|
|
45
|
-
|
|
34
|
+
`snapshot-resources.sh` copies `Resources/Figma/Components` and `Resources/Localization/LocalizationStrings/Sources/Suggested` with `rsync -a --delete`; a key or component deleted upstream therefore drops out of the snapshot as well. If either source folder is missing, the script stops with `missing source dir: <dir>`. `fetch-legacy-labels.py` saves a flat `<lang>.json` for every language, sorted by key, and leaves each key exactly as the service stores it, prefix and all. Credential headers belong in `--headers-file` and must not appear on the command line. The refreshed snapshot is committed like any design-export refresh.
|
|
46
35
|
|
|
47
|
-
|
|
48
|
-
exclusive:
|
|
36
|
+
### Guardrails
|
|
49
37
|
|
|
50
|
-
|
|
38
|
+
- The skill only adds: its writes are limited to `localizations/` and `resources/`.
|
|
39
|
+
- Legacy source, `design-export/` and `specs/` are never modified.
|
|
40
|
+
- `resources/` is a generated copy. Refresh it with the scripts; do not edit it by hand.
|
|
41
|
+
|
|
42
|
+
## Option A: Confluence (live page)
|
|
51
43
|
|
|
52
44
|
```bash
|
|
53
|
-
python3 scripts/publish-confluence.py
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
45
|
+
python3 scripts/publish-confluence.py \
|
|
46
|
+
--xml <slug>.confluence.xml --screen "<Screen name>" \
|
|
47
|
+
--overlay <slug>.overlay.png --screenshot screenshot.png \
|
|
48
|
+
--keyshots <slug>.keyshots.manifest.json \
|
|
49
|
+
--attach <slug>.localization.xlsx
|
|
58
50
|
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- **
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
- **
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
**`--attach <file>` (repeatable)** attaches any extra document
|
|
77
|
-
- pass `$SLUG.localization.xlsx` (the CMS import sheet, build-spreadsheet.py); office/spreadsheet files also
|
|
78
|
-
get a `view-file` macro appended to the body so they **render inline** under a "CMS transfer file" heading.
|
|
79
|
-
- The skill asks the user for the space / parent / title when the environment doesn't already pin them.
|
|
80
|
-
- `build-artifact.py ... --print-upload` prints the exact command (plus the raw Bearer `curl`) for copy-paste.
|
|
81
|
-
|
|
82
|
-
### B) <specs-repo> PR (in-repo record - optional)
|
|
83
|
-
|
|
84
|
-
Place the canonical set under `localizations/<slug>/` and open an additive PR:
|
|
51
|
+
|
|
52
|
+
- **Target**: `--base` / `--base-url`, `--space` and `--parent`, or the variables `CONFLUENCE_BASE_URL`, `CONFLUENCE_SPACE` and `CONFLUENCE_PARENT`.
|
|
53
|
+
- **Title**: `--title` when given; otherwise `<prefix> - <screen>`, with the prefix taken from `--title-prefix`, then `LOCALIZATION_PAGE_PREFIX`, then the default `Localization`.
|
|
54
|
+
- **Token**: a Server / Data Center personal access token, sent as a Bearer header. The script tries `--token`, then `CONFLUENCE_API_TOKEN`, then the macOS keychain service given by `--keychain-name` (default `CONFLUENCE_API_TOKEN`). Use the keychain where possible, because other processes can read argv.
|
|
55
|
+
- **Transport**: `curl` carries every request. The Authorization header is written to a temporary config file with mode 600, handed over with `-K` and removed at the end; JSON bodies also travel through a temporary file.
|
|
56
|
+
- **Idempotent**: the lookup is `GET /rest/api/content?spaceKey=&title=&type=page&expand=version&limit=5`, which reads the database rather than the CQL index. A hit is updated with `PUT` and the next version number, reported as `updated (vN->vN+1)`; a miss is created with `POST` below the parent and reported as `created`. A second run lands on the same page id.
|
|
57
|
+
- **Attachments**: the screenshot first, then the overlay, then each `.png` listed in the keyshots manifest, then every `--attach` file. When a file of that name is already attached, a new version is uploaded to `.../child/attachment/<id>/data` instead of adding a second copy.
|
|
58
|
+
- **Inline spreadsheet**: an `--attach` file with the extension `.xlsx`, `.xls`, `.csv`, `.docx` or `.pdf` is additionally shown on the page: a heading "CMS Aktarım Dosyası" is appended, then one `view-file` macro per such file.
|
|
59
|
+
- **Dry run**: with `--dry-run` nothing is sent; the script prints base, space, parent, title, body size, the attachment list and the action it would take.
|
|
60
|
+
- **Output**: a JSON object with `action`, `id`, `title`, `attachments` and `url`.
|
|
61
|
+
|
|
62
|
+
Running `build-artifact.py --print-upload` shows the publish command that fits the mapping, plus a hand-written Bearer `curl` version of it that pulls the token out of the keychain. When neither route works, paste the storage XML into the Confluence editor and attach the images under their file names; the XML already points at them by name.
|
|
63
|
+
|
|
64
|
+
## Option B: specs-repo pull request
|
|
65
|
+
|
|
66
|
+
Place the canonical files in `<specs-repo>/localizations/<slug>/`: the Markdown `<slug>.md`, the storage body `<slug>.confluence.xml`, the overlay `<slug>.overlay.png`, `screenshot.png`, the manifest `<slug>.keyshots.manifest.json` with its `keyshots/` folder, and the sheet `<slug>.localization.xlsx`. Then:
|
|
67
|
+
|
|
85
68
|
```bash
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
cd "$SPECS" && git switch -c "loc-map/$SLUG" \
|
|
92
|
-
&& git add "localizations/$SLUG" \
|
|
93
|
-
&& git commit -m "localizations: $SLUG reuse map" \
|
|
94
|
-
&& git push -u origin "loc-map/$SLUG" \
|
|
95
|
-
&& gh pr create --title "Localization reuse map - $SLUG" \
|
|
96
|
-
--body "Generated by the localization-reuse-map skill; screenshot + overlay included." --fill
|
|
69
|
+
git checkout -b loc-map/<slug>
|
|
70
|
+
git add localizations/<slug>
|
|
71
|
+
git commit --message "localizations: <slug> reuse map"
|
|
72
|
+
git push --set-upstream origin loc-map/<slug>
|
|
73
|
+
gh pr create --body "<summary, counts, gate result>" --title "Localization reuse map - <slug>"
|
|
97
74
|
```
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
+ overlay embedded). Keep these heavy binaries **out** of the PR - share them directly.
|
|
103
|
-
|
|
104
|
-
## Guardrails
|
|
105
|
-
- **Additive only.** This flow creates files under `localizations/` and `resources/`; it never edits
|
|
106
|
-
legacy source, `design-export/`, or `specs/`.
|
|
107
|
-
- The `resources/` snapshot is **generated, not authored** - never hand-edit it; refresh it from
|
|
108
|
-
`<resources-repo>` (its source of truth), same as `design-export/` is refreshed from Figma.
|
|
75
|
+
|
|
76
|
+
Because the PR adds files and touches nothing else, it merges without conflicts. Keep the large `.docx` and `.pdf` files out of it and send them to people directly.
|
|
77
|
+
|
|
78
|
+
A screen may go through both options. Before publishing, ask which option or options to use, the Confluence space, and which formats are wanted.
|