diff --git a/.claude/commands/commit-user.md b/.claude/commands/commit-user.md deleted file mode 100644 index ed549ba..0000000 --- a/.claude/commands/commit-user.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -allowed-tools: Bash(git add:*), Bash(git status:*), Bash(git log:*), Bash(git diff:*), Bash(git branch:*) -description: Draft a git commit message (interactive — does NOT commit) ---- - -# Commit (Interactive) - -Draft a commit message following `docs/references/commit-message-guide.md`. Do NOT commit — show the message and the terminal command only. - -## Steps - -1. Run in parallel: - - `git status` - - `git diff HEAD` - - `git branch --show-current` - - `git log --oneline -10` (style reference — only match commits from Stanislav Jakuschevskij) -2. Analyze the diff and draft a message following all seven rules -3. New features and fixes take priority over refactoring for the commit type -4. Use tandem authorship (Co-Authored-By trailer) -5. If $ARGUMENTS is provided, add "Issue $ARGUMENTS" at the bottom -6. Show the message and the `git commit` command — do NOT execute it diff --git a/.claude/commands/session-commit.md b/.claude/commands/session-commit.md index 1e3a476..c34fe04 100644 --- a/.claude/commands/session-commit.md +++ b/.claude/commands/session-commit.md @@ -1,48 +1,31 @@ --- -allowed-tools: Bash(git *), Read, Edit, Write -description: Stage changes, update progress log, and commit (end-of-session) +allowed-tools: Bash(git *) +description: Stage changes and commit (end-of-session) --- # Session Commit -Automate end-of-session cleanup: stage, log progress, commit. +Automate end-of-session cleanup: stage and commit. ## Steps -1. **Assess changes** — run these in parallel: +1. **Assess changes** -- run these in parallel: - `git status` - `git diff HEAD` - `git branch --show-current` - `git log --oneline -10` -2. **Stage everything** — if there are unstaged or untracked changes: +2. **Stage everything** -- if there are unstaged or untracked changes: - Use `git add ` (not `git add .`) - Never stage files that likely contain secrets (.env, credentials, etc.) - Skip if everything is already staged -3. **Update progress log** — read `docs/claude-progress.txt`, then prepend a new entry at the top (after the header line) following the format in `docs/references/claude-progress-readme.md`. - - Analyze the staged diff to determine what was done - - Use today's actual date - - Be concise but complete - - Stage the updated file: `git add docs/claude-progress.txt` +3. **Draft and commit** -- follow all rules from `docs/references/commit-message-guide.md`: + - Subject: `: `, imperative mood + - Body is optional if the subject is descriptive enough, otherwise explain what and why + - No em dashes anywhere in the message -4. **Migrate blockers** — if the progress entry you just wrote has a `Blockers:` line that is NOT `None`: - - Read `docs/agent-struggles.json` - - For each blocker, append an entry: - - ```json - { - "date": "", - "description": "", - "cause": "", - "suggestion": "", - "resolved": false - } - ``` - - - Stage: `git add docs/agent-struggles.json` - -5. **Draft and commit** — follow all rules from `docs/references/commit-message-guide.md`. Determine authorship mode (tandem vs autonomous) from the guide. Use a HEREDOC: + Determine authorship mode (tandem vs autonomous) from the guide. Use a HEREDOC: ```bash git commit -m "$(cat <<'EOF' @@ -55,11 +38,11 @@ Automate end-of-session cleanup: stage, log progress, commit. )" ``` -6. **Verify** — run `git status` and `git log --oneline -1` to confirm success. +4. **Verify** -- run `git status` and `git log --oneline -1` to confirm success. If the commit fails due to the commit-msg hook, read the error output, fix the message, and create a NEW commit (never amend). ## Rules -- Analyze the FULL diff for accurate progress and commit message +- Analyze the FULL diff for an accurate commit message - Never commit secrets or sensitive files -- If commit fails due to pre-commit hook, fix and create a NEW commit (never amend) +- If commit fails due to pre-commit or commit-msg hook, fix and create a NEW commit (never amend) - Do NOT push to remote diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 0000000..5edb5ea --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,45 @@ +#!/usr/bin/env sh + +MSG_FILE="$1" + +# Strip comment lines +MSG=$(grep -v '^#' "$MSG_FILE") + +SUBJECT=$(echo "$MSG" | head -1) + +# Skip merge, fixup, and squash commits +case "$SUBJECT" in + Merge\ branch\ *|Merge\ remote-tracking\ *|Merge\ tag\ *) exit 0 ;; + fixup\!\ *|squash\!\ *) exit 0 ;; +esac + +ERRORS="" + +# 1. Conventional commit format +TYPES="feat|fix|refactor|docs|test|chore|style|perf|ci|build" +if ! echo "$SUBJECT" | grep -qE "^($TYPES): .+"; then + ERRORS="$ERRORS + Subject must match ': '. + Types: feat, fix, refactor, docs, test, chore, style, perf, ci, build" +fi + +# 2. Authorship trailer +if ! echo "$MSG" | grep -qE '^(Co-Authored-By|Signed-off-by): .+'; then + ERRORS="$ERRORS + Missing authorship trailer (Co-Authored-By or Signed-off-by)." +fi + +# 3. No em dashes +if echo "$MSG" | grep -q '—'; then + ERRORS="$ERRORS + Em dashes are not allowed. Use commas, periods, or parentheses." +fi + +if [ -n "$ERRORS" ]; then + echo "" + echo "commit-msg: FAILED" + echo "$ERRORS" + echo "" + echo "See docs/references/commit-message-guide.md for rules." + exit 1 +fi diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..2a67640 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,12 @@ +#!/usr/bin/env sh + +yarn lint +yarn type-check + +cd backend +go vet ./... +if [ -n "$(gofmt -l .)" ]; then + echo "Go files not formatted. Run: gofmt -w backend/" + gofmt -l . + exit 1 +fi diff --git a/package.json b/package.json index b2c5e3b..7e0a4c0 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "cypress-merge": "mochawesome-merge ./integration-tests/screenshots/cypress_report*.json > ./integration-tests/screenshots/cypress.json", "cypress-generate": "marge -o ./integration-tests/screenshots/ -f cypress-report -t 'OpenShift Console Plugin Template Cypress Test Results' -p 'OpenShift Cypress Plugin Template Test Results' --showPassed false --assetsDir ./integration-tests/screenshots/cypress/assets ./integration-tests/screenshots/cypress.json", "cypress-postreport": "yarn cypress-merge && yarn cypress-generate", + "type-check": "tsc --noEmit", + "prepare": "husky", "webpack": "node -r ts-node/register ./node_modules/.bin/webpack" }, "devDependencies": { @@ -55,6 +57,7 @@ "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^7.0.1", "globals": "^17.4.0", + "husky": "^9.1.7", "i18next": "^23.11.5", "i18next-parser": "^9.4.0", "jsdom": "^29.0.2", diff --git a/tsconfig.json b/tsconfig.json index b7353a8..07f8cf3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,7 @@ "strict": true, "allowSyntheticDefaultImports": true, "noUnusedLocals": true, + "skipLibCheck": true, "types": ["vitest/globals"] }, "include": ["src", "testing"], diff --git a/yarn.lock b/yarn.lock index f04ae07..176493a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5559,6 +5559,7 @@ __metadata: eslint-plugin-react: "npm:^7.37.5" eslint-plugin-react-hooks: "npm:^7.0.1" globals: "npm:^17.4.0" + husky: "npm:^9.1.7" i18next: "npm:^23.11.5" i18next-parser: "npm:^9.4.0" jsdom: "npm:^29.0.2" @@ -8987,6 +8988,15 @@ __metadata: languageName: node linkType: hard +"husky@npm:^9.1.7": + version: 9.1.7 + resolution: "husky@npm:9.1.7" + bin: + husky: bin.js + checksum: 10c0/35bb110a71086c48906aa7cd3ed4913fb913823715359d65e32e0b964cb1e255593b0ae8014a5005c66a68e6fa66c38dcfa8056dbbdfb8b0187c0ffe7ee3a58f + languageName: node + linkType: hard + "hyperdyperid@npm:^1.2.0": version: 1.2.0 resolution: "hyperdyperid@npm:1.2.0"