@harness-engineering/cli 1.6.2 → 1.8.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 (180) hide show
  1. package/dist/agents/personas/documentation-maintainer.yaml +3 -1
  2. package/dist/agents/personas/performance-guardian.yaml +23 -0
  3. package/dist/agents/personas/planner.yaml +27 -0
  4. package/dist/agents/personas/verifier.yaml +30 -0
  5. package/dist/agents/skills/claude-code/align-documentation/SKILL.md +13 -0
  6. package/dist/agents/skills/claude-code/cleanup-dead-code/SKILL.md +25 -1
  7. package/dist/agents/skills/claude-code/cleanup-dead-code/skill.yaml +5 -2
  8. package/dist/agents/skills/claude-code/detect-doc-drift/SKILL.md +12 -0
  9. package/dist/agents/skills/claude-code/enforce-architecture/SKILL.md +67 -1
  10. package/dist/agents/skills/claude-code/enforce-architecture/skill.yaml +5 -2
  11. package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +281 -0
  12. package/dist/agents/skills/claude-code/harness-accessibility/skill.yaml +51 -0
  13. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +119 -72
  14. package/dist/agents/skills/claude-code/harness-autopilot/skill.yaml +4 -2
  15. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +76 -4
  16. package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +2 -0
  17. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +487 -234
  18. package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +15 -2
  19. package/dist/agents/skills/claude-code/harness-codebase-cleanup/SKILL.md +226 -0
  20. package/dist/agents/skills/claude-code/harness-codebase-cleanup/skill.yaml +64 -0
  21. package/dist/agents/skills/claude-code/harness-dependency-health/SKILL.md +35 -6
  22. package/dist/agents/skills/claude-code/harness-dependency-health/skill.yaml +1 -1
  23. package/dist/agents/skills/claude-code/harness-design/SKILL.md +265 -0
  24. package/dist/agents/skills/claude-code/harness-design/skill.yaml +53 -0
  25. package/dist/agents/skills/claude-code/harness-design-mobile/SKILL.md +336 -0
  26. package/dist/agents/skills/claude-code/harness-design-mobile/skill.yaml +49 -0
  27. package/dist/agents/skills/claude-code/harness-design-system/SKILL.md +282 -0
  28. package/dist/agents/skills/claude-code/harness-design-system/skill.yaml +50 -0
  29. package/dist/agents/skills/claude-code/harness-design-web/SKILL.md +360 -0
  30. package/dist/agents/skills/claude-code/harness-design-web/skill.yaml +52 -0
  31. package/dist/agents/skills/claude-code/harness-docs-pipeline/SKILL.md +460 -0
  32. package/dist/agents/skills/claude-code/harness-docs-pipeline/skill.yaml +69 -0
  33. package/dist/agents/skills/claude-code/harness-execution/SKILL.md +73 -8
  34. package/dist/agents/skills/claude-code/harness-execution/skill.yaml +1 -0
  35. package/dist/agents/skills/claude-code/harness-hotspot-detector/SKILL.md +32 -6
  36. package/dist/agents/skills/claude-code/harness-hotspot-detector/skill.yaml +1 -1
  37. package/dist/agents/skills/claude-code/harness-i18n/SKILL.md +484 -0
  38. package/dist/agents/skills/claude-code/harness-i18n/skill.yaml +54 -0
  39. package/dist/agents/skills/claude-code/harness-i18n-process/SKILL.md +388 -0
  40. package/dist/agents/skills/claude-code/harness-i18n-process/skill.yaml +43 -0
  41. package/dist/agents/skills/claude-code/harness-i18n-workflow/SKILL.md +512 -0
  42. package/dist/agents/skills/claude-code/harness-i18n-workflow/skill.yaml +53 -0
  43. package/dist/agents/skills/claude-code/harness-impact-analysis/SKILL.md +51 -6
  44. package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +35 -1
  45. package/dist/agents/skills/claude-code/harness-knowledge-mapper/SKILL.md +46 -5
  46. package/dist/agents/skills/claude-code/harness-knowledge-mapper/skill.yaml +1 -1
  47. package/dist/agents/skills/claude-code/harness-onboarding/SKILL.md +19 -1
  48. package/dist/agents/skills/claude-code/harness-perf/SKILL.md +37 -8
  49. package/dist/agents/skills/claude-code/harness-perf/skill.yaml +3 -0
  50. package/dist/agents/skills/claude-code/harness-perf-tdd/SKILL.md +17 -4
  51. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +57 -3
  52. package/dist/agents/skills/claude-code/harness-planning/skill.yaml +2 -0
  53. package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +29 -9
  54. package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +562 -0
  55. package/dist/agents/skills/claude-code/harness-roadmap/skill.yaml +43 -0
  56. package/dist/agents/skills/claude-code/harness-security-review/SKILL.md +36 -2
  57. package/dist/agents/skills/claude-code/harness-security-review/skill.yaml +8 -6
  58. package/dist/agents/skills/claude-code/harness-security-scan/skill.yaml +1 -1
  59. package/dist/agents/skills/claude-code/harness-soundness-review/SKILL.md +1267 -0
  60. package/dist/agents/skills/claude-code/harness-soundness-review/skill.yaml +48 -0
  61. package/dist/agents/skills/claude-code/harness-test-advisor/SKILL.md +35 -6
  62. package/dist/agents/skills/claude-code/harness-verification/SKILL.md +66 -0
  63. package/dist/agents/skills/claude-code/harness-verification/skill.yaml +1 -0
  64. package/dist/agents/skills/claude-code/harness-verify/SKILL.md +37 -0
  65. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +15 -1
  66. package/dist/agents/skills/claude-code/validate-context-engineering/SKILL.md +12 -0
  67. package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +281 -0
  68. package/dist/agents/skills/gemini-cli/harness-accessibility/skill.yaml +51 -0
  69. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +119 -72
  70. package/dist/agents/skills/gemini-cli/harness-autopilot/skill.yaml +4 -2
  71. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/SKILL.md +226 -0
  72. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +64 -0
  73. package/dist/agents/skills/gemini-cli/harness-dependency-health/SKILL.md +35 -6
  74. package/dist/agents/skills/gemini-cli/harness-dependency-health/skill.yaml +1 -1
  75. package/dist/agents/skills/gemini-cli/harness-design/SKILL.md +265 -0
  76. package/dist/agents/skills/gemini-cli/harness-design/skill.yaml +53 -0
  77. package/dist/agents/skills/gemini-cli/harness-design-mobile/SKILL.md +336 -0
  78. package/dist/agents/skills/gemini-cli/harness-design-mobile/skill.yaml +49 -0
  79. package/dist/agents/skills/gemini-cli/harness-design-system/SKILL.md +282 -0
  80. package/dist/agents/skills/gemini-cli/harness-design-system/skill.yaml +50 -0
  81. package/dist/agents/skills/gemini-cli/harness-design-web/SKILL.md +360 -0
  82. package/dist/agents/skills/gemini-cli/harness-design-web/skill.yaml +52 -0
  83. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/SKILL.md +460 -0
  84. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/skill.yaml +69 -0
  85. package/dist/agents/skills/gemini-cli/harness-hotspot-detector/SKILL.md +32 -6
  86. package/dist/agents/skills/gemini-cli/harness-hotspot-detector/skill.yaml +1 -1
  87. package/dist/agents/skills/gemini-cli/harness-i18n/SKILL.md +484 -0
  88. package/dist/agents/skills/gemini-cli/harness-i18n/skill.yaml +54 -0
  89. package/dist/agents/skills/gemini-cli/harness-i18n-process/SKILL.md +388 -0
  90. package/dist/agents/skills/gemini-cli/harness-i18n-process/skill.yaml +43 -0
  91. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/SKILL.md +512 -0
  92. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/skill.yaml +53 -0
  93. package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +51 -6
  94. package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/SKILL.md +46 -5
  95. package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/skill.yaml +1 -1
  96. package/dist/agents/skills/gemini-cli/harness-perf/SKILL.md +37 -8
  97. package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +3 -0
  98. package/dist/agents/skills/gemini-cli/harness-perf-tdd/SKILL.md +17 -4
  99. package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +29 -9
  100. package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +562 -0
  101. package/dist/agents/skills/gemini-cli/harness-roadmap/skill.yaml +43 -0
  102. package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +8 -6
  103. package/dist/agents/skills/gemini-cli/harness-security-scan/skill.yaml +1 -1
  104. package/dist/agents/skills/gemini-cli/harness-soundness-review/SKILL.md +1267 -0
  105. package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +48 -0
  106. package/dist/agents/skills/gemini-cli/harness-test-advisor/SKILL.md +35 -6
  107. package/dist/agents/skills/node_modules/.bin/vitest +2 -2
  108. package/dist/agents/skills/shared/design-knowledge/anti-patterns/color.yaml +106 -0
  109. package/dist/agents/skills/shared/design-knowledge/anti-patterns/layout.yaml +109 -0
  110. package/dist/agents/skills/shared/design-knowledge/anti-patterns/motion.yaml +109 -0
  111. package/dist/agents/skills/shared/design-knowledge/anti-patterns/typography.yaml +112 -0
  112. package/dist/agents/skills/shared/design-knowledge/industries/creative.yaml +80 -0
  113. package/dist/agents/skills/shared/design-knowledge/industries/ecommerce.yaml +80 -0
  114. package/dist/agents/skills/shared/design-knowledge/industries/emerging-tech.yaml +83 -0
  115. package/dist/agents/skills/shared/design-knowledge/industries/fintech.yaml +80 -0
  116. package/dist/agents/skills/shared/design-knowledge/industries/healthcare.yaml +80 -0
  117. package/dist/agents/skills/shared/design-knowledge/industries/lifestyle.yaml +80 -0
  118. package/dist/agents/skills/shared/design-knowledge/industries/saas.yaml +80 -0
  119. package/dist/agents/skills/shared/design-knowledge/industries/services.yaml +80 -0
  120. package/dist/agents/skills/shared/design-knowledge/palettes/curated.yaml +234 -0
  121. package/dist/agents/skills/shared/design-knowledge/platform-rules/android.yaml +125 -0
  122. package/dist/agents/skills/shared/design-knowledge/platform-rules/flutter.yaml +144 -0
  123. package/dist/agents/skills/shared/design-knowledge/platform-rules/ios.yaml +106 -0
  124. package/dist/agents/skills/shared/design-knowledge/platform-rules/web.yaml +102 -0
  125. package/dist/agents/skills/shared/design-knowledge/typography/pairings.yaml +274 -0
  126. package/dist/agents/skills/shared/i18n-knowledge/accessibility/intersection.yaml +142 -0
  127. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/encoding.yaml +67 -0
  128. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/formatting.yaml +106 -0
  129. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/layout.yaml +80 -0
  130. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/pluralization.yaml +80 -0
  131. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/string-handling.yaml +106 -0
  132. package/dist/agents/skills/shared/i18n-knowledge/frameworks/android-resources.yaml +47 -0
  133. package/dist/agents/skills/shared/i18n-knowledge/frameworks/apple-strings.yaml +47 -0
  134. package/dist/agents/skills/shared/i18n-knowledge/frameworks/backend-patterns.yaml +50 -0
  135. package/dist/agents/skills/shared/i18n-knowledge/frameworks/flutter-intl.yaml +47 -0
  136. package/dist/agents/skills/shared/i18n-knowledge/frameworks/i18next.yaml +47 -0
  137. package/dist/agents/skills/shared/i18n-knowledge/frameworks/react-intl.yaml +47 -0
  138. package/dist/agents/skills/shared/i18n-knowledge/frameworks/vue-i18n.yaml +47 -0
  139. package/dist/agents/skills/shared/i18n-knowledge/industries/ecommerce.yaml +66 -0
  140. package/dist/agents/skills/shared/i18n-knowledge/industries/fintech.yaml +66 -0
  141. package/dist/agents/skills/shared/i18n-knowledge/industries/gaming.yaml +69 -0
  142. package/dist/agents/skills/shared/i18n-knowledge/industries/healthcare.yaml +66 -0
  143. package/dist/agents/skills/shared/i18n-knowledge/industries/legal.yaml +66 -0
  144. package/dist/agents/skills/shared/i18n-knowledge/locales/ar.yaml +41 -0
  145. package/dist/agents/skills/shared/i18n-knowledge/locales/de.yaml +35 -0
  146. package/dist/agents/skills/shared/i18n-knowledge/locales/en.yaml +32 -0
  147. package/dist/agents/skills/shared/i18n-knowledge/locales/es.yaml +35 -0
  148. package/dist/agents/skills/shared/i18n-knowledge/locales/fi.yaml +35 -0
  149. package/dist/agents/skills/shared/i18n-knowledge/locales/fr.yaml +35 -0
  150. package/dist/agents/skills/shared/i18n-knowledge/locales/he.yaml +41 -0
  151. package/dist/agents/skills/shared/i18n-knowledge/locales/hi.yaml +35 -0
  152. package/dist/agents/skills/shared/i18n-knowledge/locales/it.yaml +32 -0
  153. package/dist/agents/skills/shared/i18n-knowledge/locales/ja.yaml +38 -0
  154. package/dist/agents/skills/shared/i18n-knowledge/locales/ko.yaml +38 -0
  155. package/dist/agents/skills/shared/i18n-knowledge/locales/nl.yaml +32 -0
  156. package/dist/agents/skills/shared/i18n-knowledge/locales/pl.yaml +35 -0
  157. package/dist/agents/skills/shared/i18n-knowledge/locales/pt.yaml +32 -0
  158. package/dist/agents/skills/shared/i18n-knowledge/locales/ru.yaml +35 -0
  159. package/dist/agents/skills/shared/i18n-knowledge/locales/sv.yaml +32 -0
  160. package/dist/agents/skills/shared/i18n-knowledge/locales/th.yaml +35 -0
  161. package/dist/agents/skills/shared/i18n-knowledge/locales/tr.yaml +35 -0
  162. package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hans.yaml +38 -0
  163. package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hant.yaml +35 -0
  164. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/i18next-mcp.yaml +56 -0
  165. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lingo-dev.yaml +56 -0
  166. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lokalise.yaml +60 -0
  167. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/tolgee.yaml +60 -0
  168. package/dist/agents/skills/shared/i18n-knowledge/testing/locale-testing.yaml +107 -0
  169. package/dist/agents/skills/shared/i18n-knowledge/testing/pseudo-localization.yaml +86 -0
  170. package/dist/bin/harness.js +64 -4
  171. package/dist/{chunk-UDWGSL3T.js → chunk-3JWCBVUZ.js} +3 -3
  172. package/dist/{chunk-IUFFBBYV.js → chunk-LNI4T7R6.js} +179 -61
  173. package/dist/{chunk-USEYPS7F.js → chunk-SJECMKSS.js} +2250 -40
  174. package/dist/{dist-4MYPT3OE.js → dist-BDO5GFEM.js} +295 -14
  175. package/dist/{dist-RBZXXJHG.js → dist-NT3GXHQZ.js} +95 -1
  176. package/dist/index.d.ts +266 -7
  177. package/dist/index.js +7 -3
  178. package/dist/validate-cross-check-2OPGCGGU.js +7 -0
  179. package/package.json +7 -7
  180. package/dist/validate-cross-check-CPEPNLOD.js +0 -7
@@ -12,8 +12,21 @@
12
12
 
13
13
  ## Prerequisites
14
14
 
15
- A knowledge graph must exist at `.harness/graph/` with git history ingested. Run `harness scan` if no graph is available.
16
- If the graph exists but code has changed since the last scan, re-run `harness scan` first — stale graph data leads to inaccurate results.
15
+ A knowledge graph at `.harness/graph/` with git history enables full analysis. If no graph exists,
16
+ the skill uses static analysis fallbacks (see Graph Availability section).
17
+ Run `harness scan` to enable graph-enhanced analysis.
18
+
19
+ ### Graph Availability
20
+
21
+ Before starting, check if `.harness/graph/graph.json` exists.
22
+
23
+ **If graph exists:** Use graph tools as primary strategy. (Staleness sensitivity: **Low** — never auto-refresh.
24
+ Git-based churn data in the graph remains useful even when slightly stale.)
25
+
26
+ **If graph exists and is fresh (or refreshed):** Use graph tools as primary strategy.
27
+
28
+ **If no graph exists:** Output "Running without graph (run `harness scan` to
29
+ enable full analysis)" and use fallback strategies for all subsequent steps.
17
30
 
18
31
  ## Process
19
32
 
@@ -48,6 +61,19 @@ Rank files by:
48
61
 
49
62
  High churn in shared utilities or core modules = high risk.
50
63
 
64
+ #### Fallback (without graph)
65
+
66
+ When no graph is available, git log provides nearly all the data needed (~90% completeness):
67
+
68
+ 1. **Per-file churn**: `git log --format="%H" -- <file>` for each source file (use glob to enumerate). Count commits per file. Sort descending to rank by churn.
69
+ 2. **Recent velocity**: `git log --since="30 days ago" --format="%H" -- <file>` vs `git log --since="60 days ago" --until="30 days ago" --format="%H" -- <file>` to compare recent vs prior 30-day windows.
70
+ 3. **Co-change detection**: `git log --format="%H %n" --name-only` to build a map of which files changed together in the same commit. File pairs that appear together in >3 commits are co-change candidates.
71
+ 4. **Distant co-change identification**: For co-change pairs, check if they share a parent directory (co-located = normal) or are in different modules (distant = suspicious).
72
+ 5. **Complexity proxy**: Use line count (`wc -l`) as a rough proxy for complexity when graph complexity metrics are unavailable.
73
+ 6. **Hidden dependency detection**: Cross-reference co-change pairs against import parsing (grep for import statements). Co-change pairs with no import relationship indicate hidden dependencies.
74
+
75
+ > Fallback completeness: ~90% — git log provides nearly all the data the graph stores for this use case.
76
+
51
77
  ### Phase 3: COUPLING — Detect Hidden Dependencies
52
78
 
53
79
  Cross-reference co-change data with structural data:
@@ -90,7 +116,7 @@ Use `get_relationships` to check structural edges between co-change pairs.
90
116
 
91
117
  ## Harness Integration
92
118
 
93
- - **`harness scan`** — Must run before this skill to ensure graph is current.
119
+ - **`harness scan`** — Recommended before this skill for full graph-enhanced analysis. If graph is missing, skill uses git log fallbacks.
94
120
  - **`harness validate`** — Run after acting on findings to verify project health.
95
121
  - **Graph tools** — This skill uses `query_graph`, `get_impact`, and `get_relationships` MCP tools.
96
122
 
@@ -100,7 +126,7 @@ Use `get_relationships` to check structural edges between co-change pairs.
100
126
  - Hidden dependencies identified (high co-change, no structural edge)
101
127
  - Co-change patterns detected and classified (co-located vs distant)
102
128
  - Report follows the structured output format
103
- - All findings are backed by graph query evidence, not heuristics
129
+ - All findings are backed by graph query evidence (with graph) or git log analysis (without graph)
104
130
 
105
131
  ## Examples
106
132
 
@@ -126,8 +152,8 @@ Output:
126
152
 
127
153
  ## Gates
128
154
 
129
- - **No analysis without graph + git data.** Both code structure and git history must be ingested.
130
- - **No guessing at co-change patterns.** Use graph `co_changes_with` edges, not manual git log parsing.
155
+ - **Graph preferred, fallback available.** If no graph exists, use git log for churn and co-change analysis. Do not stop — git log provides ~90% of the data needed.
156
+ - **Systematic analysis required.** Use graph `co_changes_with` edges when available; use `git log` commit analysis when not. Do not guess — parse actual git history.
131
157
 
132
158
  ## Escalation
133
159
 
@@ -4,7 +4,7 @@ description: Identify structural risk hotspots via co-change and churn analysis
4
4
  cognitive_mode: analytical-reporter
5
5
  triggers:
6
6
  - manual
7
- - scheduled
7
+ - on_milestone
8
8
  platforms:
9
9
  - claude-code
10
10
  - gemini-cli
@@ -0,0 +1,484 @@
1
+ # Harness i18n
2
+
3
+ > Internationalization compliance verification. Detect hardcoded strings, missing translations, locale-sensitive formatting, RTL issues, and concatenation anti-patterns across web, mobile, and backend codebases.
4
+
5
+ ## When to Use
6
+
7
+ - Auditing new or existing codebases for i18n compliance
8
+ - Before PR merge to catch i18n regressions
9
+ - When `on_pr` or `on_commit` triggers fire and changes touch user-facing strings
10
+ - When translation files change (missing keys, untranslated values)
11
+ - After adding a new target locale to verify coverage
12
+ - When `on_review` triggers fire to validate i18n considerations
13
+ - NOT for setting up translation infrastructure (use harness-i18n-workflow)
14
+ - NOT for injecting i18n into brainstorming/planning (use harness-i18n-process)
15
+ - NOT for performing translations (use TMS tools or MCP integrations)
16
+ - NOT for non-user-facing code (internal logging, debug messages, developer tooling)
17
+
18
+ ## Process
19
+
20
+ ### Phase 1: DETECT -- Identify i18n Context
21
+
22
+ 1. **Read harness configuration.** Check `harness.config.json` for `i18n` block:
23
+ - `i18n.enabled` -- master toggle (if false or missing, run in discovery mode: detect but do not enforce)
24
+ - `i18n.strictness` -- enforcement level (`strict`, `standard`, `permissive`)
25
+ - `i18n.sourceLocale` -- BCP 47 code of source language (default: `en`)
26
+ - `i18n.targetLocales` -- array of BCP 47 codes for target languages
27
+ - `i18n.framework` -- `auto` or specific framework name
28
+ - `i18n.platforms` -- which platforms to scan (`web`, `mobile`, `backend`)
29
+ - `i18n.coverage` -- coverage thresholds and requirements
30
+
31
+ 2. **Auto-detect project platform(s).** Scan project root for:
32
+ - Web: `package.json` with React/Vue/Svelte/Next/Nuxt deps, `.tsx`/`.jsx`/`.vue`/`.svelte` files
33
+ - Mobile iOS: `*.xcodeproj`, `Podfile`, `Package.swift`, `.swift` files
34
+ - Mobile Android: `build.gradle`/`build.gradle.kts`, `AndroidManifest.xml`, `.kt`/`.java` files
35
+ - Mobile Flutter: `pubspec.yaml` with `flutter` dependency, `.dart` files
36
+ - Backend: `package.json` with Express/Fastify/NestJS, `requirements.txt`/`pyproject.toml`, `go.mod`, `pom.xml`/`build.gradle`
37
+
38
+ 3. **Auto-detect i18n framework.** Read framework detection profiles from `agents/skills/shared/i18n-knowledge/frameworks/`. For each profile, check:
39
+ - `detection.package_json_keys` -- dependencies and devDependencies in `package.json`
40
+ - `detection.config_files` -- presence of framework config files
41
+ - `detection.file_patterns` -- translation file patterns
42
+ - Match the first profile that satisfies detection criteria. If none match, record "no i18n framework detected."
43
+
44
+ 4. **Locate existing translation files.** Search for:
45
+ - JSON files in `locales/`, `src/locales/`, `public/locales/`, `assets/translations/`
46
+ - `.strings` and `.stringsdict` files (iOS)
47
+ - `res/values*/strings.xml` (Android)
48
+ - `.arb` files (Flutter)
49
+ - PO/POT files (gettext)
50
+ - If `i18n.translationPaths` is configured, use those paths instead.
51
+
52
+ 5. **Load locale profiles.** For each locale in `i18n.targetLocales` (or detected from translation files), read the locale profile from `agents/skills/shared/i18n-knowledge/locales/{locale}.yaml`. This provides: plural rules, text direction, expansion factor, script characteristics, common pitfalls.
53
+
54
+ 6. **Load industry profile.** If `i18n.industry` is configured, read `agents/skills/shared/i18n-knowledge/industries/{industry}.yaml` for industry-specific rules.
55
+
56
+ 7. **Report detection results before proceeding:**
57
+
58
+ ```
59
+ i18n Detection Report
60
+ =====================
61
+ Config: Found (i18n.enabled: true, strictness: standard)
62
+ Platform(s): web, backend
63
+ Framework: i18next (detected from package.json)
64
+ Translation files: public/locales/{en,es,fr}/*.json (3 locales, 4 namespaces)
65
+ Source locale: en
66
+ Target locales: es, fr
67
+ Industry profile: fintech (loaded)
68
+ ```
69
+
70
+ ### Phase 2: SCAN -- Detect i18n Violations
71
+
72
+ 1. **Determine scan scope.** Based on detected platforms, select file patterns:
73
+ - Web: `**/*.{tsx,jsx,vue,svelte,html}` and `**/*.{ts,js}` (for template literals in rendering code)
74
+ - Mobile iOS: `**/*.swift`
75
+ - Mobile Android: `**/*.{kt,java}`, `**/res/values*/*.xml`
76
+ - Mobile Flutter: `**/*.dart`
77
+ - Backend: `**/*.{ts,js,py,go,java}` (filtered to HTTP handlers, templates, email services)
78
+ - Exclude: `node_modules`, `build`, `dist`, `.next`, `vendor`, `Pods`, test files (unless explicitly included)
79
+
80
+ 2. **Scan for hardcoded user-facing strings.** For each platform, apply these detection rules:
81
+
82
+ _Web (React/Vue/Svelte/vanilla):_
83
+ - `I18N-001` String literals in JSX text content (text nodes between tags)
84
+ - `I18N-002` String literals in i18n-sensitive props: `title`, `placeholder`, `alt`, `aria-label`, `aria-description`
85
+ - `I18N-003` Template literals with user-facing text in JSX or template expressions
86
+ - Exclude: CSS class names, data attributes, event names, `key` prop, `id`, `data-testid`, `className`, `style`, `type`, `role`, `htmlFor`, `ref`, numeric literals, boolean props, import/require paths
87
+
88
+ _Mobile iOS (SwiftUI/UIKit):_
89
+ - `I18N-011` String literals in `Text()`, `Label()`, `Alert()`, `.navigationTitle()`, `.toolbar` labels
90
+ - `I18N-012` String literals in `UILabel.text`, `UIButton.setTitle`, `UIAlertController` messages
91
+ - Exclude: SF Symbol names, asset names, notification names, UserDefaults keys
92
+
93
+ _Mobile Android (Compose/Views):_
94
+ - `I18N-021` String literals in `Text()`, `TextField()`, `Button()` content
95
+ - `I18N-022` String literals in `setText()`, `setTitle()`, `Toast.makeText()`
96
+ - Exclude: Log tags, intent actions, preference keys, layout identifiers
97
+
98
+ _Mobile Flutter:_
99
+ - `I18N-031` String literals in `Text()`, `TextSpan()`, `AppBar(title:)`, `SnackBar(content:)`
100
+ - Exclude: route names, asset paths, key values
101
+
102
+ _Backend:_
103
+ - `I18N-041` String literals in HTTP response bodies (`res.json({ message: '...' })`, `res.send('...')`)
104
+ - `I18N-042` String literals in email template content (detected via email service imports)
105
+ - `I18N-043` String literals in notification payloads
106
+ - Exclude: log messages (unless returned to users), internal error codes, header names, route paths
107
+
108
+ 3. **Scan for locale-sensitive formatting.**
109
+ - `I18N-101` `new Date().toLocaleDateString()` without explicit locale argument
110
+ - `I18N-102` `Number.toFixed()`, `.toLocaleString()` without locale argument
111
+ - `I18N-103` Hardcoded currency symbols (`$`, `EUR`, etc.) in string templates
112
+ - `I18N-104` Hardcoded decimal separators (`.` for decimal, `,` for thousands)
113
+ - `I18N-105` `new Intl.DateTimeFormat()` or `new Intl.NumberFormat()` without locale parameter (using implicit browser locale is often a bug)
114
+
115
+ 4. **Scan for missing `lang`/`dir` attributes.**
116
+ - `I18N-201` Missing `lang` attribute on `<html>` element
117
+ - `I18N-202` Missing `dir` attribute on `<html>` element (required when any target locale is RTL)
118
+ - `I18N-203` Missing `dir="auto"` on user-generated content containers (detected via heuristic: elements rendering user input, comments, messages)
119
+ - `I18N-204` Hardcoded `left`/`right` in CSS or style props instead of logical properties (`start`/`end`, `inline-start`/`inline-end`) -- only flagged when RTL locales are in target list
120
+
121
+ 5. **Scan for string concatenation.**
122
+ - `I18N-301` String concatenation to build user-facing messages (`"Hello, " + name`, `` `Welcome ${name}` `` used as complete messages)
123
+ - `I18N-302` Array `.join()` to build sentences or messages
124
+ - `I18N-303` Conditional text assembly (`isPlural ? "items" : "item"` -- hardcoded plural logic)
125
+ - Provide framework-specific alternative in the finding (e.g., for i18next: `t('greeting', { name })`)
126
+
127
+ 6. **Scan translation files for completeness.**
128
+ - `I18N-401` Missing keys: keys present in source locale file but absent in target locale file
129
+ - `I18N-402` Untranslated values: values in target locale file identical to source locale (suggesting copy-paste, not translation)
130
+ - `I18N-403` Missing plural forms: for each locale, check that all required CLDR plural categories are present. Load plural rules from locale profile (e.g., Arabic requires: zero, one, two, few, many, other).
131
+ - `I18N-404` Empty translation values (key exists but value is empty string)
132
+ - `I18N-405` Orphan keys: keys in translation files not referenced in source code (requires cross-referencing with source scan)
133
+
134
+ 7. **Record all findings.** Each finding includes:
135
+ - File path
136
+ - Line number (approximate, from Grep output)
137
+ - Violation code (e.g., `I18N-001`)
138
+ - Category: `strings`, `formatting`, `attributes`, `concatenation`, `translations`
139
+ - Element or pattern that triggered the finding
140
+ - Raw evidence (the matching line of code)
141
+
142
+ ### Phase 3: REPORT -- Generate i18n Report
143
+
144
+ 1. **Assign severity based on `i18n.strictness`:**
145
+ - `strict` mode: all violations are `error` severity
146
+ - `standard` mode: hardcoded strings and missing translations are `error`; formatting and concatenation are `warn`; orphan keys and info patterns are `info`
147
+ - `permissive` mode: missing translations and hardcoded strings are `warn`; everything else is `info`
148
+ - Discovery mode (unconfigured): all findings are `info`
149
+
150
+ 2. **Generate summary header:**
151
+
152
+ ```
153
+ i18n Report
154
+ ===========
155
+ Scanned: 87 source files, 12 translation files
156
+ Findings: 24 total (8 error, 12 warn, 4 info)
157
+ Strictness: standard
158
+ Framework: i18next
159
+ Platforms: web, backend
160
+ Locales: en (source), es, fr (targets)
161
+ ```
162
+
163
+ 3. **List findings grouped by category.** Each finding follows this format:
164
+
165
+ ```
166
+ I18N-001 [error] Hardcoded string in JSX text content
167
+ File: src/components/Header.tsx
168
+ Line: 12
169
+ Element: <h1>Welcome to our platform</h1>
170
+ Category: strings
171
+ Fix: Wrap in translation: <h1>{t('header.welcome')}</h1>
172
+ ```
173
+
174
+ ```
175
+ I18N-401 [error] Missing translation key
176
+ File: public/locales/es/common.json
177
+ Key: checkout.summary.totalLabel
178
+ Source: "Total" (en)
179
+ Category: translations
180
+ Fix: Add key to es/common.json with Spanish translation
181
+ ```
182
+
183
+ 4. **Provide category summaries** with counts and severity breakdown:
184
+
185
+ ```
186
+ Category Breakdown
187
+ ------------------
188
+ Strings: 12 findings (6 error, 4 warn, 2 info)
189
+ Translations: 6 findings (4 error, 2 warn)
190
+ Formatting: 3 findings (0 error, 3 warn)
191
+ Attributes: 2 findings (1 error, 1 warn)
192
+ Concatenation: 1 finding (0 error, 1 warn)
193
+ ```
194
+
195
+ 5. **Provide translation coverage summary** (if translation files exist):
196
+
197
+ ```
198
+ Translation Coverage
199
+ --------------------
200
+ Locale Keys Translated Coverage Missing Plurals
201
+ en 142 142 100% 0
202
+ es 142 128 90.1% 2
203
+ fr 142 135 95.1% 0
204
+ ```
205
+
206
+ 6. **If graph is available** (`.harness/graph/` exists): map findings to components/routes for contextual coverage. Report per-component translation coverage.
207
+
208
+ 7. **If graph is unavailable**: report per-file key-level coverage. Group findings by source file.
209
+
210
+ 8. **List actionable next steps:**
211
+ - Errors that can be auto-fixed (Phase 4)
212
+ - Errors that require human judgment (choosing translation keys, writing translations)
213
+ - Warnings to address in next iteration
214
+ - Coverage gaps to escalate to translation workflow (harness-i18n-workflow)
215
+
216
+ ### Phase 4: FIX -- Apply Automated Remediation (Optional)
217
+
218
+ This phase is optional. It applies fixes only for mechanical issues -- violations with a single, unambiguous correct fix. Translation content, key naming, and locale-specific formatting choices are never auto-fixed.
219
+
220
+ 1. **Fixable violations:**
221
+ - `I18N-001`/`I18N-002`: Wrap string literals in framework translation call. Detect framework from Phase 1:
222
+ - i18next: `{t('generated.key')}` (generate key from string content, dot-notation)
223
+ - react-intl: `<FormattedMessage id="generated.key" defaultMessage="original text" />`
224
+ - vue-i18n: `{{ $t('generated.key') }}`
225
+ - No framework: `{t('generated.key')}` (generic, user picks framework later)
226
+ - `I18N-201`: Add `lang="{sourceLocale}"` to `<html>` element
227
+ - `I18N-202`: Add `dir="ltr"` (or `dir="auto"` if RTL locales are targets) to `<html>` element
228
+ - `I18N-203`: Add `dir="auto"` to user-content containers
229
+ - `I18N-404`: Flag empty translation values for review (not auto-fillable)
230
+
231
+ 2. **Apply each fix as a minimal, targeted edit.** Use the Edit tool. Do not refactor surrounding code. Do not change formatting. The fix should be the smallest possible change that resolves the violation.
232
+
233
+ 3. **Show before/after diff for each fix.** Present the exact change to the user. This is a hard gate -- no fix is applied without showing the diff first.
234
+
235
+ 4. **Interactive confirmation per fix category.** Group fixes by category (string wrapping, attribute addition) and ask for approval per category, not per individual fix:
236
+
237
+ ```
238
+ Fix Category: String Wrapping (12 fixes)
239
+ -----------------------------------------
240
+ Wrap 12 hardcoded strings in t() calls across 5 files.
241
+ Generated keys follow dot-notation: component.element.description
242
+
243
+ Apply these fixes? [y/n]
244
+ ```
245
+
246
+ 5. **Generate extraction output.** For each wrapped string, output the key-value pair that needs to be added to the source locale translation file:
247
+
248
+ ```json
249
+ {
250
+ "header.welcome": "Welcome to our platform",
251
+ "checkout.totalLabel": "Total",
252
+ "auth.loginButton": "Sign in"
253
+ }
254
+ ```
255
+
256
+ 6. **Re-scan after fixes.** Run the scan phase again on fixed files to confirm violations are resolved. Report:
257
+ - Fixes applied: N
258
+ - Violations resolved: N
259
+ - Keys extracted: N (add to source locale file)
260
+ - Remaining violations (require human judgment): M
261
+
262
+ 7. **Do NOT fix:**
263
+ - Translation content (requires human translators or TMS)
264
+ - Key naming beyond generated defaults (requires project context)
265
+ - Locale-sensitive formatting (requires knowing the correct Intl API usage for each case)
266
+ - Plural form additions (requires CLDR knowledge + framework-specific syntax)
267
+ - Any fix that would change the runtime behavior of the application
268
+
269
+ ## Harness Integration
270
+
271
+ - **`harness validate`** -- i18n findings surface when `i18n.enabled` is true and `i18n.strictness` is `strict` or `standard`. Running validate after a scan reflects the current i18n state.
272
+ - **`harness-integrity`** -- The i18n scan is chained into integrity checks when `i18n.enabled: true`. Findings are included in the unified integrity report.
273
+ - **`harness-release-readiness`** -- Translation coverage is checked against `i18n.coverage.minimumPercent`. Per-locale coverage is reported.
274
+ - **`harness-accessibility`** -- When both i18n and accessibility skills are enabled, `lang`/`dir` attribute checks are handled by the i18n skill. The accessibility skill defers I18N-201/202/203 to avoid duplicate findings.
275
+ - **`harness-i18n-workflow`** -- After scanning, coverage gaps and extracted keys can be passed to the workflow skill for scaffolding and translation file updates.
276
+ - **Knowledge base** at `agents/skills/shared/i18n-knowledge/` -- Framework profiles, locale profiles, industry profiles, and anti-pattern catalogs are consumed during detect and scan phases.
277
+
278
+ ## Success Criteria
279
+
280
+ - All scanned source files have findings categorized by violation code and severity
281
+ - Hardcoded user-facing strings detected with correct platform-specific rules (web, mobile, backend)
282
+ - Missing translation keys and untranslated values identified with file paths and key names
283
+ - Locale-sensitive formatting issues (dates, numbers, currencies) flagged with specific file and line references
284
+ - RTL and `lang`/`dir` attribute violations detected when target locales include RTL languages
285
+ - String concatenation and hardcoded plural logic identified as anti-patterns
286
+ - Report generated with violation codes, categories, severity, and actionable remediation
287
+ - Automated fixes applied only for mechanical issues (string wrapping, attribute addition) with interactive confirmation
288
+ - Translation coverage reported per-locale against configured thresholds
289
+ - `harness validate` reflects i18n findings at the configured strictness level
290
+
291
+ ## Examples
292
+
293
+ ### Example: Scanning a React + i18next Project
294
+
295
+ **Context:** A React web app using i18next with English source, targeting Spanish and French. The `harness.config.json` has:
296
+
297
+ ```json
298
+ {
299
+ "version": 1,
300
+ "i18n": {
301
+ "enabled": true,
302
+ "strictness": "standard",
303
+ "sourceLocale": "en",
304
+ "targetLocales": ["es", "fr"],
305
+ "framework": "auto",
306
+ "platforms": ["web"]
307
+ }
308
+ }
309
+ ```
310
+
311
+ **Phase 1: DETECT**
312
+
313
+ ```
314
+ i18n Detection Report
315
+ =====================
316
+ Config: Found (i18n.enabled: true, strictness: standard)
317
+ Platform(s): web
318
+ Framework: i18next (detected from package.json: "i18next", "react-i18next")
319
+ Translation files: public/locales/{en,es,fr}/common.json (3 locales, 1 namespace)
320
+ Source locale: en
321
+ Target locales: es, fr
322
+ Industry profile: none configured
323
+ ```
324
+
325
+ **Phase 2: SCAN**
326
+
327
+ Source file with violations:
328
+
329
+ ```tsx
330
+ // src/components/CheckoutSummary.tsx
331
+ export function CheckoutSummary({ items, total }) {
332
+ return (
333
+ <div>
334
+ <h2>Order Summary</h2>
335
+ <p>
336
+ You have {items.length} {items.length === 1 ? 'item' : 'items'} in your cart.
337
+ </p>
338
+ <span title="Total price">Total: ${total.toFixed(2)}</span>
339
+ </div>
340
+ );
341
+ }
342
+ ```
343
+
344
+ Findings:
345
+
346
+ ```
347
+ I18N-001 [error] Hardcoded string in JSX text content
348
+ File: src/components/CheckoutSummary.tsx
349
+ Line: 5
350
+ Element: <h2>Order Summary</h2>
351
+ Category: strings
352
+ Fix: Wrap in translation: <h2>{t('checkout.orderSummary')}</h2>
353
+
354
+ I18N-002 [error] Hardcoded string in i18n-sensitive prop
355
+ File: src/components/CheckoutSummary.tsx
356
+ Line: 9
357
+ Element: title="Total price"
358
+ Category: strings
359
+ Fix: Wrap in translation: title={t('checkout.totalPriceTitle')}
360
+
361
+ I18N-303 [warn] Conditional text assembly (hardcoded plural logic)
362
+ File: src/components/CheckoutSummary.tsx
363
+ Line: 7
364
+ Element: items.length === 1 ? "item" : "items"
365
+ Category: concatenation
366
+ Fix: Use i18next plural: t('checkout.itemCount', { count: items.length })
367
+
368
+ I18N-103 [warn] Hardcoded currency symbol
369
+ File: src/components/CheckoutSummary.tsx
370
+ Line: 10
371
+ Element: $${total.toFixed(2)}
372
+ Category: formatting
373
+ Fix: Use Intl.NumberFormat: new Intl.NumberFormat(locale, { style: 'currency', currency }).format(total)
374
+
375
+ I18N-102 [warn] Number.toFixed() without locale-aware formatting
376
+ File: src/components/CheckoutSummary.tsx
377
+ Line: 10
378
+ Element: total.toFixed(2)
379
+ Category: formatting
380
+ Fix: Use Intl.NumberFormat for locale-aware decimal formatting
381
+ ```
382
+
383
+ Translation file issue:
384
+
385
+ ```
386
+ I18N-401 [error] Missing translation key
387
+ File: public/locales/es/common.json
388
+ Key: checkout.confirmButton
389
+ Source: "Confirm Order" (en)
390
+ Category: translations
391
+ Fix: Add key to es/common.json with Spanish translation
392
+
393
+ I18N-402 [warn] Untranslated value (identical to source)
394
+ File: public/locales/fr/common.json
395
+ Key: auth.welcomeMessage
396
+ Source: "Welcome back" (en)
397
+ Value: "Welcome back" (fr -- same as source, likely untranslated)
398
+ Category: translations
399
+ Fix: Translate value to French or mark as intentionally identical
400
+ ```
401
+
402
+ **Phase 3: REPORT**
403
+
404
+ ```
405
+ i18n Report
406
+ ===========
407
+ Scanned: 23 source files, 6 translation files
408
+ Findings: 7 total (3 error, 3 warn, 1 info)
409
+ Strictness: standard
410
+ Framework: i18next
411
+ Platforms: web
412
+ Locales: en (source), es, fr (targets)
413
+
414
+ Category Breakdown
415
+ ------------------
416
+ Strings: 2 findings (2 error, 0 warn)
417
+ Translations: 2 findings (1 error, 1 warn)
418
+ Formatting: 2 findings (0 error, 2 warn)
419
+ Concatenation: 1 finding (0 error, 1 warn)
420
+
421
+ Translation Coverage
422
+ --------------------
423
+ Locale Keys Translated Coverage Missing Plurals
424
+ en 42 42 100% 0
425
+ es 42 41 97.6% 0
426
+ fr 42 42 100% 0
427
+ (note: fr has 1 untranslated value not counted as missing)
428
+ ```
429
+
430
+ **Phase 4: FIX**
431
+
432
+ ```
433
+ Fix Category: String Wrapping (2 fixes)
434
+ -----------------------------------------
435
+ Wrap 2 hardcoded strings in t() calls in CheckoutSummary.tsx.
436
+ Generated keys: checkout.orderSummary, checkout.totalPriceTitle
437
+
438
+ Apply these fixes? [y/n]
439
+ ```
440
+
441
+ After applying fixes:
442
+
443
+ ```diff
444
+ - <h2>Order Summary</h2>
445
+ + <h2>{t('checkout.orderSummary')}</h2>
446
+
447
+ - <span title="Total price">
448
+ + <span title={t('checkout.totalPriceTitle')}>
449
+ ```
450
+
451
+ Keys extracted for source locale file:
452
+
453
+ ```json
454
+ {
455
+ "checkout.orderSummary": "Order Summary",
456
+ "checkout.totalPriceTitle": "Total price"
457
+ }
458
+ ```
459
+
460
+ Remaining violations (require human judgment): 5
461
+
462
+ - I18N-303: Plural logic -- requires choosing i18next plural key structure
463
+ - I18N-103: Currency symbol -- requires knowing the correct currency code per locale
464
+ - I18N-102: Number formatting -- requires choosing Intl.NumberFormat options
465
+ - I18N-401: Missing key in es -- requires Spanish translation
466
+ - I18N-402: Untranslated value in fr -- requires French translation
467
+
468
+ ## Gates
469
+
470
+ These are hard stops. Violating any gate means the process has broken down.
471
+
472
+ - **No scan results without completing the detect phase first.** Framework and platform detection must run before scanning begins.
473
+ - **No fix applied without showing the before/after diff.** Every fix must be presented to the user with the exact code change before being written to disk.
474
+ - **No severity downgrade below what `i18n.strictness` specifies.** If the project is in `strict` mode, a hardcoded string is an error. The scanner does not get to decide it is a warning.
475
+ - **No translation content generated by the fix phase.** The fix phase wraps strings and adds attributes. It does not write translations. Translation content is the domain of humans or TMS tools.
476
+ - **No false-positive suppression without explicit user confirmation.** If a string is intentionally not translated (e.g., brand name), the user must mark it with a suppression comment (`// i18n-ignore`) before it is excluded from future scans.
477
+
478
+ ## Escalation
479
+
480
+ - **When a project has more than 100 hardcoded strings:** suggest running harness-i18n-workflow for bulk extraction and scaffolding rather than fixing one by one.
481
+ - **When no i18n framework is detected:** recommend one based on the project platform (i18next for React/Node, vue-i18n for Vue, flutter intl for Flutter, etc.). Reference the framework profiles in the knowledge base.
482
+ - **When translation coverage is below 50%:** suggest a phased approach -- prioritize user-facing flows (checkout, onboarding, error messages) before attempting full coverage.
483
+ - **When target locales include RTL languages (ar, he) and the project has no RTL support:** flag this as a high-priority architectural concern. RTL support often requires layout changes beyond simple attribute additions.
484
+ - **When the project uses a framework not in the knowledge base:** fall back to generic detection rules. Log: "Framework {name} not in knowledge base -- using generic string detection. Consider contributing a framework profile."
@@ -0,0 +1,54 @@
1
+ name: harness-i18n
2
+ version: "1.0.0"
3
+ description: Internationalization scanning — detect hardcoded strings, missing translations, locale-sensitive formatting, RTL issues, and generate actionable reports across web, mobile, and backend
4
+ cognitive_mode: meticulous-verifier
5
+ triggers:
6
+ - manual
7
+ - on_pr
8
+ - on_commit
9
+ - on_review
10
+ platforms:
11
+ - claude-code
12
+ - gemini-cli
13
+ tools:
14
+ - Bash
15
+ - Read
16
+ - Write
17
+ - Edit
18
+ - Glob
19
+ - Grep
20
+ cli:
21
+ command: harness skill run harness-i18n
22
+ args:
23
+ - name: path
24
+ description: Project root path
25
+ required: false
26
+ - name: scope
27
+ description: Scope of scan (full, component, file)
28
+ required: false
29
+ - name: platform
30
+ description: Target platform override (web, mobile, backend)
31
+ required: false
32
+ mcp:
33
+ tool: run_skill
34
+ input:
35
+ skill: harness-i18n
36
+ path: string
37
+ type: rigid
38
+ phases:
39
+ - name: detect
40
+ description: Identify project platform(s), i18n framework in use, existing translation files, and locale config
41
+ required: true
42
+ - name: scan
43
+ description: Scan source files for i18n violations — hardcoded strings, locale-sensitive formatting, missing translations, RTL issues
44
+ required: true
45
+ - name: report
46
+ description: Group findings by severity and category, generate structured i18n report
47
+ required: true
48
+ - name: fix
49
+ description: Apply automated fixes for mechanical i18n issues (string wrapping, lang/dir attributes)
50
+ required: false
51
+ state:
52
+ persistent: false
53
+ files: []
54
+ depends_on: []