22 Commits
Author SHA1 Message Date
christian 14a5774d32 Merge pull request 'Fix duplicate ids, validate CLI input, harden load/save' (#2) from fix/review-findings into main
Reviewed-on: #2
2026-10-21 00:58:54 +02:00
christian 696049b3b1 Merge pull request 'Document branch-and-PR workflow; never write to main' (#1) from docs/branch-pr-workflow into main
Reviewed-on: #1
2026-10-21 00:58:40 +02:00
christian 2088568b5e Merge pull request 'Protect main: git hooks + Claude Code deny rules' (#3) from chore/deny-push-main into main
Reviewed-on: #3
2026-10-21 00:58:30 +02:00
christianandClaude Opus 5.5 f666bdf6b3 Give the PR workflow a hard stop
Only confirmed correctness bugs block approval; everything else is a note.
At most one fix round, then hand off. Don't widen scope to satisfy a
review. Merge main only on conflict or request. The token goes in a
private header file, and PR responses are checked for a number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:56:51 +02:00
christianandClaude Opus 5.5 130ffe0d13 Drop the lock file: too much machinery for a personal CLI
Concurrent runs of the CLI can again lose an update; saves stay atomic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:56:16 +02:00
christianandClaude Opus 5.5 480ed6a8b2 Install hooks into the repo's own hooks dir, ignoring core.hooksPath
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:55:32 +02:00
christianandClaude Opus 5.5 ed197eeeb1 Address review round 3: safe API snippets, PR opened once, pinned review
- Titles and bodies go through --rawfile files, never inline shell quotes
- pipefail + curl -f + jq -e so a failed call can't look successful
- Fix rounds merge latest main and skip re-opening the PR
- Check the branch isn't main before pushing; never bypass the hooks
- Review at a pinned level; only correctness findings checked against the
  code block approval

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:50:38 +02:00
christianandClaude Opus 5.5 dab492da1e Lock during updates, repair duplicate ids, keep file identity on save
- CLI holds a lock file from load to save, so concurrent commands can't
  lose an update; stale locks from crashed runs are taken over
- load() renumbers duplicate ids from the old add() bug instead of
  refusing the file
- save() keeps owner, group and setgid on the temp file, and falls back to
  an in-place write for hard-linked files, files whose owner/group can't
  be kept, and directories that aren't writable

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:49:47 +02:00
christianandClaude Opus 5.5 24541f0602 Install hooks by copying into .git/hooks instead of core.hooksPath
Linking core.hooksPath to the tracked, sandbox-writable .githooks/ let a
sandboxed command rewrite a hook that git commit/push then run unsandboxed.
Copies in .git/hooks can't be changed from the sandbox. This also keeps
existing .git/hooks scripts working and lets npm install succeed outside a
git checkout. pre-merge-commit now names itself in errors; hook tests clean
up, ignore GIT_* env and cover the installer; docs state what each layer
does and doesn't stop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:44:30 +02:00
christianandClaude Opus 5.5 f09d20cb84 Address review round 3: id limit, private temp files, canonical ids
- add() refuses to create an id that load() would reject; the CLI reports it
- save() creates the temp file with the real file's mode (and O_EXCL), so a
  private list is never briefly world-readable; one stat call; symlink
  resolution inlined; comment states the rename trade-offs
- CLI rejects ids with leading zeros and id 0
- Tests for trimming, the bare 'todo' default, and the id limit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:41:37 +02:00
christianandClaude Opus 5.5 8b08c7b27a Block pushes and commits to main with git hooks
pre-push rejects any push that would update refs/heads/main, however the
command is spelled; pre-commit and pre-merge-commit refuse commits while
main is checked out. npm install enables them via core.hooksPath. The
README documents the three layers of protection for main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:39:56 +02:00
christianandClaude Opus 5.5 089fc94e16 Address review round 2: duplicate ids, read-only files, dangling links, safe ids
- load() rejects duplicate ids (left by the old add bug) and ids that aren't safe positive integers
- save() refuses files the user can't write, and follows dangling symlinks to their target
- CLI rejects ids beyond Number.MAX_SAFE_INTEGER
- Skip permission-based tests when running as root

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:33:46 +02:00
christianandClaude Opus 5.5 fa45c58c0c Address review round 2: no-track branches, honest enforcement, safer API calls
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:32:15 +02:00
christianandClaude Opus 5.5 183e44db62 Deny Claude Code pushes to main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:30:36 +02:00
christianandClaude Opus 5.5 8dc5194438 Address review: safer save, stricter load and id parsing
- save() follows symlinks, keeps permissions, uses a unique temp file and cleans it up on failure
- load() rejects entries that aren't {id, text, done}
- add() finds the max id with reduce (no spread limit)
- CLI accepts only plain digits as ids and reports save errors readably
- Ignore *.tmp

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:26:22 +02:00
christianandClaude Opus 5.5 962c1aa9a1 Address review: fresh base, named review target, round cap, Gitea API
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:22:48 +02:00
christianandClaude Opus 5.5 ba17376132 Fix duplicate ids, validate CLI input, harden load/save
- add() uses max id + 1 so ids are never reused after rm
- done/rm reject missing, non-numeric and unknown ids; add rejects empty text
- load() gives a readable error on bad JSON or non-list data
- save() writes a temp file and renames it
- CLI checks the command before loading and no longer relies on process.exit for ls
- Add regression tests for all of the above

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:13:51 +02:00
christianandClaude Opus 5.5 82ba704957 Document branch-and-PR workflow; never write to main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:12:37 +02:00
christianandClaude Opus 5.5 f0ba80a7bd Drop ineffective ~/.config/git read exception
Project settings can't re-open a path denied by another settings source,
so this lives in user settings instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:07:59 +02:00
christianandClaude Opus 5.5 e5e43efafa Let git ls-remote reach Gitea from the sandbox
Run git ls-remote unsandboxed so SSH works, and ask before each use like
the other network git commands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:06:42 +02:00
christianandClaude Opus 5.5 371a6af0b4 Sandbox Claude Code to the project folder
Enable the Bash sandbox with writes limited to the project, block reads
of credential and personal folders, and protect the settings files from
edits. git commit/push/fetch/pull run unsandboxed so GPG and SSH work;
network git commands always ask first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:02:02 +02:00
christianandClaude Opus 5.5 3cec32b9e6 Initial commit: demo todo CLI with Claude Code setup
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 23:49:20 +02:00