claude-prism 0.4.1 → 0.5.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/README.md CHANGED
@@ -32,7 +32,6 @@ An AI coding problem decomposition tool for Claude Code. Installs the **UDEC** m
32
32
  - **20 test runner patterns** — Added bun, pnpm, yarn, deno, rspec, dotnet, mvn, gradle detection
33
33
  - **9 framework-specific result detectors** — Accurate pass/fail for node, jest, vitest, pytest, go, cargo, mocha, rspec, dotnet
34
34
  - **Unified hook pipeline** — Single process per hook event instead of separate processes per rule (reduced I/O)
35
- - **i18n message system** — All hook messages localized in en/ko/ja/zh
36
35
  - **Session event logging** — JSONL-based per-session event recording
37
36
  - **Alignment detection** — Scope drift tracking and major decision flagging
38
37
  - **Custom rules** — User-defined hook rules via config
@@ -52,10 +51,7 @@ Without structure, Claude does this:
52
51
  ## Installation
53
52
 
54
53
  ```bash
55
- npx claude-prism init # English, with hooks
56
- npx claude-prism init --lang=ko # Korean
57
- npx claude-prism init --lang=ja # Japanese
58
- npx claude-prism init --lang=zh # Chinese
54
+ npx claude-prism init # Install with hooks
59
55
  npx claude-prism init --no-hooks # Rules only, no hooks
60
56
  npx claude-prism init --global # Install as global skill (available in all projects)
61
57
  npx claude-prism update # Update rules and commands to latest
@@ -90,7 +86,7 @@ After running `prism init`, your project gains:
90
86
  - `alignment` — Detects scope drift (new directories outside base scope) and major decisions (package installs, db migrations, destructive deletes)
91
87
  - `turn-reporter` — Tracks turn count, warns at 5 autonomous turns without user input, provides previous turn summary
92
88
 
93
- **Configuration** — `.prism.json` stores language preference and hook settings. Includes OMC (oh-my-claudecode) detection.
89
+ **Configuration** — `.claude-prism.json` stores hook settings. Includes OMC (oh-my-claudecode) detection.
94
90
 
95
91
  ## File Structure After Installation
96
92
 
@@ -162,7 +158,7 @@ your-project/
162
158
  | `/claude-prism:plan` | Manage plan files | List, create, or view plans |
163
159
  | `/claude-prism:checkpoint` | Mid-project | Check batch progress, preview next batch |
164
160
  | `/claude-prism:doctor` | Installation issues | Diagnose health, suggest fixes |
165
- | `/claude-prism:stats` | Check current state | Version, hooks, language, plan progress |
161
+ | `/claude-prism:stats` | Check current state | Version, hooks, plan progress |
166
162
  | `/claude-prism:update` | After `npm update` | Update rules and commands to latest |
167
163
  | `/claude-prism:help` | Forgot commands | Quick reference |
168
164
 
@@ -221,7 +217,7 @@ User request arrives
221
217
  **Pattern 4: Quick Troubleshooting**
222
218
  ```
223
219
  /claude-prism:doctor → Check installation health
224
- /claude-prism:stats → Verify hooks, language, OMC status
220
+ /claude-prism:stats → Verify hooks, OMC status
225
221
  ```
226
222
 
227
223
  ### Before & After
@@ -356,7 +352,6 @@ Edit `.claude-prism.json` to customize behavior:
356
352
 
357
353
  ```json
358
354
  {
359
- "language": "en",
360
355
  "hooks": {
361
356
  "commit-guard": { "enabled": true, "maxTestAge": 300 },
362
357
  "debug-loop": { "enabled": true, "warnAt": 3, "blockAt": 5 },
@@ -367,7 +362,6 @@ Edit `.claude-prism.json` to customize behavior:
367
362
  ```
368
363
 
369
364
  **Settings:**
370
- - `language` — Rule language: `en` (English), `ko` (Korean), `ja` (Japanese), `zh` (Chinese)
371
365
  - `hooks.*` — Enable/disable individual hooks or customize thresholds
372
366
  - `hooks.commit-guard.maxTestAge` — Seconds before test is considered stale (default: 300)
373
367
  - `hooks.debug-loop.warnAt/blockAt` — Edit counts that trigger warnings/blocks
@@ -430,7 +424,7 @@ If issues are found:
430
424
 
431
425
  ### prism stats
432
426
 
433
- Show installation summary including version, language, hook status, plan file count, and OMC detection:
427
+ Show installation summary including version, hook status, plan file count, and OMC detection:
434
428
 
435
429
  ```bash
436
430
  prism stats
@@ -439,7 +433,6 @@ prism stats
439
433
  Output:
440
434
  ```
441
435
  Version: v0.4.0
442
- Language: en
443
436
  Plans: 2 file(s)
444
437
  OMC: ✅ v4.1.1
445
438
  Hooks:
@@ -472,23 +465,6 @@ npx claude-prism uninstall
472
465
 
473
466
  This removes CLAUDE.md rules, slash commands, and hooks.
474
467
 
475
- ## Languages
476
-
477
- Supported languages for UDEC rules:
478
-
479
- - **en** — English (default)
480
- - **ko** — Korean
481
- - **ja** — Japanese
482
- - **zh** — Chinese
483
-
484
- Change language (or re-install with different language):
485
-
486
- ```bash
487
- npx claude-prism init --lang=ko # Install Korean rules
488
- npx claude-prism init --lang=ja # Install Japanese rules
489
- npx claude-prism init --lang=zh # Install Chinese rules
490
- ```
491
-
492
468
  ## OMC (oh-my-claudecode) Integration
493
469
 
494
470
  Prism auto-detects if [oh-my-claudecode](https://github.com/raidenppl/oh-my-claudecode) is installed in your environment. When OMC is present:
package/bin/cli.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  /**
4
4
  * claude-prism CLI
5
- * Usage: prism init [--lang=ko] [--no-hooks]
5
+ * Usage: prism init [--no-hooks]
6
6
  * prism check [--ci]
7
7
  * prism doctor
8
8
  * prism stats
@@ -16,11 +16,6 @@ import { init, check, uninstall, update, doctor, stats, reset, initGlobal, unins
16
16
  const args = process.argv.slice(2);
17
17
  const command = args[0];
18
18
 
19
- function getFlag(name) {
20
- const flag = args.find(a => a.startsWith(`--${name}=`));
21
- return flag ? flag.split('=')[1] : null;
22
- }
23
-
24
19
  function hasFlag(name) {
25
20
  return args.includes(`--${name}`) || args.includes(`-${name}`);
26
21
  }
@@ -47,12 +42,11 @@ switch (command) {
47
42
  break;
48
43
  }
49
44
 
50
- const language = getFlag('lang') || 'en';
51
45
  const hooks = !hasFlag('no-hooks');
52
46
 
53
47
  if (hasFlag('dry-run')) {
54
48
  const { dryRun } = await import('../lib/installer.mjs');
55
- const result = dryRun(cwd, { language, hooks });
49
+ const result = dryRun(cwd, { hooks });
56
50
  console.log('🌈 claude-prism init --dry-run\n');
57
51
  console.log(' Files that would be created/updated:\n');
58
52
  for (const action of result.actions) {
@@ -64,7 +58,7 @@ switch (command) {
64
58
  }
65
59
 
66
60
  console.log('🌈 claude-prism init\n');
67
- await init(cwd, { language, hooks });
61
+ await init(cwd, { hooks });
68
62
 
69
63
  console.log('✅ Rules injected → CLAUDE.md');
70
64
  console.log('✅ Commands installed → /prism, /checkpoint');
@@ -121,7 +115,6 @@ switch (command) {
121
115
  const result = stats(cwd);
122
116
  console.log('🌈 claude-prism stats\n');
123
117
  console.log(` Version: v${result.version}`);
124
- console.log(` Language: ${result.language}`);
125
118
  console.log(` Plans: ${result.planFiles} file(s)`);
126
119
  console.log(` OMC: ${result.omc.detected ? `✅ v${result.omc.version || 'unknown'}` : '⏭️ not detected'}`);
127
120
  console.log(' Hooks:');
@@ -182,7 +175,7 @@ switch (command) {
182
175
  console.log(`🌈 claude-prism — AI coding problem decomposition tool
183
176
 
184
177
  Usage:
185
- prism init [--lang=XX] [--no-hooks] Install prism in current project
178
+ prism init [--no-hooks] Install prism in current project
186
179
  prism init --global Install globally (~/.claude/) + OMC skill
187
180
  prism check [--ci] Verify installation
188
181
  prism doctor Diagnose issues with fix suggestions
@@ -194,7 +187,6 @@ Usage:
194
187
  prism uninstall --global Remove global commands + OMC skill
195
188
 
196
189
  Options:
197
- --lang=XX Language: en (default), ko, ja, zh
198
190
  --no-hooks Skip enforcement hooks
199
191
  --dry-run Show what init would do without making changes
200
192
  --global Install/uninstall globally (all projects)
package/lib/config.mjs CHANGED
@@ -7,7 +7,6 @@ import { readFileSync, existsSync } from 'fs';
7
7
  import { join } from 'path';
8
8
 
9
9
  const DEFAULTS = {
10
- language: 'en',
11
10
  sourceExtensions: ['ts', 'tsx', 'js', 'jsx', 'py', 'go', 'rs', 'java', 'c', 'cpp', 'h', 'svelte', 'vue', 'rb', 'kt', 'swift', 'php', 'cs', 'scala', 'ex', 'clj', 'zig', 'lua', 'dart'],
12
11
  testPatterns: ['test', 'spec', '_test'],
13
12
  customRules: [],
@@ -39,7 +38,6 @@ export function getHookConfig(hookName, projectRoot) {
39
38
  const config = loadConfig(projectRoot);
40
39
  const hookConfig = config.hooks?.[hookName] || DEFAULTS.hooks[hookName] || { enabled: true };
41
40
  // Include top-level fields needed by hooks
42
- hookConfig.language = config.language || DEFAULTS.language;
43
41
  hookConfig.sourceExtensions = config.sourceExtensions || DEFAULTS.sourceExtensions;
44
42
  hookConfig.testPatterns = config.testPatterns || DEFAULTS.testPatterns;
45
43
  return hookConfig;
package/lib/installer.mjs CHANGED
@@ -16,11 +16,10 @@ const TEMPLATES_DIR = join(__dirname, '..', 'templates');
16
16
  * Initialize prism in a project
17
17
  * @param {string} projectDir - Project root
18
18
  * @param {Object} options
19
- * @param {string} options.language - 'en' | 'ko'
20
19
  * @param {boolean} options.hooks - Install enforcement hooks
21
20
  */
22
21
  export async function init(projectDir, options = {}) {
23
- const { language = 'en', hooks = true } = options;
22
+ const { hooks = true } = options;
24
23
 
25
24
  // 1. Create directories
26
25
  const claudeDir = join(projectDir, '.claude');
@@ -78,13 +77,12 @@ export async function init(projectDir, options = {}) {
78
77
  }
79
78
 
80
79
  // 4. Inject rules into CLAUDE.md
81
- injectRules(projectDir, language);
80
+ injectRules(projectDir);
82
81
 
83
82
  // 5. Create .claude-prism.json config
84
83
  const configPath = join(projectDir, '.claude-prism.json');
85
84
  if (!existsSync(configPath)) {
86
85
  writeFileSync(configPath, JSON.stringify({
87
- language,
88
86
  hooks: {
89
87
  'commit-guard': { enabled: true, maxTestAge: 300 },
90
88
  'debug-loop': { enabled: true, warnAt: 3, blockAt: 5 },
@@ -216,12 +214,10 @@ export async function update(projectDir) {
216
214
  }
217
215
 
218
216
  const configPath = newConfigPath;
219
- let language = 'en';
220
217
  let hooks = true;
221
218
 
222
219
  if (existsSync(configPath)) {
223
220
  const config = JSON.parse(readFileSync(configPath, 'utf8'));
224
- language = config.language || 'en';
225
221
  hooks = config.hooks?.['commit-guard']?.enabled !== false;
226
222
  }
227
223
 
@@ -241,7 +237,7 @@ export async function update(projectDir) {
241
237
  // Remove old config so init creates a fresh one
242
238
  if (existsSync(configPath)) rmSync(configPath);
243
239
 
244
- await init(projectDir, { language, hooks });
240
+ await init(projectDir, { hooks });
245
241
  }
246
242
 
247
243
  /**
@@ -356,7 +352,7 @@ export function doctor(projectDir, options = {}) {
356
352
  * @param {string} projectDir
357
353
  * @param {Object} [options]
358
354
  * @param {string} [options.homeDir] - Override home dir (for testing)
359
- * @returns {{ version: string, language: string, hooks: Object, planFiles: number, omc: Object }}
355
+ * @returns {{ version: string, hooks: Object, planFiles: number, omc: Object }}
360
356
  */
361
357
  export function stats(projectDir, options = {}) {
362
358
  // Read version from package.json
@@ -365,12 +361,10 @@ export function stats(projectDir, options = {}) {
365
361
 
366
362
  // Read config
367
363
  const configPath = join(projectDir, '.claude-prism.json');
368
- let language = 'en';
369
364
  let hookConfig = {};
370
365
 
371
366
  if (existsSync(configPath)) {
372
367
  const config = JSON.parse(readFileSync(configPath, 'utf8'));
373
- language = config.language || 'en';
374
368
  if (config.hooks) {
375
369
  for (const [name, cfg] of Object.entries(config.hooks)) {
376
370
  hookConfig[name] = cfg.enabled !== false;
@@ -390,7 +384,6 @@ export function stats(projectDir, options = {}) {
390
384
 
391
385
  return {
392
386
  version: pkg.version,
393
- language,
394
387
  hooks: hookConfig,
395
388
  planFiles,
396
389
  omc
@@ -463,7 +456,7 @@ export function uninstallGlobal(options = {}) {
463
456
  * @returns {{ actions: Array<{type: string, path: string, status: string}> }}
464
457
  */
465
458
  export function dryRun(projectDir, options = {}) {
466
- const { language = 'en', hooks = true } = options;
459
+ const { hooks = true } = options;
467
460
  const claudeDir = join(projectDir, '.claude');
468
461
  const actions = [];
469
462
 
@@ -531,16 +524,10 @@ export function dryRun(projectDir, options = {}) {
531
524
 
532
525
  // ─── internal helpers ───
533
526
 
534
- function injectRules(projectDir, language) {
527
+ function injectRules(projectDir) {
535
528
  const claudeMdPath = join(projectDir, 'CLAUDE.md');
536
- const rulesFile = `rules.${language}.md`;
537
- let rulesPath = join(TEMPLATES_DIR, rulesFile);
538
-
539
- // Fallback to English if requested language not available
540
- if (!existsSync(rulesPath)) {
541
- rulesPath = join(TEMPLATES_DIR, 'rules.en.md');
542
- if (!existsSync(rulesPath)) return;
543
- }
529
+ const rulesPath = join(TEMPLATES_DIR, 'rules.md');
530
+ if (!existsSync(rulesPath)) return;
544
531
 
545
532
  const rules = readFileSync(rulesPath, 'utf8');
546
533
 
package/lib/messages.mjs CHANGED
@@ -1,60 +1,21 @@
1
1
  /**
2
2
  * claude-prism — Hook Message Templates
3
- * Provides localized messages for hook output
4
3
  */
5
4
 
6
5
  const MESSAGES = {
7
- en: {
8
- 'commit-guard.block.failed': '🌈 Prism Commit blocked: last test run FAILED. Fix tests before committing.',
9
- 'commit-guard.warn.no-test': '🌈 Prism > No test run detected this session. Run tests before committing.',
10
- 'commit-guard.warn.stale': '🌈 Prism > Last test run was {minutes}min ago. Run tests before committing.',
11
- 'debug-loop.block.divergent': '🌈 Prism Debug Loop blocked: {name} edited {count} times on same area. Discuss approach with user before continuing.',
12
- 'debug-loop.warn.divergent': '🌈 Prism > Debug Loop: {name} edited {count} times on same area. Stop and investigate root cause.',
13
- 'debug-loop.warn.convergent': '🌈 Prism > Debug Loop: {name} edited {count} times (different areas). Consider if this is expected.',
14
- 'scope-guard.block': '🌈 Prism Scope Guard: {count} unique files modified without a plan. Run /prism to decompose before continuing.',
15
- 'scope-guard.warn': '🌈 Prism > Scope Guard: {count} unique files modified. Consider running /prism to decompose the task.',
16
- 'scope-guard.plan-detected': '🌈 Prism 📋 Plan file detected. Scope thresholds raised.',
17
- 'test-tracker.warn.failed': '🌈 Prism 📊 Tests FAILED. Fix before committing.',
18
- },
19
- ko: {
20
- 'commit-guard.block.failed': '🌈 Prism ✋ 커밋 차단: 마지막 테스트 실패. 테스트를 수정한 후 커밋하세요.',
21
- 'commit-guard.warn.no-test': '🌈 Prism > 이 세션에서 테스트 실행 이력이 없습니다. 커밋 전에 테스트를 실행하세요.',
22
- 'commit-guard.warn.stale': '🌈 Prism > 마지막 테스트가 {minutes}분 전입니다. 커밋 전에 테스트를 실행하세요.',
23
- 'debug-loop.block.divergent': '🌈 Prism ✋ 디버그 루프 차단: {name}이 같은 영역에서 {count}회 수정됨. 사용자와 접근 방식을 논의하세요.',
24
- 'debug-loop.warn.divergent': '🌈 Prism > 디버그 루프: {name}이 같은 영역에서 {count}회 수정됨. 멈추고 근본 원인을 조사하세요.',
25
- 'debug-loop.warn.convergent': '🌈 Prism > 디버그 루프: {name}이 {count}회 수정됨 (다른 영역). 예상된 작업인지 확인하세요.',
26
- 'scope-guard.block': '🌈 Prism ✋ 스코프 가드: 계획 없이 {count}개 고유 파일 수정됨. /prism으로 분해 후 계속하세요.',
27
- 'scope-guard.warn': '🌈 Prism > 스코프 가드: {count}개 고유 파일 수정됨. /prism으로 작업을 분해하는 것을 고려하세요.',
28
- 'scope-guard.plan-detected': '🌈 Prism 📋 계획 파일 감지됨. 스코프 임계값이 상향 조정되었습니다.',
29
- 'test-tracker.warn.failed': '🌈 Prism 📊 테스트 실패. 커밋 전에 수정하세요.',
30
- },
31
- ja: {
32
- 'commit-guard.block.failed': '🌈 Prism ✋ コミットブロック: 最後のテストが失敗しました。テストを修正してからコミットしてください。',
33
- 'commit-guard.warn.no-test': '🌈 Prism > このセッションでテスト実行が検出されません。コミット前にテストを実行してください。',
34
- 'commit-guard.warn.stale': '🌈 Prism > 最後のテスト実行は{minutes}分前です。コミット前にテストを実行してください。',
35
- 'debug-loop.block.divergent': '🌈 Prism ✋ デバッグループブロック: {name}が同じ領域で{count}回編集されました。ユーザーとアプローチを議論してください。',
36
- 'debug-loop.warn.divergent': '🌈 Prism > デバッグループ: {name}が同じ領域で{count}回編集されました。停止して根本原因を調査してください。',
37
- 'debug-loop.warn.convergent': '🌈 Prism > デバッグループ: {name}が{count}回編集されました(異なる領域)。想定通りか確認してください。',
38
- 'scope-guard.block': '🌈 Prism ✋ スコープガード: 計画なしに{count}個のファイルが変更されました。/prismで分解してから続行してください。',
39
- 'scope-guard.warn': '🌈 Prism > スコープガード: {count}個のファイルが変更されました。/prismでタスクの分解を検討してください。',
40
- 'scope-guard.plan-detected': '🌈 Prism 📋 計画ファイルを検出。スコープ閾値を引き上げました。',
41
- 'test-tracker.warn.failed': '🌈 Prism 📊 テスト失敗。コミット前に修正してください。',
42
- },
43
- zh: {
44
- 'commit-guard.block.failed': '🌈 Prism ✋ 提交被阻止:上次测试失败。请修复测试后再提交。',
45
- 'commit-guard.warn.no-test': '🌈 Prism > 本次会话未检测到测试运行。请在提交前运行测试。',
46
- 'commit-guard.warn.stale': '🌈 Prism > 上次测试运行在{minutes}分钟前。请在提交前运行测试。',
47
- 'debug-loop.block.divergent': '🌈 Prism ✋ 调试循环阻止:{name}在同一区域被编辑了{count}次。请与用户讨论方法。',
48
- 'debug-loop.warn.divergent': '🌈 Prism > 调试循环:{name}在同一区域被编辑了{count}次。停止并调查根本原因。',
49
- 'debug-loop.warn.convergent': '🌈 Prism > 调试循环:{name}被编辑了{count}次(不同区域)。请确认这是否是预期行为。',
50
- 'scope-guard.block': '🌈 Prism ✋ 范围守卫:未制定计划就修改了{count}个文件。请运行/prism分解后再继续。',
51
- 'scope-guard.warn': '🌈 Prism > 范围守卫:已修改{count}个文件。请考虑运行/prism来分解任务。',
52
- 'scope-guard.plan-detected': '🌈 Prism 📋 检测到计划文件。范围阈值已提高。',
53
- 'test-tracker.warn.failed': '🌈 Prism 📊 测试失败。请在提交前修复。',
54
- },
6
+ 'commit-guard.block.failed': '🌈 Prism ✋ Commit blocked: last test run FAILED. Fix tests before committing.',
7
+ 'commit-guard.warn.no-test': '🌈 Prism > No test run detected this session. Run tests before committing.',
8
+ 'commit-guard.warn.stale': '🌈 Prism > Last test run was {minutes}min ago. Run tests before committing.',
9
+ 'debug-loop.block.divergent': '🌈 Prism Debug Loop blocked: {name} edited {count} times on same area. Discuss approach with user before continuing.',
10
+ 'debug-loop.warn.divergent': '🌈 Prism > Debug Loop: {name} edited {count} times on same area. Stop and investigate root cause.',
11
+ 'debug-loop.warn.convergent': '🌈 Prism > Debug Loop: {name} edited {count} times (different areas). Consider if this is expected.',
12
+ 'scope-guard.block': '🌈 Prism Scope Guard: {count} unique files modified without a plan. Run /prism to decompose before continuing.',
13
+ 'scope-guard.warn': '🌈 Prism > Scope Guard: {count} unique files modified. Consider running /prism to decompose the task.',
14
+ 'scope-guard.plan-detected': '🌈 Prism 📋 Plan file detected. Scope thresholds raised.',
15
+ 'test-tracker.warn.failed': '🌈 Prism 📊 Tests FAILED. Fix before committing.',
55
16
  };
56
17
 
57
- export function getMessage(lang, key, params = {}) {
58
- const template = MESSAGES[lang]?.[key] || MESSAGES.en[key] || key;
18
+ export function getMessage(_lang, key, params = {}) {
19
+ const template = MESSAGES[key] || key;
59
20
  return template.replace(/\{(\w+)\}/g, (_, k) => params[k] ?? `{${k}}`);
60
21
  }
package/lib/pipeline.mjs CHANGED
@@ -80,7 +80,6 @@ export function runPipeline(rules, hookEventName) {
80
80
  for (const { name, rule } of rules) {
81
81
  // Build hook-specific config (same as getHookConfig but without re-reading file)
82
82
  const hookConfig = fullConfig.hooks?.[name] || { enabled: true };
83
- hookConfig.language = fullConfig.language || 'en';
84
83
  hookConfig.sourceExtensions = fullConfig.sourceExtensions;
85
84
  hookConfig.testPatterns = fullConfig.testPatterns;
86
85
 
@@ -157,7 +156,6 @@ export async function runPipelineAsync(builtInRules, hookEventName) {
157
156
 
158
157
  for (const { name, rule } of rules) {
159
158
  const hookConfig = fullConfig.hooks?.[name] || { enabled: true };
160
- hookConfig.language = fullConfig.language || 'en';
161
159
  hookConfig.sourceExtensions = fullConfig.sourceExtensions;
162
160
  hookConfig.testPatterns = fullConfig.testPatterns;
163
161
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-prism",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "AI coding problem decomposition tool — Understand, Decompose, Execute, Checkpoint.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,8 +33,7 @@
33
33
  "lib/",
34
34
  "hooks/",
35
35
  "templates/",
36
- "README.md",
37
- "README.ko.md"
36
+ "README.md"
38
37
  ],
39
38
  "repository": {
40
39
  "type": "git",