Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .githooks/lib/check-ascii.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env sh
# Reject non-ASCII bytes (em dash, accented letters, smart quotes) in added
# lines. Reads "path:line:content". Stricter superset of check-english.sh.
set -eu
status=0

while IFS= read -r entry; do
path=${entry%%:*}
case "$path" in
*.png|*.jpg|*.jpeg|*.gif|*.ico|*.svg|*.woff|*.woff2|*.ttf) continue ;;
package-lock.json|*.lock) continue ;;
esac
rest=${entry#*:}; content=${rest#*:}
if printf '%s' "$content" | LC_ALL=C grep -q '[^[:print:][:space:]]'; then
echo "Non-ASCII character: ${path}:${rest%%:*}"
status=1
fi
done

exit $status
1 change: 1 addition & 0 deletions .githooks/lib/run-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ sh "$lib/check-env-files.sh" "$@" || status=1
sh "$lib/check-ai-attribution.sh" < "$added" || status=1
sh "$lib/check-secrets.sh" < "$added" || status=1
sh "$lib/check-english.sh" < "$added" || status=1
sh "$lib/check-ascii.sh" < "$added" || status=1
sh "$lib/check-forbidden-patterns.sh" < "$added" || status=1

exit $status
14 changes: 13 additions & 1 deletion .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#!/usr/bin/env sh
# Local gate: type-check before push to catch errors earlier than CI.
# Local gate before push: catch what CI would reject, earlier.
set -eu

root="$(git rev-parse --show-toplevel)"
lib="$root/.githooks/lib"

echo "[pre-push] type-check"
npx tsc --noEmit

echo "[pre-push] ascii-only (added lines vs origin/main)"
base="$(git merge-base origin/main HEAD 2>/dev/null || git rev-parse HEAD)"
sh "$lib/added-lines.sh" range "$base" | sh "$lib/check-ascii.sh" || {
echo ""
echo "Push blocked: non-ASCII characters in added lines (em dash, accents)."
echo "CI compliance rejects these. Do not bypass with --no-verify."
exit 1
}
27 changes: 21 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,41 @@ Rules for AI assistants (Claude Code, Codex, Cursor, etc.) contributing to this
- No comments unless the WHY is non-obvious (hidden constraint, workaround for a specific bug, surprising invariant).
- No multi-line docstrings or comment blocks.
- No error handling for impossible cases. Trust framework guarantees. Validate only at system boundaries (user input, external APIs).
- No unused variables prefixed with `_` to silence linters — remove the variable.
- No unused variables prefixed with `_` to silence linters, remove the variable.
- ASCII only in source and docs. No em dash, no accented or other non-ASCII characters (CI compliance blocks them).

## Security

- Never hardcode secrets, tokens, API keys, or credentials.
- Never log sensitive data (passwords, tokens, PII).
- If a vulnerability is introduced (XSS, SQL injection, command injection, etc.), fix it immediately before proceeding.
- If a pre-existing vulnerability is found in adjacent code (not introduced by the current change), do not touch it emit a loud warning to the user in the chat (bold, clearly marked as a security issue) and continue with the requested scope.
- If a pre-existing vulnerability is found in adjacent code (not introduced by the current change), do not touch it, emit a loud warning to the user in the chat (bold, clearly marked as a security issue) and continue with the requested scope.

## Commits

Follow [Conventional Commits](https://www.conventionalcommits.org/) same rules as in [CONTRIBUTING.md](CONTRIBUTING.md).
Follow [Conventional Commits](https://www.conventionalcommits.org/), same rules as in [CONTRIBUTING.md](CONTRIBUTING.md).

- Subject 50 characters.
- Subject 50 characters or fewer.
- No `Co-Authored-By` lines.
- Body only when the "why" is not obvious from the diff.
- The **PR title** is the gate validated by CI (squash merge uses it), so it must be a valid Conventional Commit, not just the individual commits.

## Dependencies

- Do not add a dependency without a clear need; prefer existing ones.
- New dependencies must not introduce high or critical advisories (`npm audit --audit-level=high` blocks CI).

## Before proposing changes

- Verify TypeScript types pass (`npm run typecheck` if available).
- Respect the existing Prettier config — do not reformat unrelated lines.
Run the same gates CI enforces, in this order:

- Lint with zero warnings: `npm run lint -- --max-warnings 0`.
- Type check: `npx tsc --noEmit`.
- Validate the Prisma schema when `prisma/` changes: `npx prisma validate`.
- Confirm the build passes without real secrets: `npm run build`.

Also:

- Respect the existing Prettier config, do not reformat unrelated lines.
- Do not push to remote unless explicitly asked.
- Do not open, close, or comment on issues or pull requests unless explicitly asked.