tillerhand 3.47.0 → 3.48.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 (111) hide show
  1. package/.claude/agents/board-chair.md +9 -9
  2. package/.claude/agents/code-reviewer.md +2 -2
  3. package/.claude/agents/council-advisor.md +2 -2
  4. package/.claude/agents/security-auditor.md +6 -6
  5. package/.claude/agents/test-writer.md +1 -1
  6. package/.claude/board/board-ai.md +6 -6
  7. package/.claude/board/board-api.md +6 -6
  8. package/.claude/board/board-architect.md +7 -7
  9. package/.claude/board/board-devops.md +6 -6
  10. package/.claude/board/board-mobile.md +6 -6
  11. package/.claude/board/board-performance.md +6 -6
  12. package/.claude/board/board-privacy.md +6 -6
  13. package/.claude/board/board-product.md +7 -7
  14. package/.claude/board/board-qa.md +7 -7
  15. package/.claude/board/board-ux.md +6 -6
  16. package/.claude/board/council.md +32 -32
  17. package/.claude/board/rules.md +8 -8
  18. package/.claude/commands/adopt.md +10 -10
  19. package/.claude/commands/ask-mode.md +6 -5
  20. package/.claude/commands/board.md +1 -1
  21. package/.claude/commands/build.md +10 -10
  22. package/.claude/commands/design.md +8 -8
  23. package/.claude/commands/findings-all.md +2 -2
  24. package/.claude/commands/findings-security.md +1 -1
  25. package/.claude/commands/fix-bug.md +3 -3
  26. package/.claude/commands/handoff.md +12 -12
  27. package/.claude/commands/language.md +1 -1
  28. package/.claude/commands/maintain.md +2 -2
  29. package/.claude/commands/plan-task.md +3 -3
  30. package/.claude/commands/qa.md +5 -5
  31. package/.claude/commands/release.md +3 -3
  32. package/.claude/commands/research.md +2 -2
  33. package/.claude/commands/retro.md +2 -2
  34. package/.claude/commands/review-changes.md +2 -2
  35. package/.claude/commands/rollback.md +1 -1
  36. package/.claude/commands/start.md +20 -20
  37. package/.claude/commands/tools.md +8 -6
  38. package/.claude/commands/user-feedback.md +3 -3
  39. package/.claude/commands/wrap-up.md +3 -3
  40. package/.claude/findings/protocol.md +2 -2
  41. package/.claude/findings/report-template.md +1 -1
  42. package/.claude/hooks/commit-gate.mjs +11 -9
  43. package/.claude/hooks/council.mjs +51 -24
  44. package/.claude/hooks/dashboard-data.mjs +73 -53
  45. package/.claude/hooks/dashboard.mjs +80 -71
  46. package/.claude/hooks/destructive-guard.mjs +1 -1
  47. package/.claude/hooks/freeze-guard.mjs +1 -1
  48. package/.claude/hooks/gate.mjs +14 -11
  49. package/.claude/hooks/labels.mjs +177 -0
  50. package/.claude/hooks/messages.mjs +8 -7
  51. package/.claude/hooks/notify.mjs +2 -1
  52. package/.claude/hooks/prefs.mjs +24 -10
  53. package/.claude/hooks/preview.mjs +6 -6
  54. package/.claude/hooks/progress.mjs +27 -15
  55. package/.claude/hooks/qa-report.mjs +12 -10
  56. package/.claude/hooks/session-start.mjs +9 -7
  57. package/.claude/hooks/status-read.mjs +22 -18
  58. package/.claude/hooks/statusline.mjs +10 -8
  59. package/.claude/hooks/tools.mjs +13 -8
  60. package/.claude/output-styles/{anlatici.md → narrator.md} +2 -2
  61. package/.claude/skills/logo-design/SKILL.md +2 -2
  62. package/.claude/skills/source-research/SKILL.md +1 -1
  63. package/.claude/skills/ui-motion/SKILL.md +2 -2
  64. package/AGENTS.md +12 -12
  65. package/CLAUDE.md +1 -1
  66. package/README.md +2 -2
  67. package/README.tr.md +3 -3
  68. package/docs/decisions/adr-template.md +1 -1
  69. package/docs/decisions/log.md +2 -2
  70. package/docs/findings/README.md +1 -1
  71. package/docs/operations/accounts.md +7 -7
  72. package/docs/operations/deploy-setup.md +3 -3
  73. package/docs/operations/feature-flags.md +2 -2
  74. package/docs/operations/maintenance.md +1 -1
  75. package/docs/operations/release-checklist.md +2 -2
  76. package/docs/operations/spend-alarms.md +2 -2
  77. package/docs/product/feedback.md +4 -4
  78. package/docs/product/launch.md +1 -1
  79. package/docs/product/prd.md +10 -10
  80. package/docs/product/roadmap.md +8 -8
  81. package/docs/product/specs/_template.md +8 -8
  82. package/docs/product/unit-economics.md +10 -10
  83. package/docs/quality/metrics.md +2 -2
  84. package/docs/quality/test-plan.md +5 -5
  85. package/docs/security/checklist.md +2 -2
  86. package/docs/workflow/board.md +5 -5
  87. package/docs/workflow/cost-log.md +1 -1
  88. package/docs/workflow/decision-protocol.md +18 -16
  89. package/docs/workflow/learning.md +2 -2
  90. package/docs/workflow/mcp-catalog.md +1 -1
  91. package/docs/workflow/models.md +1 -1
  92. package/docs/workflow/progress.md +14 -14
  93. package/docs/workflow/skills.md +9 -9
  94. package/docs/workflow/usage-limits.md +5 -5
  95. package/kit/CHANGELOG.md +25 -0
  96. package/kit/VERSION +1 -1
  97. package/kit/guide.html +21 -21
  98. package/kit/guide.tr.html +21 -21
  99. package/kit/kit.mjs +29 -0
  100. package/kit/project/README.md +1 -1
  101. package/kit/templates/backend/docs/architecture/stack.md +7 -7
  102. package/kit/templates/backend/docs/architecture/structure.md +2 -2
  103. package/kit/templates/mobile/docs/architecture/stack.md +5 -5
  104. package/kit/templates/mobile/docs/architecture/structure.md +1 -1
  105. package/kit/templates/mobile/docs/design/design-guide.md +1 -1
  106. package/kit/templates/mobile/tests/security/rls.mjs +4 -4
  107. package/kit/templates/web-saas/docs/architecture/stack.md +12 -12
  108. package/kit/templates/web-saas/docs/architecture/structure.md +2 -2
  109. package/kit/templates/web-saas/docs/design/design-guide.md +1 -1
  110. package/kit/templates/web-saas/tests/security/rls.mjs +4 -4
  111. package/package.json +1 -1
@@ -59,13 +59,13 @@ function publicTables(t) {
59
59
  }
60
60
  }
61
61
 
62
- test('SALDIRI: RLS is on for every public table', (t) => {
62
+ test('ATTACK: RLS is on for every public table', (t) => {
63
63
  const tables = publicTables(t);
64
64
  if (!tables) return;
65
65
  assert.deepEqual(tables.filter((x) => !x.rls).map((x) => x.name), [], 'table with RLS off: write "alter table ... enable row level security" and a policy');
66
66
  });
67
67
 
68
- test('SALDIRI: RLS every public table is registered in this test', (t) => {
68
+ test('ATTACK: RLS every public table is registered in this test', (t) => {
69
69
  const tables = publicTables(t);
70
70
  if (!tables) return;
71
71
  const registered = new Set([...TABLES, ...PUBLIC_TABLES].map((x) => x.name));
@@ -73,7 +73,7 @@ test('SALDIRI: RLS every public table is registered in this test', (t) => {
73
73
  });
74
74
 
75
75
  for (const { name, owner, sample, key = 'id' } of TABLES) {
76
- test(`SALDIRI: RLS ${name} is closed to other users and to anonymous`, async () => {
76
+ test(`ATTACK: RLS ${name} is closed to other users and to anonymous`, async () => {
77
77
  const [a, b] = users;
78
78
  const anon = client(ANON);
79
79
  const { data: row, error } = await a.c.from(name).insert({ ...sample(), [owner]: a.id }).select().single();
@@ -92,7 +92,7 @@ for (const { name, owner, sample, key = 'id' } of TABLES) {
92
92
  }
93
93
 
94
94
  for (const { name, sample } of PUBLIC_TABLES) {
95
- test(`SALDIRI: RLS ${name} is public to read but closed to writes`, async () => {
95
+ test(`ATTACK: RLS ${name} is public to read but closed to writes`, async () => {
96
96
  assert.ok((await client(ANON).from(name).insert(sample())).error, 'anonymous can write');
97
97
  assert.ok((await users[1].c.from(name).insert(sample())).error, 'a signed-in user can write');
98
98
  });
@@ -5,24 +5,24 @@
5
5
 
6
6
  ## Decision points
7
7
 
8
- `/start` asks these decisions in order (`docs/workflow/decision-protocol.md`). For each decision, offer the 2-4 options that best fit this project. The **recommended** label is the default, but if another option fits the PRD better, recommend that one and say why. If a claim that can change (price, free tier, limit) carries a `(kaynak: <adres>, YYYY-AA-GG)` note newer than 90 days, do not research it again.
8
+ `/start` asks these decisions in order (`docs/workflow/decision-protocol.md`). For each decision, offer the 2-4 options that best fit this project. The **recommended** label is the default, but if another option fits the PRD better, recommend that one and say why. If a claim that can change (price, free tier, limit) carries a `(source: <url>, YYYY-MM-DD)` note newer than 90 days, do not research it again.
9
9
 
10
10
  | # | Decision | Options (when each is better) |
11
11
  |---|---|---|
12
12
  | 1 | Framework | **Next.js** (recommended: SEO + dashboard + API in one project, the ecosystem the AI knows best) · Astro (content/landing-page heavy, fastest pages) · SvelteKit (less code, fast; smaller ecosystem) · React + Vite SPA (app only behind login, no SEO need, simplest hosting) |
13
13
  | 2 | Language | **TypeScript** (recommended: catches AI mistakes at compile time) · JavaScript (only for a very small prototype) |
14
- | 3 | Database + identity | **Supabase** (recommended: Postgres + Auth + Storage + RLS in one place; free tier has 2 active projects, 500 MB database per project, a project idle for 1 week is paused (kaynak: https://supabase.com/pricing, 2026-10-26)) · Neon + Better Auth (more control, less provider lock-in) · Firebase (realtime, NoSQL, shared backend with mobile) · Clerk + Postgres (ready-made, polished identity UI; first 50,000 monthly returning users free, then per-user fee (kaynak: https://clerk.com/billing, 2026-10-26)) |
14
+ | 3 | Database + identity | **Supabase** (recommended: Postgres + Auth + Storage + RLS in one place; free tier has 2 active projects, 500 MB database per project, a project idle for 1 week is paused (source: https://supabase.com/pricing, 2026-10-26)) · Neon + Better Auth (more control, less provider lock-in) · Firebase (realtime, NoSQL, shared backend with mobile) · Clerk + Postgres (ready-made, polished identity UI; first 50,000 monthly returning users free, then per-user fee (source: https://clerk.com/billing, 2026-10-26)) |
15
15
  | 4 | Data access | **Supabase client + RLS** (if Supabase is chosen) · Drizzle ORM (type-safe SQL, provider-independent) · Prisma (mature, schema-driven; heavier) |
16
16
  | 5 | UI components | **shadcn/ui + Tailwind** (recommended: code lives in the project, fully customizable, works with the design skills) · Tailwind + own components (fully original design) · Mantine (rich ready-made components, dashboard heavy) |
17
- | 6 | Payment | None (free in the first release) · **iyzico** (Turkish cards, installments, TRY) · Stripe (customers abroad; may be restricted for a Turkish company: Turkey does not appear in the supported-country list (kaynak: https://stripe.com/global, 2026-10-26)) · Paddle / Lemon Squeezy (merchant of record: they handle tax and invoicing; subscriptions sold abroad) |
18
- | 7 | Hosting | **Vercel** (recommended for Next.js: zero config, preview environments; the free Hobby plan is for personal, non-commercial use only, a product that takes payments or shows ads needs Pro (kaynak: https://vercel.com/docs/limits/fair-use-guidelines, 2026-10-26)) · Cloudflare (cheap and fast; free Workers are limited to 100,000 requests per day and 10 ms CPU per request (kaynak: https://developers.cloudflare.com/workers/platform/limits/, 2026-10-26)) · Netlify · Your own server + Coolify (fixed cost, maintenance is yours) |
19
- | 8 | Email | **Resend** (recommended: developer friendly, React email templates; free plan gives 3,000 emails per month, 100 per day (kaynak: https://resend.com/pricing, 2026-10-26)) · Postmark (very high deliverability) · Amazon SES (cheapest, hard to set up) |
20
- | 9 | Analytics | **Plausible** (cookieless, KVKK friendly; no free plan, starts at 9 dollars per month, 30-day trial (kaynak: https://plausible.io/docs/billing, 2026-10-26)) · PostHog (product analytics, funnels, feature flags) · Umami (self-host, free) · None |
17
+ | 6 | Payment | None (free in the first release) · **iyzico** (Turkish cards, installments, TRY) · Stripe (customers abroad; may be restricted for a Turkish company: Turkey does not appear in the supported-country list (source: https://stripe.com/global, 2026-10-26)) · Paddle / Lemon Squeezy (merchant of record: they handle tax and invoicing; subscriptions sold abroad) |
18
+ | 7 | Hosting | **Vercel** (recommended for Next.js: zero config, preview environments; the free Hobby plan is for personal, non-commercial use only, a product that takes payments or shows ads needs Pro (source: https://vercel.com/docs/limits/fair-use-guidelines, 2026-10-26)) · Cloudflare (cheap and fast; free Workers are limited to 100,000 requests per day and 10 ms CPU per request (source: https://developers.cloudflare.com/workers/platform/limits/, 2026-10-26)) · Netlify · Your own server + Coolify (fixed cost, maintenance is yours) |
19
+ | 8 | Email | **Resend** (recommended: developer friendly, React email templates; free plan gives 3,000 emails per month, 100 per day (source: https://resend.com/pricing, 2026-10-26)) · Postmark (very high deliverability) · Amazon SES (cheapest, hard to set up) |
20
+ | 9 | Analytics | **Plausible** (cookieless, KVKK friendly; no free plan, starts at 9 dollars per month, 30-day trial (source: https://plausible.io/docs/billing, 2026-10-26)) · PostHog (product analytics, funnels, feature flags) · Umami (self-host, free) · None |
21
21
  | 10 | Error tracking | **Sentry** (recommended) · Highlight / Better Stack |
22
22
  | 11 | Language support | **Turkish only** (recommended for the MVP) · Turkish + English (next-intl; setting it up from the start is cheaper than adding it later) |
23
23
  | 12 | Test | **Vitest + Playwright** (recommended) · Playwright only (little logic, mostly UI) |
24
24
 
25
- ## Seçilen teknolojiler
25
+ ## Chosen technologies
26
26
 
27
27
  > `/start` fills this in at Step 4 from the decision points. The table below is the **recommended** stack and counts as a proposal until approved.
28
28
  > If the choice differs, rewrite the commands, folder, rules, verification and checks sections of this file to match the choice.
@@ -41,7 +41,7 @@
41
41
  | Analytics | Plausible / PostHog | Watch cookie consent |
42
42
  | Test | Vitest (unit), Playwright (e2e) | |
43
43
 
44
- ## Komutlar (commands)
44
+ ## Commands (commands)
45
45
 
46
46
  ```bash
47
47
  npm run dev # development
@@ -83,7 +83,7 @@ src/
83
83
  └── middleware.ts
84
84
  public/ # static files
85
85
  tests/
86
- ├── e2e/ # Playwright acceptance tests (Ö-01.1 ...)
86
+ ├── e2e/ # Playwright acceptance tests (AC-01.1 ...)
87
87
  └── live/ # live monitoring tests (that delete no data)
88
88
  supabase/migrations/ # database changes ONLY here
89
89
  ```
@@ -103,7 +103,7 @@ supabase/migrations/ # database changes ONLY here
103
103
 
104
104
  ## Verification (evidence before a task is done)
105
105
 
106
- - UI: `node .claude/hooks/preview.mjs <task id>` takes a desktop (1440) and mobile (390) screenshot (the `geliştirme:` and `önizleme:` lines in `AGENTS.md`). To try scenarios, with `npm run dev` running, open the page with the Playwright CLI (`npx -y @playwright/cli@0.1.22 open http://localhost:3000`, then `snapshot`, `console`, `screenshot`) or with Claude's browser, and try the main scenario and one error scenario.
106
+ - UI: `node .claude/hooks/preview.mjs <task id>` takes a desktop (1440) and mobile (390) screenshot (the `dev:` and `preview:` lines in `AGENTS.md`). To try scenarios, with `npm run dev` running, open the page with the Playwright CLI (`npx -y @playwright/cli@0.1.22 open http://localhost:3000`, then `snapshot`, `console`, `screenshot`) or with Claude's browser, and try the main scenario and one error scenario.
107
107
  - Proving acceptance criteria in the browser: `/qa` (one Playwright test per criterion, report in `docs/quality/qa/`).
108
108
  - Authorization: with a second test user, try to reach the first user's record; it must fail.
109
109
  - No errors/warnings in the console.
@@ -120,7 +120,7 @@ supabase/migrations/ # database changes ONLY here
120
120
 
121
121
  ## Acceptance tests and feature flags
122
122
 
123
- **Acceptance tests** (`docs/quality/test-plan.md` §1a): The test name carries the criterion id (`test('Ö-01.1 ...')`). The dashboard reads the JUnit report:
123
+ **Acceptance tests** (`docs/quality/test-plan.md` §1a): The test name carries the criterion id (`test('AC-01.1 ...')`). The dashboard reads the JUnit report:
124
124
 
125
125
  ```bash
126
126
  PLAYWRIGHT_JUNIT_OUTPUT_NAME=test-results/junit.xml npx playwright test --reporter=list,junit
@@ -129,7 +129,7 @@ npx vitest run --reporter=default --reporter=junit --outputFile.junit=test-resul
129
129
 
130
130
  **Feature flags** (`docs/operations/feature-flags.md`): Emergency shutdown must not need a deploy. So use a source read at runtime, not an environment variable:
131
131
  - PostHog feature flags if PostHog is chosen; otherwise
132
- - A `feature_flags` table in Supabase (`ad`, `acik`, `yuzde`) + a 60 s cache on the server. Reading goes through one helper: `lib/bayrak.ts` → `bayrakAcik('ad', kullanici)`.
132
+ - A `feature_flags` table in Supabase (`name`, `enabled`, `percent`) + a 60 s cache on the server. Reading goes through one helper: `lib/flags.ts` → `isEnabled('name', user)`.
133
133
  - The flag check runs on the server; the client only sees the result.
134
134
 
135
135
  ## Common AI mistakes (watch for these)
@@ -32,7 +32,7 @@ src/
32
32
  └── middleware.ts
33
33
  public/ # static files
34
34
  tests/
35
- ├── e2e/ # Playwright acceptance tests (Ö-01.1 ...)
35
+ ├── e2e/ # Playwright acceptance tests (AC-01.1 ...)
36
36
  └── live/ # live monitoring tests (that delete no data)
37
37
  supabase/migrations/ # database changes ONLY here
38
38
  ```
@@ -68,4 +68,4 @@ supabase/migrations/ # database changes ONLY here
68
68
  4. **Naming:** Folders and files use `kebab-case`. React component files may use `PascalCase.tsx`; Python modules use `snake_case.py`. A feature folder name is singular and English (`invoice`, `customer`).
69
69
  5. **Temporary and unrelated work** goes under `sandbox/`. If something useful comes out, it moves to the right place; `sandbox/` is cleaned regularly.
70
70
  6. **Old documents** are not deleted; they move under `docs/archive/` with a line at the top saying why they were archived.
71
- 7. **Changing the map** (a new top-level folder, a new layer) is a `teknik` decision: ask the user, record it under `docs/decisions/`, then update `.claude/structure.json` and this file.
71
+ 7. **Changing the map** (a new top-level folder, a new layer) is a `tech` decision: ask the user, record it under `docs/decisions/`, then update `.claude/structure.json` and this file.
@@ -8,7 +8,7 @@
8
8
  > Decisions are made with `/design` using **visual previews** (`docs/workflow/decision-protocol.md` §5). If a new color, size or component
9
9
  > is needed, it is asked as a decision first, then added to DESIGN.md. No raw colors or arbitrary sizes in code.
10
10
 
11
- ## 1. Seçilen yön (Chosen direction)
11
+ ## 1. Chosen direction (Chosen direction)
12
12
 
13
13
  | Area | Choice | Skill | Preview | Date |
14
14
  |---|---|---|---|---|
@@ -59,13 +59,13 @@ function publicTables(t) {
59
59
  }
60
60
  }
61
61
 
62
- test('SALDIRI: RLS is on for every public table', (t) => {
62
+ test('ATTACK: RLS is on for every public table', (t) => {
63
63
  const tables = publicTables(t);
64
64
  if (!tables) return;
65
65
  assert.deepEqual(tables.filter((x) => !x.rls).map((x) => x.name), [], 'table with RLS off: write "alter table ... enable row level security" and a policy');
66
66
  });
67
67
 
68
- test('SALDIRI: RLS every public table is registered in this test', (t) => {
68
+ test('ATTACK: RLS every public table is registered in this test', (t) => {
69
69
  const tables = publicTables(t);
70
70
  if (!tables) return;
71
71
  const registered = new Set([...TABLES, ...PUBLIC_TABLES].map((x) => x.name));
@@ -73,7 +73,7 @@ test('SALDIRI: RLS every public table is registered in this test', (t) => {
73
73
  });
74
74
 
75
75
  for (const { name, owner, sample, key = 'id' } of TABLES) {
76
- test(`SALDIRI: RLS ${name} is closed to other users and to anonymous`, async () => {
76
+ test(`ATTACK: RLS ${name} is closed to other users and to anonymous`, async () => {
77
77
  const [a, b] = users;
78
78
  const anon = client(ANON);
79
79
  const { data: row, error } = await a.c.from(name).insert({ ...sample(), [owner]: a.id }).select().single();
@@ -92,7 +92,7 @@ for (const { name, owner, sample, key = 'id' } of TABLES) {
92
92
  }
93
93
 
94
94
  for (const { name, sample } of PUBLIC_TABLES) {
95
- test(`SALDIRI: RLS ${name} is public to read but closed to writes`, async () => {
95
+ test(`ATTACK: RLS ${name} is public to read but closed to writes`, async () => {
96
96
  assert.ok((await client(ANON).from(name).insert(sample())).error, 'anonymous can write');
97
97
  assert.ok((await users[1].c.from(name).insert(sample())).error, 'a signed-in user can write');
98
98
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tillerhand",
3
- "version": "3.47.0",
3
+ "version": "3.48.0",
4
4
  "description": "Vibe coding kit for Claude Code, Codex and Antigravity: rules, commands, guards and project templates.",
5
5
  "license": "MIT",
6
6
  "type": "module",