tillerhand 3.48.1 → 3.49.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 (108) hide show
  1. package/.claude/agents/board-chair.md +1 -1
  2. package/.claude/agents/security-auditor.md +1 -1
  3. package/.claude/agents/test-writer.md +1 -1
  4. package/.claude/board/board-product.md +1 -1
  5. package/.claude/board/council.md +1 -1
  6. package/.claude/board/rules.md +6 -6
  7. package/.claude/commands/adopt.md +3 -3
  8. package/.claude/commands/ask-mode.md +4 -4
  9. package/.claude/commands/board.md +1 -1
  10. package/.claude/commands/build.md +1 -1
  11. package/.claude/commands/design.md +4 -4
  12. package/.claude/commands/findings-business.md +1 -1
  13. package/.claude/commands/findings-legal.md +1 -1
  14. package/.claude/commands/findings-perf.md +1 -1
  15. package/.claude/commands/findings-security.md +2 -2
  16. package/.claude/commands/findings-tech.md +1 -1
  17. package/.claude/commands/findings-ux.md +1 -1
  18. package/.claude/commands/fix-bug.md +2 -2
  19. package/.claude/commands/handoff.md +2 -2
  20. package/.claude/commands/kit-update.md +2 -2
  21. package/.claude/commands/qa.md +1 -1
  22. package/.claude/commands/release.md +2 -2
  23. package/.claude/commands/research.md +3 -3
  24. package/.claude/commands/retro.md +1 -1
  25. package/.claude/commands/rollback.md +3 -3
  26. package/.claude/commands/start.md +4 -4
  27. package/.claude/commands/tools.md +1 -1
  28. package/.claude/commands/user-feedback.md +1 -1
  29. package/.claude/findings/lenses/business.md +1 -1
  30. package/.claude/findings/protocol.md +2 -2
  31. package/.claude/hooks/budget.mjs +1 -1
  32. package/.claude/hooks/checkpoint.mjs +2 -2
  33. package/.claude/hooks/commit-gate.mjs +14 -15
  34. package/.claude/hooks/council.mjs +37 -52
  35. package/.claude/hooks/dashboard-data.mjs +34 -42
  36. package/.claude/hooks/dashboard.mjs +18 -20
  37. package/.claude/hooks/destructive-guard.mjs +2 -2
  38. package/.claude/hooks/flow.mjs +1 -1
  39. package/.claude/hooks/freeze-guard.mjs +2 -2
  40. package/.claude/hooks/gate.mjs +18 -11
  41. package/.claude/hooks/labels.mjs +92 -152
  42. package/.claude/hooks/lang.mjs +25 -9
  43. package/.claude/hooks/messages.mjs +496 -494
  44. package/.claude/hooks/notify.mjs +1 -1
  45. package/.claude/hooks/prefs.mjs +10 -18
  46. package/.claude/hooks/preview.mjs +1 -1
  47. package/.claude/hooks/progress.mjs +7 -9
  48. package/.claude/hooks/qa-report.mjs +1 -3
  49. package/.claude/hooks/session-start.mjs +2 -3
  50. package/.claude/hooks/status-read.mjs +5 -5
  51. package/.claude/hooks/statusline.mjs +4 -4
  52. package/.claude/hooks/tools.mjs +3 -7
  53. package/.claude/hooks/usage.mjs +2 -2
  54. package/.claude/i18n/tr.json +495 -0
  55. package/.claude/security-patterns.json +1 -1
  56. package/.claude/skills/logo-design/SKILL.md +2 -2
  57. package/.claude/skills/motion-video/SKILL.md +1 -1
  58. package/.claude/skills/source-research/SKILL.md +1 -1
  59. package/.claude/skills/ui-motion/SKILL.md +1 -1
  60. package/AGENTS.md +1 -1
  61. package/CHANGELOG.md +1 -1
  62. package/README.md +2 -2
  63. package/README.tr.md +2 -2
  64. package/docs/architecture/overview.md +1 -1
  65. package/docs/decisions/log.md +1 -1
  66. package/docs/legal/privacy-kvkk.md +35 -35
  67. package/docs/operations/deploy-setup.md +1 -1
  68. package/docs/operations/feature-flags.md +1 -1
  69. package/docs/product/glossary.md +3 -3
  70. package/docs/product/launch.md +1 -1
  71. package/docs/product/prd.md +2 -2
  72. package/docs/product/roadmap.md +1 -1
  73. package/docs/product/specs/_template.md +1 -1
  74. package/docs/product/unit-economics.md +1 -1
  75. package/docs/quality/test-plan.md +5 -5
  76. package/docs/workflow/decision-protocol.md +1 -2
  77. package/docs/workflow/mcp-catalog.md +1 -1
  78. package/docs/workflow/skills.md +2 -2
  79. package/docs/workflow/usage-limits.md +1 -1
  80. package/kit/CHANGELOG.md +28 -0
  81. package/kit/VERSION +1 -1
  82. package/kit/guide.html +56 -56
  83. package/kit/guide.tr.html +10 -10
  84. package/kit/kit.mjs +7 -42
  85. package/kit/templates/addons/ai/.env.example.append +3 -3
  86. package/kit/templates/addons/tr/docs/legal/turkiye.md +55 -55
  87. package/kit/templates/addons/tr/types/backend/.env.example.append +2 -2
  88. package/kit/templates/addons/tr/types/backend/app/shared/payments.py +1 -1
  89. package/kit/templates/addons/tr/types/backend/tests/security/test_payment_webhook.py +3 -3
  90. package/kit/templates/addons/tr/types/web-saas/.env.example.append +2 -2
  91. package/kit/templates/addons/tr/types/web-saas/.github/workflows/payment-webhook.yml +3 -3
  92. package/kit/templates/addons/tr/types/web-saas/src/lib/payments/webhook-signature.ts +1 -1
  93. package/kit/templates/addons/tr/types/web-saas/tests/security/payment-webhook.mjs +4 -4
  94. package/kit/templates/backend/.github/dependabot.yml +1 -1
  95. package/kit/templates/backend/.github/workflows/live-monitoring.yml +1 -1
  96. package/kit/templates/backend/docs/architecture/stack.md +3 -3
  97. package/kit/templates/mobile/.github/dependabot.yml +1 -1
  98. package/kit/templates/mobile/.github/workflows/ci.yml +2 -2
  99. package/kit/templates/mobile/docs/architecture/stack.md +4 -4
  100. package/kit/templates/mobile/docs/architecture/structure.md +1 -1
  101. package/kit/templates/mobile/docs/design/design-guide.md +1 -1
  102. package/kit/templates/web-saas/.github/dependabot.yml +1 -1
  103. package/kit/templates/web-saas/.github/workflows/ci.yml +2 -2
  104. package/kit/templates/web-saas/.github/workflows/live-monitoring.yml +1 -1
  105. package/kit/templates/web-saas/docs/architecture/stack.md +4 -4
  106. package/kit/templates/web-saas/docs/design/design-guide.md +1 -1
  107. package/kit/tools/antigravity/.agents/hooks.json +5 -5
  108. package/package.json +1 -1
@@ -23,14 +23,14 @@ const stateFile = (root) => path.join(root, '.claude', 'state', 'lang.json');
23
23
  const i18nFile = (root, lang) => path.join(root, '.claude', 'i18n', `${lang}.json`);
24
24
  const placeholders = (s) => [...new Set([...s.matchAll(PLACEHOLDER)].map((m) => m[1]))].sort().join(',');
25
25
 
26
- // null: not set up and not chosen yet (/start asks). Projects set up before languages existed were Turkish.
26
+ // null: not set up and not chosen yet (/start asks). A set-up project without a choice is English.
27
27
  export function readLang(root = findRoot()) {
28
28
  const kit = readJson(kitFile(root));
29
29
  const chosen = validCode(kit?.lang) ?? validCode(readJson(stateFile(root))?.lang);
30
30
  if (chosen) return chosen;
31
31
  // same rule as status-read kitPending: a broken .kit.json counts as missing
32
32
  const notSetUp = kit ? kit.type === null : fs.existsSync(path.join(root, 'kit', 'kit.mjs'));
33
- return notSetUp ? null : 'tr';
33
+ return notSetUp ? null : 'en';
34
34
  }
35
35
 
36
36
  export function setLang(root, code) {
@@ -51,18 +51,34 @@ const translation = (root, lang) => {
51
51
  return j && typeof j === 'object' && !Array.isArray(j) ? j : {};
52
52
  };
53
53
 
54
+ // Per process: the dashboard calls t() hundreds of times; the modification time keeps a rewritten file visible
55
+ const cache = new Map();
56
+ const cachedTranslation = (root, lang) => {
57
+ const file = i18nFile(root, lang);
58
+ let stamp = 0;
59
+ try { stamp = fs.statSync(file).mtimeMs; } catch { /* no file: English */ }
60
+ const hit = cache.get(file);
61
+ if (hit?.stamp === stamp) return hit.own;
62
+ const own = translation(root, lang);
63
+ cache.set(file, { stamp, own });
64
+ return own;
65
+ };
66
+
54
67
  export function t(root, key, vars = {}) {
55
68
  if (!Object.hasOwn(MESSAGES, key)) return key;
56
69
  const lang = readLang(root) ?? 'en';
57
- let text = MESSAGES[key][lang];
58
- if (text === undefined) {
59
- const own = translation(root, lang);
60
- text = Object.hasOwn(own, key) && typeof own[key] === 'string' ? own[key] : MESSAGES[key].en;
61
- }
70
+ const own = lang === 'en' ? {} : cachedTranslation(root, lang);
71
+ const en = MESSAGES[key].en;
72
+ // A hand-edited text that drops or adds a placeholder could hide what an approval dialog asks: English instead
73
+ const text = Object.hasOwn(own, key) && typeof own[key] === 'string' && placeholders(own[key]) === placeholders(en) ? own[key] : en;
62
74
  return text.replace(PLACEHOLDER, (m, name) => Object.hasOwn(vars, name) ? String(vars[name]) : m);
63
75
  }
64
76
 
65
- const needsTranslation = (lang) => lang !== null && lang !== 'tr' && lang !== 'en';
77
+ // Date and number locale for a language code (English when the runtime does not know the code)
78
+ export const locale = (lang) => { try { return Intl.DateTimeFormat.supportedLocalesOf(lang ?? 'en')[0] ?? 'en'; } catch { return 'en'; } };
79
+
80
+ // Every language but English reads .claude/i18n/<lang>.json (tr ships with the kit)
81
+ const needsTranslation = (lang) => Boolean(lang) && lang !== 'en';
66
82
 
67
83
  export function missingKeys(root = findRoot()) {
68
84
  const lang = readLang(root);
@@ -73,7 +89,7 @@ export function missingKeys(root = findRoot()) {
73
89
 
74
90
  export function writeTranslation(root, obj) {
75
91
  const lang = readLang(root);
76
- if (!needsTranslation(lang)) throw new Error(`No translation file for language ${lang ?? 'none'}: tr and en are built in.`);
92
+ if (!needsTranslation(lang)) throw new Error(`No translation file for language ${lang ?? 'none'}: en is built in.`);
77
93
  if (!obj || typeof obj !== 'object' || Array.isArray(obj) || Object.getPrototypeOf(obj) !== Object.prototype) throw new Error('Translation must be a JSON object { key: text }.');
78
94
  for (const [k, v] of Object.entries(obj)) {
79
95
  if (!Object.hasOwn(MESSAGES, k)) throw new Error(`Unknown key: ${k}`);