tillerhand 3.50.0 → 3.51.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/.claude/hooks/commit-gate.mjs +42 -12
- package/.claude/hooks/messages.mjs +3 -0
- package/.claude/i18n/tr.json +3 -0
- package/.claude/settings.json +5 -0
- package/AGENTS.md +9 -3
- package/README.md +2 -2
- package/README.tr.md +2 -2
- package/docs/workflow/decision-protocol.md +9 -4
- package/kit/CHANGELOG.md +14 -0
- package/kit/VERSION +1 -1
- package/kit/guide.html +21 -9
- package/kit/guide.tr.html +18 -10
- package/package.json +1 -1
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
// PreToolUse (Bash) hook: without review approval it stops the commit with exit code 2 and says what to do.
|
|
4
4
|
// node .claude/hooks/commit-gate.mjs --approve "<members who took part, or a note>" binds the approval to the current changes.
|
|
5
5
|
// node .claude/hooks/commit-gate.mjs --skip "<reason>" only when the user asks: skips the board and the gate (always asked).
|
|
6
|
+
// Commands that make commits with no working-tree change to review (git merge, git revert…) and git calls the text cannot
|
|
7
|
+
// read ($g commit, git $(echo commit)) have nothing to bind an approval to: the user is asked.
|
|
6
8
|
// Exempt: no board set up, "Commit review: off" in docs/workflow/board.md, or only docs changed.
|
|
7
9
|
// Commits the user makes from their own terminal are not affected (this is a Claude Code hook).
|
|
8
10
|
import fs from 'node:fs';
|
|
@@ -11,14 +13,14 @@ import crypto from 'node:crypto';
|
|
|
11
13
|
import { execSync } from 'node:child_process';
|
|
12
14
|
import { findRoot, isMain, reviewOff, parseInput, decisionText } from './shared.mjs';
|
|
13
15
|
import { t } from './lang.mjs';
|
|
14
|
-
import { unquote } from './destructive-guard.mjs';
|
|
16
|
+
import { unquote, MAX_COMMAND } from './destructive-guard.mjs';
|
|
15
17
|
import { isTestFile, isTestConfig, digest, readRecord } from './test-guard.mjs';
|
|
16
18
|
import { isCodeFile } from './edit-rounds.mjs';
|
|
17
19
|
|
|
18
20
|
// Project root (the script's location) even when called from a subfolder: approval and gate must not be written elsewhere
|
|
19
21
|
const root = findRoot();
|
|
20
22
|
const approvalFile = path.join(root, '.claude', 'state', 'commit-approval.json');
|
|
21
|
-
const git = (c) => execSync(`git ${c}`, { cwd: root, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], maxBuffer: 64 * 1024 * 1024 });
|
|
23
|
+
const git = (c) => execSync(`git ${c}`, { cwd: root, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], maxBuffer: 64 * 1024 * 1024, timeout: 20000 });
|
|
22
24
|
|
|
23
25
|
// Changes that will go into the commit: staged, unstaged in tracked files (git commit -a) and untracked new
|
|
24
26
|
// files (git add -A && git commit). -z: non-ASCII or spaced paths are not quoted and escaped
|
|
@@ -56,8 +58,28 @@ export function changes() {
|
|
|
56
58
|
export const sinceApproval = (approval, d) => d.files.filter((f) => !approval?.hashes || !Object.hasOwn(approval.hashes, f) || approval.hashes[f] !== d.hashes[f]);
|
|
57
59
|
|
|
58
60
|
// git's global options may come before commit: git --no-pager commit, git -C x commit, git --git-dir=x commit; git.exe on Windows
|
|
59
|
-
|
|
61
|
+
// Every option has one reading: with two, "-c -c -c …" or "--a --a --a …" backtracks exponentially, and a hook that times out lets the command run.
|
|
62
|
+
const VALUE_OPTIONS = '(?:-[cC]|--(?:git-dir|work-tree|namespace|exec-path|super-prefix|config-env|attr-source))';
|
|
63
|
+
// One shell word: git -C "my dir" commit, git -c user.name='A B' commit, git -C my\ dir commit
|
|
64
|
+
const WORD = `(?:"[^"]*"|'[^']*'|\\\\.|[^\\s"'\\\\])+`;
|
|
65
|
+
const GLOBALS = `(?:\\s+(?:${VALUE_OPTIONS}\\s+${WORD}|(?!${VALUE_OPTIONS}\\s)-[\\w-]+(?:=${WORD})?))*`;
|
|
66
|
+
const VERB_END = '(?=\\s|$|["\';&|)])';
|
|
67
|
+
// i: Windows runs GIT.exe as git. $GIT is a variable, not git by name.
|
|
68
|
+
const commitRe = (verbs) => new RegExp(`(?<!\\$)\\bgit(?:\\.exe)?["']?${GLOBALS}\\s+["']?(?:${verbs.join('|')})${VERB_END}`, 'i');
|
|
60
69
|
const COMMIT = commitRe(['commit']);
|
|
70
|
+
// shortcut: these rules read text, so a quoted mention (grep "git merge") also asks; a script file, xargs git, base64 | sh or a mixed-quote spelling (git -C "a b" c"ommit") is not seen; a git hook would close that.
|
|
71
|
+
const MAKES_COMMITS = ['merge', 'cherry-pick', 'revert', 'am', 'rebase', 'commit-tree', 'fast-import'];
|
|
72
|
+
const OTHER_COMMIT = [
|
|
73
|
+
// git merge, git $(echo commit), git "$@"
|
|
74
|
+
commitRe([...MAKES_COMMITS, '[$`%@]\\S*']),
|
|
75
|
+
// $g commit, $(which git) merge, %g% commit
|
|
76
|
+
new RegExp(`(?:\\$\\{?\\w+\\}?|\\$\\([^)\\n]{0,200}\\)|\`[^\`\\n]{0,200}\`|%\\w+%)["']?${GLOBALS}\\s+["']?(?:commit|${MAKES_COMMITS.join('|')})${VERB_END}`, 'i'),
|
|
77
|
+
];
|
|
78
|
+
// Backing out makes no commit, but only as a whole command: git merge x # --abort still merges
|
|
79
|
+
const BACK_OUT = new RegExp(`\\bgit(?:\\.exe)?${GLOBALS}\\s+(?:merge|cherry-pick|revert|am|rebase)\\s+--(?:abort|quit)(?=\\s*(?:$|[;&|\\n]))`, 'gi');
|
|
80
|
+
const makesOtherCommit = (command) => OTHER_COMMIT.some((re) => re.test(command.replace(BACK_OUT, '')));
|
|
81
|
+
// These rules are not linear in the length, and a hook that times out lets the command run: a long command that names any of this is asked unread
|
|
82
|
+
const GATE_WORDS = new RegExp(`git|commit|${MAKES_COMMITS.join('|')}|gate\\.mjs`, 'i');
|
|
61
83
|
const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
62
84
|
|
|
63
85
|
// git aliases that run commit ([alias] ci = commit, cm = !git commit), from git config and from an inline -c alias.x=commit
|
|
@@ -184,20 +206,26 @@ function stop(reason) {
|
|
|
184
206
|
process.exit(2);
|
|
185
207
|
}
|
|
186
208
|
|
|
209
|
+
const internalError = (e) => t(root, 'guard.commit.internalError', { error: String(e?.message ?? e).slice(0, 200) });
|
|
210
|
+
|
|
187
211
|
async function hook() {
|
|
188
|
-
let
|
|
212
|
+
let raw = '', dir = root;
|
|
189
213
|
try {
|
|
190
214
|
const g = parseInput(JSON.parse(fs.readFileSync(0, 'utf8')) ?? {});
|
|
191
215
|
tool = g.tool;
|
|
192
|
-
|
|
193
|
-
// text rules may also need it as a space ("git commit\<newline>-m x"). Whichever spelling is a commit is checked.
|
|
194
|
-
const raw = String(g.command ?? '');
|
|
195
|
-
const joined = raw.replace(/\\\r?\n/g, '');
|
|
196
|
-
command = [joined, unquote(joined)].some((c) => commitPattern(joined).test(c)) ? joined : raw.replace(/\\\r?\n/g, ' ');
|
|
216
|
+
raw = String(g.command ?? '');
|
|
197
217
|
if (g.dir) dir = g.dir;
|
|
198
218
|
} catch {
|
|
199
219
|
process.exit(0);
|
|
200
220
|
}
|
|
221
|
+
if (raw.length > MAX_COMMAND) {
|
|
222
|
+
if ([raw, unquote(raw)].some((c) => GATE_WORDS.test(c))) decideOut('ask', t(root, 'guard.commit.tooLong'));
|
|
223
|
+
process.exit(0);
|
|
224
|
+
}
|
|
225
|
+
// A backslash-newline is a line continuation: bash joins the words ("git comm\<newline>it" is git commit), the
|
|
226
|
+
// text rules may also need it as a space ("git commit\<newline>-m x"). Whichever spelling is a commit is checked.
|
|
227
|
+
const joined = raw.replace(/\\\r?\n/g, '');
|
|
228
|
+
const command = [joined, unquote(joined)].some((c) => commitPattern(joined).test(c)) ? joined : raw.replace(/\\\r?\n/g, ' ');
|
|
201
229
|
// --skip bypasses the gate and the board: the user is asked in every spelling (the AI must not write it on its own)
|
|
202
230
|
// A commit whose message names --skip goes on to the commit checks below (a real --skip chained to a commit is stopped there).
|
|
203
231
|
const open = unquote(command);
|
|
@@ -219,6 +247,8 @@ async function hook() {
|
|
|
219
247
|
const note = unknown.length ? `\n${t(root, 'guard.commit.gateUnknownKeys', { keys: unknown.join(', ') })}` : '';
|
|
220
248
|
decideOut('ask', t(root, 'guard.commit.gateApprovalAsk', { list }) + note);
|
|
221
249
|
}
|
|
250
|
+
// A plain commit stays with the commit checks below: what its message names is text
|
|
251
|
+
if (!commit.test(command) && [command, open].some(makesOtherCommit) && hasBoard() && !boardReviewOff()) decideOut('ask', t(root, 'guard.commit.otherCommitAsk'));
|
|
222
252
|
if (!commit.test(command) && !commit.test(open)) process.exit(0);
|
|
223
253
|
if (!hasBoard() || boardReviewOff()) process.exit(0);
|
|
224
254
|
const chain = chainIssue(command, commit.inline ? COMMIT : commit);
|
|
@@ -230,8 +260,8 @@ async function hook() {
|
|
|
230
260
|
let d;
|
|
231
261
|
try {
|
|
232
262
|
d = changes();
|
|
233
|
-
} catch {
|
|
234
|
-
|
|
263
|
+
} catch (e) {
|
|
264
|
+
decideOut('ask', internalError(e)); // git failed or there is no repo: unread changes must not pass as reviewed
|
|
235
265
|
}
|
|
236
266
|
if (!d.files.length || docsOnly(d.files)) process.exit(0);
|
|
237
267
|
|
|
@@ -286,5 +316,5 @@ if (isMain(import.meta.url)) {
|
|
|
286
316
|
if (i > -1) approve(process.argv[i + 1] || 'unspecified');
|
|
287
317
|
else if (j > -1) save(`skipped: ${process.argv[j + 1] || 'user request'}`);
|
|
288
318
|
else if (process.argv.includes('--status')) status();
|
|
289
|
-
else hook();
|
|
319
|
+
else hook().catch((e) => decideOut('ask', internalError(e))); // a crash exits 1, which does not block the commit
|
|
290
320
|
}
|
|
@@ -378,6 +378,9 @@ export const MESSAGES = {
|
|
|
378
378
|
'dashboardData.prodRefAction': { en: '.mcp.json → dev ref (docs/operations/accounts.md → Environments)' },
|
|
379
379
|
'dashboardData.rlsMissing': { en: 'Supabase is in use but there is no RLS attacker test (tests/security/rls.mjs).' },
|
|
380
380
|
'dashboardData.rlsAction': { en: 'Get the template with /kit-update, add the tables to TABLES' },
|
|
381
|
+
'guard.commit.otherCommitAsk': { en: 'Commit gate: this command can make a commit the board review and the deterministic gate cannot check (merge, revert, cherry-pick, am, rebase, commit-tree, fast-import, or git called through a variable). Approve only if the user asked for it.' },
|
|
382
|
+
'guard.commit.internalError': { en: 'The commit gate could not check this command ({error}). User approval required.' },
|
|
383
|
+
'guard.commit.tooLong': { en: 'Commit gate: this command is too long to check and it names git or a commit. Approve only if the user asked for it.' },
|
|
381
384
|
'guard.commit.skipAsk': { en: 'Commit gate: --skip bypasses the board review and the deterministic gate. Approve only if the user explicitly asks.' },
|
|
382
385
|
'guard.commit.noCommands': { en: '(no commands defined)' },
|
|
383
386
|
'guard.commit.gateApprovalAsk': { en: 'Gate command approval: from now on the gate runs these commands from AGENTS.md → Commands every time:\n{list}\nApprove only if you trust them.' },
|
package/.claude/i18n/tr.json
CHANGED
|
@@ -375,6 +375,9 @@
|
|
|
375
375
|
"dashboardData.prodRefAction": ".mcp.json → dev ref (docs/operations/accounts.md → Environments)",
|
|
376
376
|
"dashboardData.rlsMissing": "Supabase kullanılıyor ama RLS saldırgan testi yok (tests/security/rls.mjs).",
|
|
377
377
|
"dashboardData.rlsAction": "/kit-update ile şablonu al, tabloları TABLES'a ekle",
|
|
378
|
+
"guard.commit.otherCommitAsk": "Commit kapısı: bu komut, kurul denetiminin ve deterministik kapının denetleyemeyeceği bir commit yapabilir (merge, revert, cherry-pick, am, rebase, commit-tree, fast-import veya değişkenle çağrılan git). Sadece kullanıcı istediyse onayla.",
|
|
379
|
+
"guard.commit.internalError": "Commit kapısı bu komutu denetleyemedi ({error}). Kullanıcı onayı gerekli.",
|
|
380
|
+
"guard.commit.tooLong": "Commit kapısı: bu komut denetlenemeyecek kadar uzun ve git veya commit geçiyor. Sadece kullanıcı istediyse onayla.",
|
|
378
381
|
"guard.commit.skipAsk": "Commit kapısı: --skip kurul denetimini ve deterministik kapıyı aşar. Sadece kullanıcı açıkça isterse onayla.",
|
|
379
382
|
"guard.commit.noCommands": "(tanımlı komut yok)",
|
|
380
383
|
"guard.commit.gateApprovalAsk": "Kapı komut onayı: AGENTS.md → Commands bölümündeki şu komutlar bundan sonra her kapıda çalışır:\n{list}\nGüvendiğin komutlarsa onayla.",
|
package/.claude/settings.json
CHANGED
package/AGENTS.md
CHANGED
|
@@ -21,9 +21,15 @@ This file holds the shared rules of the project. Claude Code, Codex and Antigrav
|
|
|
21
21
|
|
|
22
22
|
```
|
|
23
23
|
── Status ──────────────────────
|
|
24
|
-
Phase: …
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
Phase: …
|
|
25
|
+
Task: … (x/y)
|
|
26
|
+
Question mode: …
|
|
27
|
+
Limit: 5h %… weekly %…
|
|
28
|
+
Done: …
|
|
29
|
+
Board: …
|
|
30
|
+
Auto decisions: …
|
|
31
|
+
Next: …
|
|
32
|
+
Pending decision: …
|
|
27
33
|
```
|
|
28
34
|
|
|
29
35
|
9. **Know the user.** Follow the "Personal preferences" that arrive at session start (project rules come first). If the user corrects a behavior or says how they want to work (conversation, question frequency, report format, code style, things to avoid), note it briefly; do not break the flow. At the end of a task (`/build`) and at the end of a session (`/wrap-up`), ask about the notes with AskUserQuestion as a multi-select ("Save as a preference?"). Write the selected ones with `node .claude/hooks/prefs.mjs --add <conversation|questions|reports|code|avoid> "<preference>"`. Do not write without approval. Do not write secrets, personal data or the project name. A project-specific rule goes to "Learned rules", not to this file.
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
8
|
<p align="center">
|
|
9
|
-
<a href="kit/CHANGELOG.md"><img alt="Version" src="https://img.shields.io/badge/version-3.
|
|
9
|
+
<a href="kit/CHANGELOG.md"><img alt="Version" src="https://img.shields.io/badge/version-3.51.0-2a78d6?style=flat-square"></a>
|
|
10
10
|
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-2a78d6?style=flat-square"></a>
|
|
11
11
|
<img alt="Claude Code" src="https://img.shields.io/badge/Claude%20Code-ready-d97757?style=flat-square">
|
|
12
12
|
<img alt="Also Codex and Antigravity" src="https://img.shields.io/badge/also-Codex%20%C2%B7%20Antigravity-5b6577?style=flat-square">
|
|
@@ -242,7 +242,7 @@ A new file outside the map is asked about, clutter like `*.bak` and `*-old.*` is
|
|
|
242
242
|
| Test separation | Only the `test-writer` agent writes test files; the main session and the coding agent are blocked |
|
|
243
243
|
| Test guard | Asks before a test is deleted, skipped or weakened |
|
|
244
244
|
| Deterministic gate | No commit until lint, type check, tests and Semgrep have run; catches machine-specific paths written into code |
|
|
245
|
-
| Commit gate | No commit without a board review and a green gate; a test file changed by a patch or a script stops it too |
|
|
245
|
+
| Commit gate | No commit without a board review and a green gate; a test file changed by a patch or a script stops it too; merge, revert and other commands that make commits are asked |
|
|
246
246
|
| Edit lock | With `/freeze <folder>` on, the AI writes only inside that folder |
|
|
247
247
|
| Scope shield | Asks before writing to a file outside the approved plan |
|
|
248
248
|
| Config approval | Rule and guard files never change without your approval |
|
package/README.tr.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
8
|
<p align="center">
|
|
9
|
-
<a href="kit/CHANGELOG.md"><img alt="Sürüm" src="https://img.shields.io/badge/s%C3%BCr%C3%BCm-3.
|
|
9
|
+
<a href="kit/CHANGELOG.md"><img alt="Sürüm" src="https://img.shields.io/badge/s%C3%BCr%C3%BCm-3.51.0-2a78d6?style=flat-square"></a>
|
|
10
10
|
<a href="LICENSE"><img alt="Lisans: MIT" src="https://img.shields.io/badge/lisans-MIT-2a78d6?style=flat-square"></a>
|
|
11
11
|
<img alt="Claude Code" src="https://img.shields.io/badge/Claude%20Code-haz%C4%B1r-d97757?style=flat-square">
|
|
12
12
|
<img alt="Codex ve Antigravity" src="https://img.shields.io/badge/ayr%C4%B1ca-Codex%20%C2%B7%20Antigravity-5b6577?style=flat-square">
|
|
@@ -242,7 +242,7 @@ Harita dışı yeni dosya sorulur, `*.bak` ve `*-old.*` gibi dağınıklık dosy
|
|
|
242
242
|
| Test ayrımı | Test dosyasına yalnız `test-writer` ajanı yazar; ana oturum ve kod ajanı denerse engellenir |
|
|
243
243
|
| Test koruması | Silinen, atlanan veya gevşetilen testi sorar |
|
|
244
244
|
| Deterministik kapı | Lint, tip, test ve Semgrep çalışmadan commit açılmaz; koda yazılmış makineye özel yolu yakalar |
|
|
245
|
-
| Commit kapısı | Kurul denetimi ve yeşil kapı olmadan commit atılmaz; patch veya betikle değişen test dosyası da durur |
|
|
245
|
+
| Commit kapısı | Kurul denetimi ve yeşil kapı olmadan commit atılmaz; patch veya betikle değişen test dosyası da durur; merge, revert gibi commit üreten komutlar sorulur |
|
|
246
246
|
| Düzenleme kilidi | `/freeze <klasör>` açıkken AI sadece o klasöre yazar |
|
|
247
247
|
| Kapsam kalkanı | Onaylı planın dışındaki dosyaya yazım sorulur |
|
|
248
248
|
| Yapılandırma onayı | Kural ve koruma dosyaları onayın olmadan değişmez |
|
|
@@ -80,14 +80,19 @@ Every `design` decision is asked with visuals. The user chooses an image, not te
|
|
|
80
80
|
|
|
81
81
|
## 6. Status block (at the end of every answer)
|
|
82
82
|
|
|
83
|
-
In short, compressed language (caveman),
|
|
83
|
+
In short, compressed language (caveman), one item per line:
|
|
84
84
|
|
|
85
85
|
```
|
|
86
86
|
── Status ─────────────────────────────
|
|
87
|
-
Phase: Phase 1
|
|
88
|
-
|
|
87
|
+
Phase: Phase 1
|
|
88
|
+
Task: G-012 (7/23)
|
|
89
|
+
Question mode: open
|
|
90
|
+
Limit: 5h %34 weekly %5
|
|
91
|
+
Done: signup form + validation, tests green
|
|
92
|
+
Board: APPROVE (ux, qa)
|
|
89
93
|
Auto decisions: none
|
|
90
|
-
Next: G-013 password reset
|
|
94
|
+
Next: G-013 password reset
|
|
95
|
+
Pending decision: email service
|
|
91
96
|
```
|
|
92
97
|
|
|
93
98
|
- Phase and task come from `docs/workflow/progress.md`; the task count is checked/total in `docs/product/roadmap.md`.
|
package/kit/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
The kit version is in `kit/VERSION`. To update a project, run `/kit-update` in it.
|
|
4
4
|
Items with an "Adapt by hand" note concern files owned by the project; the update does not touch them.
|
|
5
5
|
|
|
6
|
+
## [3.51.0] - 2026-11-01
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
- **The status block has one item per line.** Phase, task, question mode, limit, done, board, auto decisions, next and pending decision each get their own line, so the block reads at a glance.
|
|
10
|
+
- **Commits and pull requests carry no AI attribution by default.** `.claude/settings.json` turns off the co-author line and the session link. This applies to Claude Code; Codex has no reliable local setting for it.
|
|
11
|
+
|
|
12
|
+
## [3.50.1] - 2026-11-01
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- **The commit gate now asks about other commands that make commits.** `git merge`, `cherry-pick`, `revert`, `am`, `rebase`, `commit-tree` and `fast-import` are asked even on a clean tree, since a review cannot be bound to them. So is git called in a way the text cannot show (`$g commit`, `git $(echo commit)`, `git "$@"`). On Codex, which has no question, the command is blocked and the user runs it. A lone `--abort` or `--quit` is not asked. A quoted mention such as `grep "git merge"` is also asked.
|
|
16
|
+
- **An error inside the commit gate no longer lets a commit through.** When git fails, or the hook itself crashes, the command is asked instead of passing.
|
|
17
|
+
- **Long or repetitive commands can no longer time the commit gate out.** Text such as `git --a --a --a …` made matching exponentially slow, and a hook that times out lets the command run. Matching no longer backtracks that way, and a command over 10 000 characters that names git or a commit is asked without being read.
|
|
18
|
+
- **A global option's value no longer hides the subcommand.** `git -C "my dir" commit`, `git -c user.name="A B" commit`, `git --work-tree . commit` and `git --attr-source HEAD commit` used to pass as if they were not commits. `GIT commit` now counts as git too.
|
|
19
|
+
|
|
6
20
|
## [3.50.0] - 2026-10-30
|
|
7
21
|
|
|
8
22
|
### Added
|
package/kit/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.51.0
|
package/kit/guide.html
CHANGED
|
@@ -361,7 +361,7 @@ footer .container { display: flex; flex-wrap: wrap; gap: 16px; justify-content:
|
|
|
361
361
|
<section class="hero">
|
|
362
362
|
<div class="container">
|
|
363
363
|
<div>
|
|
364
|
-
<span class="pill"><b>v3.
|
|
364
|
+
<span class="pill"><b>v3.51.0</b> Starter kit for Claude Code · MIT</span>
|
|
365
365
|
<h1>The AI builds.<br><em>You steer.</em></h1>
|
|
366
366
|
<p class="sub">TillerHand takes a product from idea to production and maintenance with Claude Code. At every important decision the AI gives you the options, its recommendation and the cost of each option. An expert board reviews the work, and guardrails stop mistakes before they happen.</p>
|
|
367
367
|
<div class="setup">
|
|
@@ -512,9 +512,15 @@ an environment variable and add its name to .env.example with an empty value.
|
|
|
512
512
|
<div class="window">
|
|
513
513
|
<div class="bar"><i></i><i></i><i></i><span>At the end of every answer</span></div>
|
|
514
514
|
<pre class="term">── Status ──────────────────────
|
|
515
|
-
Phase: 1
|
|
516
|
-
|
|
517
|
-
|
|
515
|
+
Phase: 1
|
|
516
|
+
Task: G-012 (7/23)
|
|
517
|
+
Question mode: open
|
|
518
|
+
Limit: 5h 34% weekly 5%
|
|
519
|
+
Done: signup form + validation, tests green
|
|
520
|
+
Board: <span class="g">APPROVE</span> (ux, qa)
|
|
521
|
+
Auto decisions: none
|
|
522
|
+
Next: G-013 password reset
|
|
523
|
+
Pending decision: email service</pre>
|
|
518
524
|
</div>
|
|
519
525
|
<h3>You always know where you are</h3>
|
|
520
526
|
<p>Phase, task, limit, the board's verdict and the next step at the end of every answer. When you come back after a break, your place is ready.</p>
|
|
@@ -948,7 +954,7 @@ npx tillerhand init
|
|
|
948
954
|
<tr><td>Test separation</td><td>The tests are written before the code by a separate agent (<code>test-writer</code>, a different model is recommended), not by whoever writes the code. Nobody but this agent can write to a test file: the main session and the code agent are blocked if they try. A test file changed indirectly by a patch or script also stops at the commit gate. So whoever writes the code can't shape the test to fit their own code</td></tr>
|
|
949
955
|
<tr><td>Test protection</td><td>Deleting or commenting out an assertion, <code>.skip</code>/<code>.only</code>, a loosened assertion, deleting or moving a test file, and narrowing coverage in the test config are asked; so is writing to a test file through the shell</td></tr>
|
|
950
956
|
<tr><td>Deterministic gate</td><td><code>gate.mjs --run</code>: lint, type check, tests and Semgrep run; the output feeds the board, and a red check counts as REJECT. If the "must not change" behaviors in the spec have no test or the test is red, the gate is red. It is also red if an added line contains a path specific to this machine (the full path of the project folder or the home folder). A new or changed command is first shown to you for approval</td></tr>
|
|
951
|
-
<tr><td>Commit gate</td><td>No commit without a board review and a green gate for the same changes; the task-end approval also counts for the commit, so the same change is not reviewed twice; skipping the review (<code>--skip</code>)
|
|
957
|
+
<tr><td>Commit gate</td><td>No commit without a board review and a green gate for the same changes; the task-end approval also counts for the commit, so the same change is not reviewed twice; skipping the review (<code>--skip</code>) and commands that make commits with nothing to review (<code>git merge</code>, <code>git revert</code>…) are asked every time</td></tr>
|
|
952
958
|
<tr><td>Edit lock</td><td>While <code>/freeze <folder></code> is on, the AI writes only to that folder; writing outside through the shell is asked, and a symlink can't escape it</td></tr>
|
|
953
959
|
<tr><td>Scope shield</td><td>After <code>/plan-task</code> approval, the plan's file list is saved; writing to an existing file not on the list is asked. Turning the shield on and off is asked too</td></tr>
|
|
954
960
|
<tr><td>Edit round counter</td><td>When the same code file is edited for the 5th and 10th time in a session, a Semgrep and security review reminder appears</td></tr>
|
|
@@ -1017,9 +1023,15 @@ AGENTS.md · CLAUDE.md · README.md · CHANGELOG.md</pre>
|
|
|
1017
1023
|
<div>
|
|
1018
1024
|
<h3 style="margin-top:0">At the end of every answer: the status block</h3>
|
|
1019
1025
|
<pre class="term">── Status ──────────────────────
|
|
1020
|
-
Phase: 1
|
|
1021
|
-
|
|
1022
|
-
|
|
1026
|
+
Phase: 1
|
|
1027
|
+
Task: G-012 (7/23)
|
|
1028
|
+
Question mode: open
|
|
1029
|
+
Limit: 5h 34% weekly 5%
|
|
1030
|
+
Done: signup form + validation, tests green
|
|
1031
|
+
Board: APPROVE (ux, qa)
|
|
1032
|
+
Auto decisions: none
|
|
1033
|
+
Next: G-013 password reset
|
|
1034
|
+
Pending decision: email service</pre>
|
|
1023
1035
|
<h3>Always: the status line</h3>
|
|
1024
1036
|
<pre class="term">▶ Phase 1 · G-012 · task 7/23 · questions: open · 5h 34% · weekly 5% · context 42%</pre>
|
|
1025
1037
|
</div>
|
|
@@ -1242,7 +1254,7 @@ Next: G-013 password reset · pending decision: email service</pre>
|
|
|
1242
1254
|
<footer>
|
|
1243
1255
|
<div class="container">
|
|
1244
1256
|
<a class="brand" href="#top" style="font-size:16px"><svg class="mark" style="width:22px;height:22px"><use href="#mark"/></svg>TillerHand</a>
|
|
1245
|
-
<span>Version 3.
|
|
1257
|
+
<span>Version 3.51.0 · <a href="https://github.com/burakdogrul/TillerHand">GitHub</a> · <a href="https://github.com/burakdogrul/TillerHand/blob/main/LICENSE">MIT license</a> · The KVKK section is a checklist, not legal advice.</span>
|
|
1246
1258
|
</div>
|
|
1247
1259
|
</footer>
|
|
1248
1260
|
|
package/kit/guide.tr.html
CHANGED
|
@@ -361,7 +361,7 @@ footer .container { display: flex; flex-wrap: wrap; gap: 16px; justify-content:
|
|
|
361
361
|
<section class="hero">
|
|
362
362
|
<div class="container">
|
|
363
363
|
<div>
|
|
364
|
-
<span class="pill"><b>v3.
|
|
364
|
+
<span class="pill"><b>v3.51.0</b> Claude Code için başlangıç kiti · MIT</span>
|
|
365
365
|
<h1>Kodu AI yazar.<br><em>Dümen sende.</em></h1>
|
|
366
366
|
<p class="sub">TillerHand, Claude Code ile bir ürünü fikirden canlıya ve bakıma kadar götürür. Her önemli kararda AI sana seçenekleri, önerisini ve her seçeneğin bedelini sunar. Bir uzman kurulu işi denetler, korumalar hatayı daha olmadan durdurur.</p>
|
|
367
367
|
<div class="setup">
|
|
@@ -512,10 +512,13 @@ ve adını .env.example'a boş değerle ekle.
|
|
|
512
512
|
<div class="window">
|
|
513
513
|
<div class="bar"><i></i><i></i><i></i><span>Her cevabın sonunda</span></div>
|
|
514
514
|
<pre class="term">── Durum ─────────────────────────────
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
515
|
+
Faz: 1
|
|
516
|
+
Görev: G-012 (7/23)
|
|
517
|
+
Soru modu: açık
|
|
518
|
+
Limit: 5s %34 hf %5
|
|
519
|
+
Biten: kayıt formu + doğrulama, test yeşil
|
|
518
520
|
Kurul: <span class="g">APPROVE</span> (ux, qa)
|
|
521
|
+
Otomatik karar: yok
|
|
519
522
|
Sıradaki: G-013 şifre sıfırlama
|
|
520
523
|
Bekleyen karar: e-posta servisi</pre>
|
|
521
524
|
</div>
|
|
@@ -951,7 +954,7 @@ npx tillerhand init
|
|
|
951
954
|
<tr><td>Test ayrımı</td><td>Testleri kodu yazan değil, ayrı bir ajan (<code>test-writer</code>, farklı model önerilir) koddan önce yazar. Test dosyasına bu ajan dışında kimse yazamaz: ana oturum ve kod ajanı denerse engellenir. Patch veya betikle dolaylı değişen test dosyası da commit kapısında durur. Böylece kodu yazan testi kendi koduna göre şekillendiremez</td></tr>
|
|
952
955
|
<tr><td>Test koruması</td><td>Beklenti silmek veya yoruma almak, <code>.skip</code>/<code>.only</code>, gevşek beklenti, test dosyasını silmek veya taşımak ve test ayarında kapsamı daraltmak sorulur; kabukla test dosyasına yazmak da</td></tr>
|
|
953
956
|
<tr><td>Deterministik kapı</td><td><code>gate.mjs --run</code>: lint, tip kontrolü, test ve Semgrep çalışır; çıktı kurula girdi olur, kırmızı kontrol REJECT sayılır. Spec'teki "değişmemesi gereken" davranışların testi yoksa veya kırmızıysa kapı kırmızıdır. Eklenen bir satırda bu makineye özel bir yol (proje klasörünün ya da ev klasörünün tam yolu) varsa da kırmızıdır. Yeni veya değişen komut önce sana gösterilip onaylatılır</td></tr>
|
|
954
|
-
<tr><td>Commit kapısı</td><td>Kurul denetimi ve aynı değişiklikler için yeşil kapı olmadan commit atılmaz; görev sonu onayı commit için de geçerli, aynı değişiklik iki kez denetlenmez; denetimi atlamak (<code>--skip</code>) her seferinde sorulur</td></tr>
|
|
957
|
+
<tr><td>Commit kapısı</td><td>Kurul denetimi ve aynı değişiklikler için yeşil kapı olmadan commit atılmaz; görev sonu onayı commit için de geçerli, aynı değişiklik iki kez denetlenmez; denetimi atlamak (<code>--skip</code>) ve denetlenecek değişiklik olmadan commit üreten komutlar (<code>git merge</code>, <code>git revert</code>…) her seferinde sorulur</td></tr>
|
|
955
958
|
<tr><td>Düzenleme kilidi</td><td><code>/freeze <klasör></code> açıkken AI sadece o klasöre yazar; kabukla dışarı yazmak sorulur, sembolik bağdan kaçılamaz</td></tr>
|
|
956
959
|
<tr><td>Kapsam kalkanı</td><td><code>/plan-task</code> onayından sonra planın dosya listesi kaydedilir; listede olmayan mevcut dosyaya yazım sorulur. Kalkanı açmak ve kapatmak da sorulur</td></tr>
|
|
957
960
|
<tr><td>Düzenleme turu sayacı</td><td>Aynı kod dosyası bir oturumda 5., 10. kez düzenlenince Semgrep ve güvenlik incelemesi hatırlatılır</td></tr>
|
|
@@ -1020,10 +1023,15 @@ AGENTS.md · CLAUDE.md · README.md · CHANGELOG.md</pre>
|
|
|
1020
1023
|
<div>
|
|
1021
1024
|
<h3 style="margin-top:0">Her cevabın sonunda: durum bloğu</h3>
|
|
1022
1025
|
<pre class="term">── Durum ─────────────────────────────
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1026
|
+
Faz: 1
|
|
1027
|
+
Görev: G-012 (7/23)
|
|
1028
|
+
Soru modu: açık
|
|
1029
|
+
Limit: 5s %34 hf %5
|
|
1030
|
+
Biten: kayıt formu + doğrulama, test yeşil
|
|
1031
|
+
Kurul: APPROVE (ux, qa)
|
|
1032
|
+
Otomatik karar: yok
|
|
1033
|
+
Sıradaki: G-013 şifre sıfırlama
|
|
1034
|
+
Bekleyen karar: e-posta servisi</pre>
|
|
1027
1035
|
<h3>Her zaman: alt durum çubuğu</h3>
|
|
1028
1036
|
<pre class="term">▶ Faz 1 · G-012 · görev 7/23 · soru: açık · 5s %34 · hf %5 · bağlam %42</pre>
|
|
1029
1037
|
</div>
|
|
@@ -1246,7 +1254,7 @@ Sıradaki: G-013 şifre sıfırlama · bekleyen karar: e-posta servisi</pre>
|
|
|
1246
1254
|
<footer>
|
|
1247
1255
|
<div class="container">
|
|
1248
1256
|
<a class="brand" href="#top" style="font-size:16px"><svg class="mark" style="width:22px;height:22px"><use href="#mark"/></svg>TillerHand</a>
|
|
1249
|
-
<span>Sürüm 3.
|
|
1257
|
+
<span>Sürüm 3.51.0 · <a href="https://github.com/burakdogrul/TillerHand">GitHub</a> · <a href="https://github.com/burakdogrul/TillerHand/blob/main/LICENSE">MIT lisansı</a> · KVKK bölümü kontrol listesidir, hukuki görüş değildir.</span>
|
|
1250
1258
|
</div>
|
|
1251
1259
|
</footer>
|
|
1252
1260
|
|