@harness-engineering/cli 1.7.0 → 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.
- package/dist/agents/personas/documentation-maintainer.yaml +3 -1
- package/dist/agents/personas/performance-guardian.yaml +23 -0
- package/dist/agents/skills/claude-code/align-documentation/SKILL.md +13 -0
- package/dist/agents/skills/claude-code/cleanup-dead-code/SKILL.md +25 -1
- package/dist/agents/skills/claude-code/cleanup-dead-code/skill.yaml +5 -2
- package/dist/agents/skills/claude-code/detect-doc-drift/SKILL.md +12 -0
- package/dist/agents/skills/claude-code/enforce-architecture/SKILL.md +48 -1
- package/dist/agents/skills/claude-code/enforce-architecture/skill.yaml +5 -2
- package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +7 -0
- package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +9 -1
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +76 -4
- package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +2 -0
- package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +487 -234
- package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +15 -2
- package/dist/agents/skills/claude-code/harness-codebase-cleanup/SKILL.md +226 -0
- package/dist/agents/skills/claude-code/harness-codebase-cleanup/skill.yaml +64 -0
- package/dist/agents/skills/claude-code/harness-dependency-health/SKILL.md +35 -6
- package/dist/agents/skills/claude-code/harness-docs-pipeline/SKILL.md +460 -0
- package/dist/agents/skills/claude-code/harness-docs-pipeline/skill.yaml +69 -0
- package/dist/agents/skills/claude-code/harness-execution/SKILL.md +73 -8
- package/dist/agents/skills/claude-code/harness-execution/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-hotspot-detector/SKILL.md +32 -6
- package/dist/agents/skills/claude-code/harness-i18n/SKILL.md +484 -0
- package/dist/agents/skills/claude-code/harness-i18n/skill.yaml +54 -0
- package/dist/agents/skills/claude-code/harness-i18n-process/SKILL.md +388 -0
- package/dist/agents/skills/claude-code/harness-i18n-process/skill.yaml +43 -0
- package/dist/agents/skills/claude-code/harness-i18n-workflow/SKILL.md +512 -0
- package/dist/agents/skills/claude-code/harness-i18n-workflow/skill.yaml +53 -0
- package/dist/agents/skills/claude-code/harness-impact-analysis/SKILL.md +35 -6
- package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +17 -1
- package/dist/agents/skills/claude-code/harness-knowledge-mapper/SKILL.md +46 -5
- package/dist/agents/skills/claude-code/harness-perf/SKILL.md +37 -8
- package/dist/agents/skills/claude-code/harness-perf/skill.yaml +3 -0
- package/dist/agents/skills/claude-code/harness-perf-tdd/SKILL.md +17 -4
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +57 -3
- package/dist/agents/skills/claude-code/harness-planning/skill.yaml +2 -0
- package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +16 -0
- package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +562 -0
- package/dist/agents/skills/claude-code/harness-roadmap/skill.yaml +43 -0
- package/dist/agents/skills/claude-code/harness-security-review/SKILL.md +36 -2
- package/dist/agents/skills/claude-code/harness-security-review/skill.yaml +8 -6
- package/dist/agents/skills/claude-code/harness-soundness-review/SKILL.md +1267 -0
- package/dist/agents/skills/claude-code/harness-soundness-review/skill.yaml +48 -0
- package/dist/agents/skills/claude-code/harness-test-advisor/SKILL.md +35 -6
- package/dist/agents/skills/claude-code/harness-verification/SKILL.md +66 -0
- package/dist/agents/skills/claude-code/harness-verification/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-verify/SKILL.md +11 -0
- package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +15 -1
- package/dist/agents/skills/claude-code/validate-context-engineering/SKILL.md +12 -0
- package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +7 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +9 -1
- package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/SKILL.md +226 -0
- package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +64 -0
- package/dist/agents/skills/gemini-cli/harness-dependency-health/SKILL.md +35 -6
- package/dist/agents/skills/gemini-cli/harness-docs-pipeline/SKILL.md +460 -0
- package/dist/agents/skills/gemini-cli/harness-docs-pipeline/skill.yaml +69 -0
- package/dist/agents/skills/gemini-cli/harness-hotspot-detector/SKILL.md +32 -6
- package/dist/agents/skills/gemini-cli/harness-i18n/SKILL.md +484 -0
- package/dist/agents/skills/gemini-cli/harness-i18n/skill.yaml +54 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-process/SKILL.md +388 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-process/skill.yaml +43 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-workflow/SKILL.md +512 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-workflow/skill.yaml +53 -0
- package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +35 -6
- package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/SKILL.md +46 -5
- package/dist/agents/skills/gemini-cli/harness-perf/SKILL.md +37 -8
- package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +3 -0
- package/dist/agents/skills/gemini-cli/harness-perf-tdd/SKILL.md +17 -4
- package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +16 -0
- package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +562 -0
- package/dist/agents/skills/gemini-cli/harness-roadmap/skill.yaml +43 -0
- package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +8 -6
- package/dist/agents/skills/gemini-cli/harness-soundness-review/SKILL.md +1267 -0
- package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +48 -0
- package/dist/agents/skills/gemini-cli/harness-test-advisor/SKILL.md +35 -6
- package/dist/agents/skills/shared/i18n-knowledge/accessibility/intersection.yaml +142 -0
- package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/encoding.yaml +67 -0
- package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/formatting.yaml +106 -0
- package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/layout.yaml +80 -0
- package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/pluralization.yaml +80 -0
- package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/string-handling.yaml +106 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/android-resources.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/apple-strings.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/backend-patterns.yaml +50 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/flutter-intl.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/i18next.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/react-intl.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/vue-i18n.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/industries/ecommerce.yaml +66 -0
- package/dist/agents/skills/shared/i18n-knowledge/industries/fintech.yaml +66 -0
- package/dist/agents/skills/shared/i18n-knowledge/industries/gaming.yaml +69 -0
- package/dist/agents/skills/shared/i18n-knowledge/industries/healthcare.yaml +66 -0
- package/dist/agents/skills/shared/i18n-knowledge/industries/legal.yaml +66 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/ar.yaml +41 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/de.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/en.yaml +32 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/es.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/fi.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/fr.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/he.yaml +41 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/hi.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/it.yaml +32 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/ja.yaml +38 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/ko.yaml +38 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/nl.yaml +32 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/pl.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/pt.yaml +32 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/ru.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/sv.yaml +32 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/th.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/tr.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hans.yaml +38 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hant.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/i18next-mcp.yaml +56 -0
- package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lingo-dev.yaml +56 -0
- package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lokalise.yaml +60 -0
- package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/tolgee.yaml +60 -0
- package/dist/agents/skills/shared/i18n-knowledge/testing/locale-testing.yaml +107 -0
- package/dist/agents/skills/shared/i18n-knowledge/testing/pseudo-localization.yaml +86 -0
- package/dist/bin/harness.js +64 -4
- package/dist/{chunk-4WUGOJQ7.js → chunk-3JWCBVUZ.js} +1 -1
- package/dist/{chunk-FFIX3QVG.js → chunk-LNI4T7R6.js} +131 -41
- package/dist/{chunk-GA6GN5J2.js → chunk-SJECMKSS.js} +2244 -34
- package/dist/{dist-N4D4QWFV.js → dist-BDO5GFEM.js} +1 -1
- package/dist/{dist-C4J67MPP.js → dist-NT3GXHQZ.js} +95 -1
- package/dist/index.d.ts +187 -7
- package/dist/index.js +7 -3
- package/dist/validate-cross-check-2OPGCGGU.js +7 -0
- package/package.json +7 -7
- package/dist/validate-cross-check-WGXQ7K62.js +0 -7
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
# Harness i18n Workflow
|
|
2
|
+
|
|
3
|
+
> Translation lifecycle management. Configure i18n settings, scaffold translation files, extract translatable strings, track coverage, generate pseudo-localization, and retrofit existing projects with internationalization support.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Setting up i18n infrastructure for a new project (during `on_project_init`)
|
|
8
|
+
- Retrofitting an existing project with i18n support (extracting hardcoded strings, scaffolding translation files)
|
|
9
|
+
- Extracting new translatable strings after feature development
|
|
10
|
+
- Tracking translation coverage before a release
|
|
11
|
+
- Generating pseudo-localization for layout and truncation testing
|
|
12
|
+
- When `on_project_init` triggers fire and the user has indicated multi-language support
|
|
13
|
+
- NOT for scanning existing code for i18n violations (use harness-i18n)
|
|
14
|
+
- NOT for injecting i18n considerations into brainstorming or planning (use harness-i18n-process)
|
|
15
|
+
- NOT for performing actual translations (use TMS tools or MCP integrations like Tolgee, Lokalise, Lingo.dev)
|
|
16
|
+
|
|
17
|
+
## Process
|
|
18
|
+
|
|
19
|
+
### Phase 1: CONFIGURE -- Set Up i18n Configuration
|
|
20
|
+
|
|
21
|
+
1. **Check for existing configuration.** Read `harness.config.json` and look for an `i18n` block.
|
|
22
|
+
- If `i18n` block exists: load it and report current settings. Ask the user if they want to modify any settings.
|
|
23
|
+
- If no `i18n` block: proceed with guided setup.
|
|
24
|
+
|
|
25
|
+
2. **Auto-detect project context.** Before asking questions, gather context:
|
|
26
|
+
- Read `package.json`, `Podfile`, `build.gradle`, `pubspec.yaml` to detect platform(s) (web, mobile, backend).
|
|
27
|
+
- Check for existing i18n framework dependencies (i18next, react-intl, vue-i18n, flutter intl, etc.) using framework detection profiles from `agents/skills/shared/i18n-knowledge/frameworks/`.
|
|
28
|
+
- Check for existing translation files in common locations (`locales/`, `src/locales/`, `public/locales/`, `assets/translations/`, `res/values*/`).
|
|
29
|
+
|
|
30
|
+
3. **Present opinionated defaults.** Show the user the recommended configuration based on detection results:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
i18n Configuration (recommended defaults)
|
|
34
|
+
==========================================
|
|
35
|
+
Source locale: en
|
|
36
|
+
Target locales: [ask user]
|
|
37
|
+
Framework: [auto-detected or recommend based on platform]
|
|
38
|
+
Message format: ICU MessageFormat (industry standard, widest tooling support)
|
|
39
|
+
File format: JSON (universal, every TMS imports/exports it)
|
|
40
|
+
Key convention: dot-notation namespaced by feature (e.g., checkout.summary.totalLabel)
|
|
41
|
+
Directory: locales/{locale}/{namespace}.json
|
|
42
|
+
Strictness: standard
|
|
43
|
+
Pseudo-locale: en-XA (auto-generated for testing)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
4. **Gather required user input.** The following must be answered by the user:
|
|
47
|
+
- Target locales (BCP 47 codes): which languages will the project support?
|
|
48
|
+
- Industry (optional): fintech, healthcare, ecommerce, legal, gaming -- loads industry-specific rules.
|
|
49
|
+
- Platform(s) confirmation: confirm the auto-detected platforms or override.
|
|
50
|
+
|
|
51
|
+
5. **Write configuration.** Update `harness.config.json` with the i18n block:
|
|
52
|
+
|
|
53
|
+
```jsonc
|
|
54
|
+
{
|
|
55
|
+
"i18n": {
|
|
56
|
+
"enabled": true,
|
|
57
|
+
"strictness": "standard",
|
|
58
|
+
"sourceLocale": "en",
|
|
59
|
+
"targetLocales": ["es", "fr", "de"], // user-specified
|
|
60
|
+
"framework": "auto", // or detected framework
|
|
61
|
+
"format": "json",
|
|
62
|
+
"messageFormat": "icu",
|
|
63
|
+
"keyConvention": "dot-notation",
|
|
64
|
+
"translationPaths": {
|
|
65
|
+
"web": "locales/{locale}/{namespace}.json",
|
|
66
|
+
},
|
|
67
|
+
"platforms": ["web"], // detected or confirmed
|
|
68
|
+
"coverage": {
|
|
69
|
+
"minimumPercent": 95,
|
|
70
|
+
"requirePlurals": true,
|
|
71
|
+
"detectUntranslated": true,
|
|
72
|
+
},
|
|
73
|
+
"pseudoLocale": "en-XA",
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
If `harness.config.json` does not exist, create it with `{ "version": 1, "i18n": { ... } }`.
|
|
79
|
+
If it already exists, merge the `i18n` block into the existing config using the Edit tool.
|
|
80
|
+
|
|
81
|
+
6. **Report configuration summary.** Display the final configuration and confirm with the user before proceeding to scaffold.
|
|
82
|
+
|
|
83
|
+
### Phase 2: SCAFFOLD -- Create Translation File Structure
|
|
84
|
+
|
|
85
|
+
1. **Determine scaffold mode.** Check if the project already has source code with user-facing strings:
|
|
86
|
+
- **Greenfield mode:** No existing source code or translation files. Create the structure from scratch.
|
|
87
|
+
- **Retrofit mode:** Existing source code found. Audit first, then scaffold.
|
|
88
|
+
|
|
89
|
+
2. **Greenfield scaffolding.** Create the translation directory structure based on config:
|
|
90
|
+
- Create directory for each locale: `locales/en/`, `locales/es/`, `locales/fr/`, etc.
|
|
91
|
+
- Create initial namespace file for each locale (e.g., `locales/en/common.json`, `locales/es/common.json`).
|
|
92
|
+
- Source locale file gets a starter template:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"app": {
|
|
97
|
+
"name": "",
|
|
98
|
+
"description": ""
|
|
99
|
+
},
|
|
100
|
+
"common": {
|
|
101
|
+
"loading": "Loading...",
|
|
102
|
+
"error": "Something went wrong",
|
|
103
|
+
"retry": "Try again",
|
|
104
|
+
"cancel": "Cancel",
|
|
105
|
+
"confirm": "Confirm",
|
|
106
|
+
"save": "Save",
|
|
107
|
+
"delete": "Delete",
|
|
108
|
+
"edit": "Edit",
|
|
109
|
+
"back": "Back",
|
|
110
|
+
"next": "Next"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
- Target locale files get the same keys with empty string values (to be translated).
|
|
116
|
+
- Create pseudo-locale directory (`locales/en-XA/`) -- will be populated in Track phase.
|
|
117
|
+
|
|
118
|
+
3. **Retrofit scaffolding.** Run the retrofit workflow:
|
|
119
|
+
|
|
120
|
+
a. **Invoke harness-i18n detect + scan phases** to assess current state. This produces:
|
|
121
|
+
- Detected platform(s) and framework
|
|
122
|
+
- List of hardcoded user-facing strings with file paths and line numbers
|
|
123
|
+
- Existing translation files and their coverage
|
|
124
|
+
|
|
125
|
+
b. **Report audit results:**
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
Retrofit Audit Results
|
|
129
|
+
======================
|
|
130
|
+
Hardcoded strings found: 47
|
|
131
|
+
Existing translation keys: 0
|
|
132
|
+
Existing locales configured: 0
|
|
133
|
+
Estimated extraction effort: Medium (47 strings across 12 files)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
c. **Generate initial key catalog.** For each detected hardcoded string:
|
|
137
|
+
- Generate a dot-notation key based on file path and context (e.g., `components.header.welcomeTitle`)
|
|
138
|
+
- Use the original string as the source locale value
|
|
139
|
+
- Flag strings that need human review for key naming (ambiguous context, duplicate meanings)
|
|
140
|
+
|
|
141
|
+
d. **Scaffold translation files** with the generated key catalog for the source locale.
|
|
142
|
+
|
|
143
|
+
e. **Create empty target locale files** with the same key structure and empty values.
|
|
144
|
+
|
|
145
|
+
f. **Present the key catalog to the user for review.** This is a checkpoint -- the user should review and approve key names before they become permanent.
|
|
146
|
+
|
|
147
|
+
[checkpoint:human-verify] -- User must review generated key catalog before proceeding.
|
|
148
|
+
|
|
149
|
+
4. **Framework-specific setup.** Based on the detected or configured framework:
|
|
150
|
+
- **i18next:** Create `i18next.config.ts` (or `.js`) with namespace configuration, backend plugin setup, and language detection.
|
|
151
|
+
- **react-intl:** Verify `IntlProvider` is set up in the app root. If not, provide instructions for adding it.
|
|
152
|
+
- **vue-i18n:** Create `i18n.ts` plugin configuration. Verify it is installed in the Vue app.
|
|
153
|
+
- **flutter intl:** Create `l10n.yaml` configuration. Set up `intl` package in `pubspec.yaml`.
|
|
154
|
+
- **No framework detected:** Recommend a framework based on platform:
|
|
155
|
+
- React/Next.js: recommend i18next + react-i18next
|
|
156
|
+
- Vue/Nuxt: recommend vue-i18n
|
|
157
|
+
- Flutter: recommend flutter intl + intl package
|
|
158
|
+
- Backend Node: recommend i18next
|
|
159
|
+
- Generic: recommend i18next (widest ecosystem support)
|
|
160
|
+
|
|
161
|
+
5. **Report scaffold results.** Display what was created:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
Scaffold Results
|
|
165
|
+
================
|
|
166
|
+
Directories created: 4 (locales/en, locales/es, locales/fr, locales/en-XA)
|
|
167
|
+
Files created: 4 (common.json per locale + pseudo-locale placeholder)
|
|
168
|
+
Keys scaffolded: 10 (common starter keys)
|
|
169
|
+
Framework config: i18next.config.ts created
|
|
170
|
+
Next step: Run extract phase to populate translation files from source code
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Phase 3: EXTRACT -- Extract Translatable Strings
|
|
174
|
+
|
|
175
|
+
1. **Read configuration.** Load `harness.config.json` i18n block for:
|
|
176
|
+
- Source locale and target locales
|
|
177
|
+
- Key naming convention (`dot-notation`, `snake_case`, `camelCase`)
|
|
178
|
+
- Translation file paths and format
|
|
179
|
+
- Framework in use
|
|
180
|
+
|
|
181
|
+
2. **Scan source code for extractable strings.** Use `harness-i18n` scan results or run a fresh scan. For each detected hardcoded user-facing string, collect:
|
|
182
|
+
- File path and line number
|
|
183
|
+
- The string content
|
|
184
|
+
- Surrounding context (component name, function name, prop name)
|
|
185
|
+
- Whether it contains interpolation placeholders
|
|
186
|
+
|
|
187
|
+
3. **Generate translation keys.** For each extractable string, generate a key following the configured convention:
|
|
188
|
+
- **dot-notation** (default): `{feature}.{component}.{description}`
|
|
189
|
+
- Example: `checkout.summary.totalLabel` for "Total" in `CheckoutSummary.tsx`
|
|
190
|
+
- Example: `auth.login.submitButton` for "Sign in" in `LoginForm.tsx`
|
|
191
|
+
- **snake_case**: `{feature}_{component}_{description}`
|
|
192
|
+
- **camelCase**: `{feature}{Component}{Description}`
|
|
193
|
+
- Derive feature from directory path, component from file name, description from string content.
|
|
194
|
+
- For strings with interpolation, convert to ICU MessageFormat:
|
|
195
|
+
- `` `Hello ${name}` `` becomes `"greeting.hello": "Hello {name}"`
|
|
196
|
+
- Plurals: `items.length === 1 ? "item" : "items"` becomes `"cart.itemCount": "{count, plural, one {# item} other {# items}}"`
|
|
197
|
+
|
|
198
|
+
4. **Preserve existing translations.** Before writing to translation files:
|
|
199
|
+
- Read existing translation files for all locales.
|
|
200
|
+
- Never overwrite a key that already has a translated (non-empty, non-source-identical) value in a target locale.
|
|
201
|
+
- For keys that exist in source but have been modified, flag as "stale" rather than overwriting.
|
|
202
|
+
|
|
203
|
+
5. **Flag strings needing human review.** Mark strings that the agent cannot confidently extract:
|
|
204
|
+
- Strings with ambiguous context (same text, different meaning in different components)
|
|
205
|
+
- Strings that might be intentional non-translatable content (brand names, technical terms)
|
|
206
|
+
- Strings with complex interpolation that may not map cleanly to ICU MessageFormat
|
|
207
|
+
- Present these with `[REVIEW]` markers in the output.
|
|
208
|
+
|
|
209
|
+
6. **Write extraction results.** Update translation files:
|
|
210
|
+
- Add new keys to source locale file with the original string as the value.
|
|
211
|
+
- Add new keys to target locale files with empty string values.
|
|
212
|
+
- Maintain alphabetical ordering within each namespace.
|
|
213
|
+
- Use the Edit tool for surgical updates -- do not rewrite entire files.
|
|
214
|
+
|
|
215
|
+
7. **Report extraction results:**
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
Extraction Results
|
|
219
|
+
==================
|
|
220
|
+
Strings scanned: 47
|
|
221
|
+
Keys generated: 42
|
|
222
|
+
Keys already existed: 5 (preserved)
|
|
223
|
+
Flagged for review: 8 [REVIEW]
|
|
224
|
+
Files updated: 12 (4 source files wrapped, 8 translation files updated)
|
|
225
|
+
|
|
226
|
+
Review Required
|
|
227
|
+
---------------
|
|
228
|
+
[REVIEW] src/components/Header.tsx:5 -- "Welcome" -- ambiguous context (greeting vs. page title)
|
|
229
|
+
[REVIEW] src/utils/format.ts:12 -- "USD" -- may be intentional (currency code, not translatable)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Phase 4: TRACK -- Coverage Dashboard and Pseudo-Localization
|
|
233
|
+
|
|
234
|
+
1. **Calculate per-locale coverage.** For each target locale:
|
|
235
|
+
- Count total keys in source locale.
|
|
236
|
+
- Count translated keys in target locale (non-empty, non-source-identical values).
|
|
237
|
+
- Calculate percentage: `(translated / total) * 100`.
|
|
238
|
+
- Check for missing plural forms per CLDR rules (load from `agents/skills/shared/i18n-knowledge/locales/{locale}.yaml`).
|
|
239
|
+
- Detect stale translations using `git diff` on the source locale file. Run `git log --diff-filter=M -p -- {sourceLocalePath}` to identify keys whose source values changed since the last commit that touched the target locale file. A translation is stale when the source value changed but the target was not updated in a subsequent commit. If git history is unavailable, fall back to heuristic detection: flag target values that are identical to the current source value (likely untranslated) or that contain substrings of the old source (partial staleness).
|
|
240
|
+
|
|
241
|
+
2. **Generate coverage dashboard:**
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
Translation Coverage Dashboard
|
|
245
|
+
==============================
|
|
246
|
+
Source locale: en (142 keys)
|
|
247
|
+
|
|
248
|
+
Locale Translated Coverage Untranslated Stale Missing Plurals
|
|
249
|
+
es 128 90.1% 14 3 2
|
|
250
|
+
fr 135 95.1% 7 1 0
|
|
251
|
+
de 120 84.5% 22 5 4
|
|
252
|
+
ja 115 81.0% 27 2 1
|
|
253
|
+
ar 110 77.5% 32 4 6
|
|
254
|
+
|
|
255
|
+
Coverage threshold: 95% (from config)
|
|
256
|
+
Passing locales: fr
|
|
257
|
+
Failing locales: es, de, ja, ar
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
3. **Report untranslated keys.** For each locale below the coverage threshold, list the missing keys:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
Untranslated Keys: es (14 missing)
|
|
264
|
+
-----------------------------------
|
|
265
|
+
checkout.payment.cardLabel
|
|
266
|
+
checkout.payment.expiryLabel
|
|
267
|
+
checkout.payment.cvvLabel
|
|
268
|
+
settings.notifications.emailToggle
|
|
269
|
+
...
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
4. **Report stale translations.** List keys where the source changed but the target was not updated:
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
Stale Translations: es (3 stale)
|
|
276
|
+
---------------------------------
|
|
277
|
+
Key: auth.login.heading
|
|
278
|
+
Source (old): "Sign In"
|
|
279
|
+
Source (new): "Log In"
|
|
280
|
+
Target (es): "Iniciar Sesion" (based on old source)
|
|
281
|
+
Action: Review and update Spanish translation
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
5. **Generate pseudo-localization.** Create a pseudo-locale file (default: `en-XA`) that transforms source strings to test for:
|
|
285
|
+
- **Text expansion:** Pad strings to simulate ~35% expansion (typical for English-to-German):
|
|
286
|
+
- Strings < 10 chars: +50% expansion
|
|
287
|
+
- Strings 10-50 chars: +35% expansion
|
|
288
|
+
- Strings > 50 chars: +25% expansion
|
|
289
|
+
- **Accent characters:** Replace ASCII characters with accented Unicode equivalents to test font rendering and encoding:
|
|
290
|
+
- a → à, e → ë, i → ì, o → ö, u → ù, c → ç, n → ñ, s → š, z → ž
|
|
291
|
+
- Uppercase: A → À, E → Ë, I → Ì, O → Ö, U → Ù, C → Ç, N → Ñ, S → Š, Z → Ž
|
|
292
|
+
- **Bracket wrapping:** Wrap each string in `[` and `]` to detect truncation and overflow.
|
|
293
|
+
- **Preserve placeholders:** ICU MessageFormat placeholders (`{name}`, `{count, plural, ...}`) must NOT be modified.
|
|
294
|
+
- **Preserve HTML/JSX tags:** Tags like `<strong>`, `<br/>`, `<Link>` must NOT be modified.
|
|
295
|
+
|
|
296
|
+
Example transformations (showing both expansion and accent replacement):
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
"Save" -> "[Šàvëë]"
|
|
300
|
+
"Hello {name}" -> "[Hëëllöö {name}]"
|
|
301
|
+
"Cancel" -> "[Çààñçëël]"
|
|
302
|
+
"{count, plural, one {# item} other {# items}}" -> "[{count, plural, one {# ìtëëm} other {# ìtëëmš}}]"
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Write the pseudo-locale file to the configured pseudo-locale path (e.g., `locales/en-XA/common.json`).
|
|
306
|
+
|
|
307
|
+
6. **Recommend MCP servers.** Based on the project's workflow needs, recommend MCP server integrations from `agents/skills/shared/i18n-knowledge/mcp-interop/`:
|
|
308
|
+
|
|
309
|
+
```
|
|
310
|
+
MCP Server Recommendations
|
|
311
|
+
==========================
|
|
312
|
+
Based on your project configuration:
|
|
313
|
+
|
|
314
|
+
Tolgee MCP (recommended)
|
|
315
|
+
- Best for: TMS integration, in-context translation, developer workflow
|
|
316
|
+
- Why: You have 5 target locales and are using i18next -- Tolgee has native i18next support
|
|
317
|
+
- Setup: Install @tolgee/mcp, configure with your project API key
|
|
318
|
+
|
|
319
|
+
Lingo.dev MCP (optional)
|
|
320
|
+
- Best for: Brand voice consistency, glossary enforcement, multi-engine MT
|
|
321
|
+
- Why: Useful if you want automated translation with quality controls
|
|
322
|
+
|
|
323
|
+
i18next MCP (optional)
|
|
324
|
+
- Best for: Project analysis, coverage tracking, key management
|
|
325
|
+
- Why: Direct i18next integration for project-level insights
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Load recommendation logic from the MCP interop profiles. Recommend based on:
|
|
329
|
+
- Framework match (e.g., Tolgee for i18next, Lokalise for broad TMS needs)
|
|
330
|
+
- Target locale count (more locales = stronger TMS recommendation)
|
|
331
|
+
- Industry (e.g., Lingo.dev for brand-sensitive industries)
|
|
332
|
+
- Existing MCP config (if `i18n.mcp` is already configured, validate the choice)
|
|
333
|
+
|
|
334
|
+
7. **If graph is available** (`.harness/graph/` exists): provide per-component/route coverage. Map translation keys to the components that use them and report coverage by feature area:
|
|
335
|
+
|
|
336
|
+
```
|
|
337
|
+
Component Coverage (graph-enhanced)
|
|
338
|
+
====================================
|
|
339
|
+
Component Keys es fr de
|
|
340
|
+
CheckoutFlow 24 92% 100% 83%
|
|
341
|
+
AuthPages 18 89% 94% 78%
|
|
342
|
+
Settings 31 87% 97% 81%
|
|
343
|
+
Dashboard 15 93% 93% 93%
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
8. **If graph is unavailable**: report per-file key-level coverage as shown in step 2.
|
|
347
|
+
|
|
348
|
+
9. **Suggest next actions** based on coverage results:
|
|
349
|
+
- If any locale is below threshold: "Run translations for {N} missing keys in {locale}. Consider using Tolgee MCP for batch translation."
|
|
350
|
+
- If stale translations exist: "Review {N} stale translations in {locale}. Source text changed since last translation."
|
|
351
|
+
- If missing plurals: "Add missing plural forms for {locale}. Required CLDR categories: {categories}."
|
|
352
|
+
- If pseudo-locale generated: "Use the en-XA pseudo-locale to test layout and truncation. Check components with long strings for overflow."
|
|
353
|
+
|
|
354
|
+
## Harness Integration
|
|
355
|
+
|
|
356
|
+
- **`harness validate`** -- Run after configuration changes and file scaffolding to verify project health.
|
|
357
|
+
- **`harness-i18n`** -- The workflow skill depends on the core i18n skill for framework detection and string scanning. The detect + scan phases of `harness-i18n` are invoked during retrofit scaffolding and extraction.
|
|
358
|
+
- **`harness-initialize-project`** -- During project init, if the user indicates multi-language support, the configure + scaffold phases are invoked automatically.
|
|
359
|
+
- **`harness-release-readiness`** -- Coverage data from the track phase feeds into release readiness checks. Per-locale coverage is compared against `i18n.coverage.minimumPercent`.
|
|
360
|
+
- **Knowledge base** at `agents/skills/shared/i18n-knowledge/` -- Framework profiles guide scaffolding and extraction. Locale profiles provide CLDR plural rules for coverage tracking. MCP interop profiles drive server recommendations.
|
|
361
|
+
|
|
362
|
+
## Success Criteria
|
|
363
|
+
|
|
364
|
+
- Configuration phase produces a valid `i18n` block in `harness.config.json` with opinionated defaults
|
|
365
|
+
- Scaffold phase creates the correct directory structure and locale files for all configured target locales
|
|
366
|
+
- Retrofit mode correctly audits existing code and generates an initial key catalog with human-review flags
|
|
367
|
+
- Extract phase generates keys following the configured naming convention and preserves existing translations
|
|
368
|
+
- Coverage tracking reports accurate per-locale percentages with untranslated, stale, and missing plural breakdowns
|
|
369
|
+
- Pseudo-localization applies text expansion, accent characters, and bracket wrapping while preserving placeholders and tags
|
|
370
|
+
- MCP server recommendations are relevant to the project's framework and workflow needs
|
|
371
|
+
- `harness validate` passes after all changes
|
|
372
|
+
|
|
373
|
+
## Examples
|
|
374
|
+
|
|
375
|
+
### Example: Greenfield React + i18next Project
|
|
376
|
+
|
|
377
|
+
**Context:** New React web app. User wants to support English, Spanish, French.
|
|
378
|
+
|
|
379
|
+
**Phase 1: CONFIGURE**
|
|
380
|
+
|
|
381
|
+
User runs `harness skill run harness-i18n-workflow`.
|
|
382
|
+
|
|
383
|
+
```
|
|
384
|
+
i18n Configuration (recommended defaults)
|
|
385
|
+
==========================================
|
|
386
|
+
Source locale: en
|
|
387
|
+
Target locales: [input required]
|
|
388
|
+
Framework: i18next (detected from package.json)
|
|
389
|
+
Message format: ICU MessageFormat
|
|
390
|
+
File format: JSON
|
|
391
|
+
Key convention: dot-notation
|
|
392
|
+
Directory: locales/{locale}/{namespace}.json
|
|
393
|
+
Strictness: standard
|
|
394
|
+
Pseudo-locale: en-XA
|
|
395
|
+
|
|
396
|
+
What target locales will this project support? (BCP 47 codes, comma-separated)
|
|
397
|
+
> es, fr
|
|
398
|
+
|
|
399
|
+
Any industry-specific requirements? (fintech, healthcare, ecommerce, legal, gaming, or none)
|
|
400
|
+
> none
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
Configuration written to `harness.config.json`.
|
|
404
|
+
|
|
405
|
+
**Phase 2: SCAFFOLD**
|
|
406
|
+
|
|
407
|
+
```
|
|
408
|
+
Scaffold Results
|
|
409
|
+
================
|
|
410
|
+
Directories created: 3 (locales/en, locales/es, locales/fr) + locales/en-XA
|
|
411
|
+
Files created: 4 (common.json per locale + pseudo-locale placeholder)
|
|
412
|
+
Keys scaffolded: 10 (common starter keys)
|
|
413
|
+
Framework config: Verified -- i18next already configured in src/i18n.ts
|
|
414
|
+
Next step: Develop features, then run extract phase to populate translation files
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
**Phase 3: EXTRACT** (after development)
|
|
418
|
+
|
|
419
|
+
```
|
|
420
|
+
Extraction Results
|
|
421
|
+
==================
|
|
422
|
+
Strings scanned: 23
|
|
423
|
+
Keys generated: 20
|
|
424
|
+
Keys already existed: 3 (common.loading, common.error, common.retry)
|
|
425
|
+
Flagged for review: 2 [REVIEW]
|
|
426
|
+
Files updated: 6 (3 translation files + 3 source files with t() wrapping instructions)
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Phase 4: TRACK**
|
|
430
|
+
|
|
431
|
+
```
|
|
432
|
+
Translation Coverage Dashboard
|
|
433
|
+
==============================
|
|
434
|
+
Source locale: en (23 keys)
|
|
435
|
+
|
|
436
|
+
Locale Translated Coverage Untranslated Stale Missing Plurals
|
|
437
|
+
es 0 0.0% 23 0 0
|
|
438
|
+
fr 0 0.0% 23 0 0
|
|
439
|
+
|
|
440
|
+
Coverage threshold: 95% (from config)
|
|
441
|
+
Passing locales: none
|
|
442
|
+
Failing locales: es, fr
|
|
443
|
+
|
|
444
|
+
Pseudo-locale generated: locales/en-XA/common.json (23 keys transformed)
|
|
445
|
+
|
|
446
|
+
MCP Server Recommendations
|
|
447
|
+
==========================
|
|
448
|
+
Tolgee MCP (recommended) -- native i18next support, in-context translation
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Example: Retrofitting an Existing Express API
|
|
452
|
+
|
|
453
|
+
**Context:** Existing Express.js backend with hardcoded error messages. User wants to add i18n.
|
|
454
|
+
|
|
455
|
+
**Phase 1: CONFIGURE**
|
|
456
|
+
|
|
457
|
+
Auto-detection finds: platform = backend, framework = none, no translation files.
|
|
458
|
+
|
|
459
|
+
```
|
|
460
|
+
i18n Configuration
|
|
461
|
+
==================
|
|
462
|
+
Source locale: en
|
|
463
|
+
Target locales: > es, de, ja
|
|
464
|
+
Framework: none detected -- recommending i18next for Node.js backend
|
|
465
|
+
Message format: ICU MessageFormat
|
|
466
|
+
File format: JSON
|
|
467
|
+
Key convention: dot-notation
|
|
468
|
+
Directory: locales/{locale}/{namespace}.json
|
|
469
|
+
Platforms: backend
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
**Phase 2: SCAFFOLD (retrofit mode)**
|
|
473
|
+
|
|
474
|
+
```
|
|
475
|
+
Retrofit Audit Results
|
|
476
|
+
======================
|
|
477
|
+
Hardcoded strings found: 31
|
|
478
|
+
Existing translation keys: 0
|
|
479
|
+
Existing locales configured: 0
|
|
480
|
+
Estimated extraction effort: Medium (31 strings across 8 files)
|
|
481
|
+
|
|
482
|
+
Generated Key Catalog (review required)
|
|
483
|
+
========================================
|
|
484
|
+
errors.auth.invalidCredentials -> "Invalid email or password"
|
|
485
|
+
errors.auth.tokenExpired -> "Session expired, please log in again"
|
|
486
|
+
errors.validation.requiredField -> "This field is required"
|
|
487
|
+
errors.notFound.resource -> "Resource not found"
|
|
488
|
+
emails.welcome.subject -> "Welcome to {appName}"
|
|
489
|
+
emails.welcome.greeting -> "Hello {name}, welcome aboard!"
|
|
490
|
+
...
|
|
491
|
+
|
|
492
|
+
[checkpoint] Please review the generated key names above.
|
|
493
|
+
Approve to continue scaffolding, or provide corrections.
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
## Gates
|
|
497
|
+
|
|
498
|
+
These are hard stops. Violating any gate means the process has broken down.
|
|
499
|
+
|
|
500
|
+
- **No scaffolding without completed configuration.** The configure phase must produce a valid i18n config before scaffold runs. Running scaffold on a project with no i18n config is not allowed.
|
|
501
|
+
- **No extraction without existing translation files.** The extract phase requires scaffold to have run first. There must be at least a source locale translation file to write keys into.
|
|
502
|
+
- **No overwriting existing translations.** When extracting or scaffolding, never overwrite a key that already has a translated (non-empty, non-source-identical) value in a target locale file.
|
|
503
|
+
- **No pseudo-localization that modifies placeholders.** ICU MessageFormat placeholders (`{name}`, `{count, plural, ...}`) and HTML/JSX tags must be preserved exactly in pseudo-locale output.
|
|
504
|
+
- **No retrofit key catalog applied without human review.** In retrofit mode, the generated key catalog must be presented to the user and approved before writing to translation files. This is a hard checkpoint.
|
|
505
|
+
|
|
506
|
+
## Escalation
|
|
507
|
+
|
|
508
|
+
- **When more than 100 strings are detected in retrofit mode:** Suggest a phased approach -- prioritize high-traffic user flows first (checkout, onboarding, error messages), then expand coverage incrementally.
|
|
509
|
+
- **When the project uses a framework not in the knowledge base:** Fall back to generic extraction patterns. Log: "Framework {name} not in knowledge base -- using generic extraction. Consider contributing a framework profile."
|
|
510
|
+
- **When translation files already exist in an unexpected format (PO, XLIFF, ARB):** Report the format mismatch. Ask the user: convert to JSON, or adapt the workflow to the existing format. Do not silently convert.
|
|
511
|
+
- **When key naming conflicts arise (two strings producing the same key):** Append a disambiguating suffix (e.g., `.heading` vs `.label` vs `.button`) and flag for human review.
|
|
512
|
+
- **When coverage is below 50% and the team has no TMS:** Strongly recommend setting up a TMS integration via MCP. Manual translation of hundreds of keys is not sustainable.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: harness-i18n-workflow
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: Translation lifecycle management — configuration, scaffolding, string extraction, coverage tracking, pseudo-localization, and retrofit for existing projects
|
|
4
|
+
cognitive_mode: constructive-architect
|
|
5
|
+
triggers:
|
|
6
|
+
- manual
|
|
7
|
+
- on_project_init
|
|
8
|
+
platforms:
|
|
9
|
+
- claude-code
|
|
10
|
+
- gemini-cli
|
|
11
|
+
tools:
|
|
12
|
+
- Bash
|
|
13
|
+
- Read
|
|
14
|
+
- Write
|
|
15
|
+
- Edit
|
|
16
|
+
- Glob
|
|
17
|
+
- Grep
|
|
18
|
+
cli:
|
|
19
|
+
command: harness skill run harness-i18n-workflow
|
|
20
|
+
args:
|
|
21
|
+
- name: path
|
|
22
|
+
description: Project root path
|
|
23
|
+
required: false
|
|
24
|
+
- name: phase
|
|
25
|
+
description: Run a specific phase (configure, scaffold, extract, track)
|
|
26
|
+
required: false
|
|
27
|
+
- name: retrofit
|
|
28
|
+
description: Enable retrofit mode for existing projects
|
|
29
|
+
required: false
|
|
30
|
+
mcp:
|
|
31
|
+
tool: run_skill
|
|
32
|
+
input:
|
|
33
|
+
skill: harness-i18n-workflow
|
|
34
|
+
path: string
|
|
35
|
+
type: flexible
|
|
36
|
+
phases:
|
|
37
|
+
- name: configure
|
|
38
|
+
description: Set up i18n config in harness.config.json with opinionated defaults or guided customization
|
|
39
|
+
required: true
|
|
40
|
+
- name: scaffold
|
|
41
|
+
description: Create translation file structure, generate locale files, and optionally audit existing code for retrofit
|
|
42
|
+
required: true
|
|
43
|
+
- name: extract
|
|
44
|
+
description: Extract translatable strings into translation files, generate keys, preserve existing translations
|
|
45
|
+
required: false
|
|
46
|
+
- name: track
|
|
47
|
+
description: Coverage dashboard, pseudo-localization generation, stale translation detection, MCP server recommendations
|
|
48
|
+
required: false
|
|
49
|
+
state:
|
|
50
|
+
persistent: false
|
|
51
|
+
files: []
|
|
52
|
+
depends_on:
|
|
53
|
+
- harness-i18n
|
|
@@ -13,8 +13,23 @@
|
|
|
13
13
|
|
|
14
14
|
## Prerequisites
|
|
15
15
|
|
|
16
|
-
A knowledge graph
|
|
17
|
-
|
|
16
|
+
A knowledge graph at `.harness/graph/` enables full analysis. If no graph exists,
|
|
17
|
+
the skill uses static analysis fallbacks (see Graph Availability section).
|
|
18
|
+
Run `harness scan` to enable graph-enhanced analysis.
|
|
19
|
+
|
|
20
|
+
### Graph Availability
|
|
21
|
+
|
|
22
|
+
Before starting, check if `.harness/graph/graph.json` exists.
|
|
23
|
+
|
|
24
|
+
**If graph exists:** Check staleness — compare `.harness/graph/metadata.json`
|
|
25
|
+
scanTimestamp against `git log -1 --format=%ct` (latest commit timestamp).
|
|
26
|
+
If graph is more than 2 commits behind (`git log --oneline <scanTimestamp>..HEAD | wc -l`),
|
|
27
|
+
run `harness scan` to refresh before proceeding. (Staleness sensitivity: **High**)
|
|
28
|
+
|
|
29
|
+
**If graph exists and is fresh (or refreshed):** Use graph tools as primary strategy.
|
|
30
|
+
|
|
31
|
+
**If no graph exists:** Output "Running without graph (run `harness scan` to
|
|
32
|
+
enable full analysis)" and use fallback strategies for all subsequent steps.
|
|
18
33
|
|
|
19
34
|
## Process
|
|
20
35
|
|
|
@@ -58,6 +73,20 @@ For each changed file:
|
|
|
58
73
|
|
|
59
74
|
6. **Design constraint impact**: When the graph contains `DesignConstraint` nodes, check if changed code introduces new `VIOLATES_DESIGN` edges.
|
|
60
75
|
|
|
76
|
+
#### Fallback (without graph)
|
|
77
|
+
|
|
78
|
+
When no graph is available, use static analysis to approximate impact:
|
|
79
|
+
|
|
80
|
+
1. **Parse imports**: For each changed file, grep all source files for `import.*from.*<changed-file>` and `require.*<changed-file>` patterns to find direct dependents.
|
|
81
|
+
2. **Follow imports 2 levels deep**: For each direct dependent found, repeat the import grep to find second-level dependents. Stop at 2 levels (fallback cannot reliably trace deeper).
|
|
82
|
+
3. **Find test files by naming convention**: For each changed file `foo.ts`, search for:
|
|
83
|
+
- `foo.test.ts`, `foo.spec.ts` (same directory and `__tests__/` directory)
|
|
84
|
+
- `*.test.*` and `*.spec.*` files that import the changed file (from step 1)
|
|
85
|
+
4. **Find docs by path matching**: Grep `docs/` directory for references to the changed module name (filename without extension).
|
|
86
|
+
5. **Group results** the same as the graph version: tests, docs, code, other. Note the count of files found.
|
|
87
|
+
|
|
88
|
+
> Fallback completeness: ~70% — misses transitive deps beyond 2 levels.
|
|
89
|
+
|
|
61
90
|
### Phase 3: ASSESS — Risk Assessment and Report
|
|
62
91
|
|
|
63
92
|
1. **Impact score**: Calculate based on:
|
|
@@ -110,7 +139,7 @@ For each changed file:
|
|
|
110
139
|
|
|
111
140
|
## Harness Integration
|
|
112
141
|
|
|
113
|
-
- **`harness scan`** —
|
|
142
|
+
- **`harness scan`** — Recommended before this skill for full graph-enhanced analysis. If graph is missing, skill uses static analysis fallbacks.
|
|
114
143
|
- **`harness validate`** — Run after acting on findings to verify project health.
|
|
115
144
|
- **Graph tools** — This skill uses `query_graph`, `get_impact`, and `get_relationships` MCP tools.
|
|
116
145
|
|
|
@@ -120,7 +149,7 @@ For each changed file:
|
|
|
120
149
|
- All affected test files listed with direct vs transitive classification
|
|
121
150
|
- All affected documentation files listed with relationship context
|
|
122
151
|
- Report follows the structured output format
|
|
123
|
-
- All findings are backed by graph query evidence
|
|
152
|
+
- All findings are backed by graph query evidence (with graph) or systematic static analysis (without graph)
|
|
124
153
|
|
|
125
154
|
## Examples
|
|
126
155
|
|
|
@@ -146,8 +175,8 @@ Output:
|
|
|
146
175
|
|
|
147
176
|
## Gates
|
|
148
177
|
|
|
149
|
-
- **
|
|
150
|
-
- **No risk assessment without data.**
|
|
178
|
+
- **Graph preferred, fallback available.** If no graph exists, use fallback strategies (import parsing, naming conventions, path matching). Do not stop — produce the best analysis possible with available tools.
|
|
179
|
+
- **No risk assessment without data.** Use graph queries when available; use import parsing and naming conventions when not. If neither approach yields data, state what is missing.
|
|
151
180
|
|
|
152
181
|
## Escalation
|
|
153
182
|
|