diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index db4d960..a127bdc 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -78,7 +78,7 @@ jobs: echo "TAG=v$VERSION" >> "$GITHUB_ENV" - name: Checkout PR branch - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ env.PR_BRANCH }} fetch-depth: 0 @@ -108,9 +108,16 @@ jobs: run: | git push origin HEAD:${{ env.PR_BRANCH }} - - name: Create git tag + - name: Merge PR + run: | + gh pr merge ${{ env.PR_NUMBER }} \ + --merge \ + --repo ${{ github.repository }} + + - name: Tag merge commit on main run: | - git tag "${{ env.TAG }}" + git fetch origin main + git tag "${{ env.TAG }}" origin/main git push origin "${{ env.TAG }}" - name: Create GitHub Release @@ -120,15 +127,9 @@ jobs: --generate-notes \ --repo ${{ github.repository }} - - name: Merge PR - run: | - gh pr merge ${{ env.PR_NUMBER }} \ - --merge \ - --repo ${{ github.repository }} - - name: Delete release branch run: | - git push origin --delete "${{ env.PR_BRANCH }}" + git push origin --delete "${{ env.PR_BRANCH }}" || true - name: Post success comment if: success() diff --git a/CLAUDE.md b/CLAUDE.md index 835039e..50fdefc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,5 +1,6 @@ @src/rules/skills-format.md @src/rules/git-workflow.md +@src/rules/jsx-style.md ## Using skills diff --git a/package.json b/package.json index a2ac293..da6f309 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@salve-software/ai-workers", - "version": "0.1.2", + "version": "0.2.0", "description": "Central package for AI configurations and Claude Code rules.", "scripts": { "postinstall": "bash scripts/setup.sh" diff --git a/src/commands/feature/SKILL.md b/src/commands/feature/SKILL.md index 60b76ae..585ebad 100644 --- a/src/commands/feature/SKILL.md +++ b/src/commands/feature/SKILL.md @@ -1,6 +1,7 @@ --- name: feature description: This skill should be used when the user asks to "build a feature", "implement a feature", "develop a feature", or wants to autonomously develop, review, and ship a complete feature following the PDCA cycle. +user-invocable: true argument-hint: allowed-tools: [Bash, Read, Glob, Grep, Agent] model: sonnet @@ -87,23 +88,13 @@ Your job is to implement a feature exactly as described in the plan below. ## Instructions -1. Follow the /branch command logic to create the branch (feat/, fix/, dev/) based on the feature type. +Read `src/rules/git-workflow.md` for branch naming rules. +Read `src/rules/conventional-commits.md` for commit types, format, and rules. + +1. Create the branch following the branch naming rules from `git-workflow.md`. 2. Implement each step from the plan sequentially. -3. After each logical implementation chunk, follow the /commit command logic to commit (Conventional Commits, imperative, max 72 chars). -4. Co-author line on every commit: Co-Authored-By: Claude Sonnet 4.6 -5. After all implementation is done, check if any test file was created or modified. If no test was touched, note it in your final report. - -## /branch logic -- feat/ — new feature -- fix/ — bug fix -- dev/ — project/umbrella branch -- release/ — release, always with vX.X.X -- Lowercase, kebab-case, 2–4 words - -## /commit logic -- Run git add (never git add . or git add -A) -- Commit with HEREDOC format including co-author -- Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, cleanup, remove +3. After each logical implementation chunk, commit following `conventional-commits.md`. Co-author line on every commit: Co-Authored-By: Claude Sonnet 4.6 +4. After all implementation is done, check if any test file was created or modified. If no test was touched, note it in your final report. Do not push. Do not open a PR. diff --git a/src/commands/land/SKILL.md b/src/commands/land/SKILL.md index afcfdbc..4991153 100644 --- a/src/commands/land/SKILL.md +++ b/src/commands/land/SKILL.md @@ -1,6 +1,7 @@ --- name: land description: Use when the user asks to create a branch and commit, or create a branch + commit + PR together. Orchestrates /branch and /commit while sharing the git diff context to avoid redundant reads. After committing, if the user also asked for a PR, invoke /pr. +user-invocable: true argument-hint: [optional: branch name or description] allowed-tools: [Bash, Read, Agent] --- diff --git a/src/commands/rn-component/SKILL.md b/src/commands/rn-component/SKILL.md new file mode 100644 index 0000000..11a1c8d --- /dev/null +++ b/src/commands/rn-component/SKILL.md @@ -0,0 +1,96 @@ +--- +name: rn-component +description: Scaffolds a React Native component using the Layered Hook Architecture (View / ViewModel / Styles / Animated / Services / Library). +user-invocable: true +argument-hint: --name [--path ] +allowed-tools: Bash, Read, Write +model: haiku +--- + +## Pre-flight — Parse arguments + +Extract `--name` and `--path` values from `$ARGUMENTS`. + +- If `--name` is missing: stop and print `⚠️ Missing --name. Usage: /rn-component --name MyButton --path src/components` +- If `--name` is not valid PascalCase (`^[A-Z][A-Za-z0-9]*$`): stop and print `⚠️ Invalid component name. Must be PascalCase (e.g. MyButton).` +- If `--path` is missing: ask the user `Where should the component be created? Provide the output directory path:` and wait for their answer before continuing. +- After `--path` is resolved (from arguments or from the user): if it contains spaces, stop and print `⚠️ Path must not contain spaces. Please provide a single-token path.` + +## Derive variables + +- `ComponentName` = value of `--name` (PascalCase) +- `componentName` = `ComponentName` with first letter lowercased (camelCase) +- `outputDir` = `/` — resolve `--path` to an absolute path if relative (use `pwd` to resolve) + +## Collision check + +Run via Bash: +```bash +if [ -d "" ]; then echo "EXISTS"; else echo "OK"; fi +``` + +If the result is `EXISTS`: stop and print `⚠️ already exists. Aborting to avoid overwrite.` + +## Architecture summary + +Read `references/architecture.md` (path relative to this SKILL.md file), then print a 3-line summary to the user: +- Layer overview (View / ViewModel / Styles / Animation / Services / Library) +- Type convention (I prefix for interfaces, barrel index.ts in every export folder) +- Barrel cycle rule (deep relative imports only, never ../..) + +## Create directory tree + +Run via Bash: +```bash +mkdir -p \ + /types \ + /hooks/useViewModel/types \ + /hooks/useReanimatedStyles/types \ + /services \ + /library +``` + +## Generate files + +For each template below: +1. Read the template file (path relative to this SKILL.md). +2. Replace every occurrence of `{{ComponentName}}` with the value of `ComponentName`. +3. Replace every occurrence of `{{componentName}}` with the value of `componentName`. +4. Write the result to the target path. + +| Template (relative to this file) | Target | +|-----------------------------------|--------| +| `references/templates/index.tsx.tmpl` | `/index.tsx` | +| `references/templates/styles.ts.tmpl` | `/styles.ts` | +| `references/templates/types/I{{ComponentName}}Props.ts.tmpl` | `/types/IProps.ts` | +| `references/templates/types/index.ts.tmpl` | `/types/index.ts` | +| `references/templates/hooks/index.ts.tmpl` | `/hooks/index.ts` | +| `references/templates/hooks/useComponentNameViewModel/index.ts.tmpl` | `/hooks/useViewModel/index.ts` | +| `references/templates/hooks/useComponentNameViewModel/types/IUseComponentNameViewModelReturn.ts.tmpl` | `/hooks/useViewModel/types/IUseViewModelReturn.ts` | +| `references/templates/hooks/useComponentNameViewModel/types/index.ts.tmpl` | `/hooks/useViewModel/types/index.ts` | +| `references/templates/hooks/useReanimatedStyles/index.ts.tmpl` | `/hooks/useReanimatedStyles/index.ts` | +| `references/templates/hooks/useReanimatedStyles/types/IUseReanimatedStylesProps.ts.tmpl` | `/hooks/useReanimatedStyles/types/IUseReanimatedStylesProps.ts` | +| `references/templates/hooks/useReanimatedStyles/types/index.ts.tmpl` | `/hooks/useReanimatedStyles/types/index.ts` | +| `references/templates/services/index.ts.tmpl` | `/services/index.ts` | +| `references/templates/services/fetch{{ComponentName}}Data.ts.tmpl` | `/services/fetchData.ts` | +| `references/templates/library/index.ts.tmpl` | `/library/index.ts` | +| `references/templates/library/format{{ComponentName}}Label.ts.tmpl` | `/library/formatLabel.ts` | + +## Confirmation + +Run via Bash: +```bash +find -type f | sort +``` + +Print: +- `✓ Component scaffolded at ` +- `Note: ensure react-native-reanimated is installed in your project.` + +## Rules + +- Never run `git add`, never commit, never create a branch. Scaffolding only. +- Never overwrite existing files — the collision check blocks the whole run. +- Do not install dependencies. +- Do not reformat the user's existing code. +- Do not push. Do not open a PR. diff --git a/src/commands/rn-component/references/architecture.md b/src/commands/rn-component/references/architecture.md new file mode 100644 index 0000000..986045c --- /dev/null +++ b/src/commands/rn-component/references/architecture.md @@ -0,0 +1,61 @@ +# Layered Hook Architecture + +This document defines the layering contract for React Native components scaffolded by `/rn-component`. + +## Layers + +### View (`index.tsx`) +- JSX only — no state, no logic, no side effects. +- Consumes exactly three hooks: `useStyles`, `useReanimatedStyles`, and `useViewModel`. +- Receives props typed as `IProps`. + +### ViewModel (`hooks/useViewModel/`) +- Single owner of all component logic. +- May use: `useState`, `useReducer`, `useMemo`, `useCallback`, `useEffect`, store subscriptions. +- Calls functions from `services/` and `library/` as needed. +- Returns `IUseViewModelReturn`. + +### Static Styles (`styles.ts`) +- Exports `useStyles(props: IProps)` — a hook that returns a `StyleSheet.create({})` result. +- Memoized with `useMemo`. +- No animated properties here. + +### Animation Styles (`hooks/useReanimatedStyles/`) +- All `react-native-reanimated` logic lives here. +- Receives `IUseReanimatedStylesProps` (never static styles). +- Never contains `StyleSheet.create` calls. + +### Services (`services/`) +- Plain async functions (API calls, AsyncStorage, etc.). +- No hooks allowed. +- Called from ViewModel only — never from the View. + +### Library (`library/`) +- Pure utility functions. +- No hooks, no side effects. +- May be called from ViewModel or from services. + +## Type conventions +- Interfaces use the `I` prefix: `IComponentNameProps`, `IUseComponentNameViewModelReturn`. +- Plain types (union, intersection, alias) have no prefix. +- Every folder that has public exports has a barrel `index.ts`. + +## Barrel cycle rule +Templates use deep relative imports only (e.g. `./types`, `../useReanimatedStyles/types`). +Never use `../..` shorthand — it creates import cycles between barrels. + +## JSX conditional rendering +Never wrap a JSX branch of a ternary in `()`. Use the line-break form: + +```tsx +{isRequired + ? + + : null +} +``` + +See `src/rules/jsx-style.md` for the full rule and rationale. diff --git a/src/commands/rn-component/references/templates/hooks/index.ts.tmpl b/src/commands/rn-component/references/templates/hooks/index.ts.tmpl new file mode 100644 index 0000000..507270c --- /dev/null +++ b/src/commands/rn-component/references/templates/hooks/index.ts.tmpl @@ -0,0 +1,2 @@ +export * from './use{{ComponentName}}ViewModel'; +export * from './useReanimatedStyles'; diff --git a/src/commands/rn-component/references/templates/hooks/useComponentNameViewModel/index.ts.tmpl b/src/commands/rn-component/references/templates/hooks/useComponentNameViewModel/index.ts.tmpl new file mode 100644 index 0000000..6334f82 --- /dev/null +++ b/src/commands/rn-component/references/templates/hooks/useComponentNameViewModel/index.ts.tmpl @@ -0,0 +1,10 @@ +import type { I{{ComponentName}}Props } from '../../types/I{{ComponentName}}Props'; +import type { IUse{{ComponentName}}ViewModelReturn } from './types'; + +export const use{{ComponentName}}ViewModel = ( + props: I{{ComponentName}}Props, +): IUse{{ComponentName}}ViewModelReturn => { + // state, effects, handlers + + return {}; +}; diff --git a/src/commands/rn-component/references/templates/hooks/useComponentNameViewModel/types/IUseComponentNameViewModelReturn.ts.tmpl b/src/commands/rn-component/references/templates/hooks/useComponentNameViewModel/types/IUseComponentNameViewModelReturn.ts.tmpl new file mode 100644 index 0000000..1820f54 --- /dev/null +++ b/src/commands/rn-component/references/templates/hooks/useComponentNameViewModel/types/IUseComponentNameViewModelReturn.ts.tmpl @@ -0,0 +1 @@ +export interface IUse{{ComponentName}}ViewModelReturn {} diff --git a/src/commands/rn-component/references/templates/hooks/useComponentNameViewModel/types/index.ts.tmpl b/src/commands/rn-component/references/templates/hooks/useComponentNameViewModel/types/index.ts.tmpl new file mode 100644 index 0000000..b9ad625 --- /dev/null +++ b/src/commands/rn-component/references/templates/hooks/useComponentNameViewModel/types/index.ts.tmpl @@ -0,0 +1 @@ +export * from './IUse{{ComponentName}}ViewModelReturn'; diff --git a/src/commands/rn-component/references/templates/hooks/useReanimatedStyles/index.ts.tmpl b/src/commands/rn-component/references/templates/hooks/useReanimatedStyles/index.ts.tmpl new file mode 100644 index 0000000..1bac7de --- /dev/null +++ b/src/commands/rn-component/references/templates/hooks/useReanimatedStyles/index.ts.tmpl @@ -0,0 +1,15 @@ +import { useAnimatedStyle, useSharedValue } from 'react-native-reanimated'; +import type { IUseReanimatedStylesProps } from './types'; + +// react-native-reanimated logic only — never static styles here. +export const useReanimatedStyles = (props: IUseReanimatedStylesProps) => { + const progress = useSharedValue(0); + + const animatedContainer = useAnimatedStyle(() => ({ + opacity: progress.value, + })); + + return { + animatedContainer, + }; +}; diff --git a/src/commands/rn-component/references/templates/hooks/useReanimatedStyles/types/IUseReanimatedStylesProps.ts.tmpl b/src/commands/rn-component/references/templates/hooks/useReanimatedStyles/types/IUseReanimatedStylesProps.ts.tmpl new file mode 100644 index 0000000..4dd3dbc --- /dev/null +++ b/src/commands/rn-component/references/templates/hooks/useReanimatedStyles/types/IUseReanimatedStylesProps.ts.tmpl @@ -0,0 +1 @@ +export interface IUseReanimatedStylesProps {} diff --git a/src/commands/rn-component/references/templates/hooks/useReanimatedStyles/types/index.ts.tmpl b/src/commands/rn-component/references/templates/hooks/useReanimatedStyles/types/index.ts.tmpl new file mode 100644 index 0000000..05dddfd --- /dev/null +++ b/src/commands/rn-component/references/templates/hooks/useReanimatedStyles/types/index.ts.tmpl @@ -0,0 +1 @@ +export * from './IUseReanimatedStylesProps'; diff --git a/src/commands/rn-component/references/templates/index.tsx.tmpl b/src/commands/rn-component/references/templates/index.tsx.tmpl new file mode 100644 index 0000000..2c85cb1 --- /dev/null +++ b/src/commands/rn-component/references/templates/index.tsx.tmpl @@ -0,0 +1,13 @@ +import React from 'react'; +import { View } from 'react-native'; +import type { I{{ComponentName}}Props } from './types'; +import { useStyles } from './styles'; +import { use{{ComponentName}}ViewModel, useReanimatedStyles } from './hooks'; + +export const {{ComponentName}}: React.FC = (props) => { + const styles = useStyles(props); + const reanimatedStyles = useReanimatedStyles({}); + const {} = use{{ComponentName}}ViewModel(props); + + return ; +}; diff --git a/src/commands/rn-component/references/templates/library/format{{ComponentName}}Label.ts.tmpl b/src/commands/rn-component/references/templates/library/format{{ComponentName}}Label.ts.tmpl new file mode 100644 index 0000000..5254c1d --- /dev/null +++ b/src/commands/rn-component/references/templates/library/format{{ComponentName}}Label.ts.tmpl @@ -0,0 +1,3 @@ +export function format{{ComponentName}}Label(input: string): string { + return input.trim(); +} diff --git a/src/commands/rn-component/references/templates/library/index.ts.tmpl b/src/commands/rn-component/references/templates/library/index.ts.tmpl new file mode 100644 index 0000000..c129dab --- /dev/null +++ b/src/commands/rn-component/references/templates/library/index.ts.tmpl @@ -0,0 +1 @@ +export * from './format{{ComponentName}}Label'; diff --git a/src/commands/rn-component/references/templates/services/fetch{{ComponentName}}Data.ts.tmpl b/src/commands/rn-component/references/templates/services/fetch{{ComponentName}}Data.ts.tmpl new file mode 100644 index 0000000..d739cb7 --- /dev/null +++ b/src/commands/rn-component/references/templates/services/fetch{{ComponentName}}Data.ts.tmpl @@ -0,0 +1,3 @@ +export async function fetch{{ComponentName}}Data(): Promise { + return null; +} diff --git a/src/commands/rn-component/references/templates/services/index.ts.tmpl b/src/commands/rn-component/references/templates/services/index.ts.tmpl new file mode 100644 index 0000000..4736a88 --- /dev/null +++ b/src/commands/rn-component/references/templates/services/index.ts.tmpl @@ -0,0 +1 @@ +export * from './fetch{{ComponentName}}Data'; diff --git a/src/commands/rn-component/references/templates/styles.ts.tmpl b/src/commands/rn-component/references/templates/styles.ts.tmpl new file mode 100644 index 0000000..a410817 --- /dev/null +++ b/src/commands/rn-component/references/templates/styles.ts.tmpl @@ -0,0 +1,10 @@ +import { StyleSheet } from 'react-native'; +import type { I{{ComponentName}}Props } from './types'; + +export const useStyles = (props: I{{ComponentName}}Props) => { + return StyleSheet.create({ + container: { + flex: 1, + }, + }); +}; diff --git a/src/commands/rn-component/references/templates/types/I{{ComponentName}}Props.ts.tmpl b/src/commands/rn-component/references/templates/types/I{{ComponentName}}Props.ts.tmpl new file mode 100644 index 0000000..932a088 --- /dev/null +++ b/src/commands/rn-component/references/templates/types/I{{ComponentName}}Props.ts.tmpl @@ -0,0 +1 @@ +export interface I{{ComponentName}}Props {} diff --git a/src/commands/rn-component/references/templates/types/index.ts.tmpl b/src/commands/rn-component/references/templates/types/index.ts.tmpl new file mode 100644 index 0000000..ea9928b --- /dev/null +++ b/src/commands/rn-component/references/templates/types/index.ts.tmpl @@ -0,0 +1 @@ +export * from './I{{ComponentName}}Props'; diff --git a/src/rules/conventional-commits.md b/src/rules/conventional-commits.md new file mode 100644 index 0000000..4675238 --- /dev/null +++ b/src/rules/conventional-commits.md @@ -0,0 +1,43 @@ +# Conventional Commits + +## Commit types + +| Type | When to use | +|---|---| +| `feat` | New feature | +| `fix` | Bug fix | +| `docs` | Documentation only | +| `style` | Formatting, whitespace (no logic change) | +| `refactor` | Code restructuring without feature/fix | +| `perf` | Performance improvement | +| `test` | Adding or updating tests | +| `build` | Build system, dependencies | +| `ci` | CI/CD configuration | +| `chore` | Maintenance, tooling | +| `raw` | Raw data, config files | +| `cleanup` | Dead code removal, cleanup | +| `remove` | Removing features or files | + +## Commit format + +``` +(): + +[optional body if subject is not enough] + +Co-Authored-By: Claude Haiku 4.5 +``` + +- Subject: max 50 characters, imperative mood ("add", not "added") +- Scope: optional, keep it short (1 word max: `auth`, `ui`, `config`) +- Description: 2–4 words only — no full sentences +- Body: only when the subject alone is insufficient + +## Rules + +- Never mix unrelated changes in one commit +- Prefer smaller, focused commits +- If a file contains changes of different natures, split them and mention in the body +- Use `git diff HEAD -- ` to inspect specific changes before deciding grouping +- Never use `git add .` or `git add -A` — always stage specific files by name +- Never run `git push` — committing only, pushing is the user's responsibility diff --git a/src/rules/git-workflow.md b/src/rules/git-workflow.md index 1377a7a..86931c4 100644 --- a/src/rules/git-workflow.md +++ b/src/rules/git-workflow.md @@ -7,3 +7,8 @@ Always follow this order when working with changes: 3. `/pr` — open PR from the branch to main Never commit directly to `main` or `master`. If already on `main`, run `/branch` first before any commits. + +## Branch naming conventions + +- Release branches: `release/v{version}` — always include the `v` prefix (e.g. `release/v0.2.0`, `release/v1.0.0`). +- Feature branches: `feat/{description}` (e.g. `feat/atoms-components`). diff --git a/src/rules/jsx-style.md b/src/rules/jsx-style.md new file mode 100644 index 0000000..69d90cc --- /dev/null +++ b/src/rules/jsx-style.md @@ -0,0 +1,49 @@ +# JSX style + +## Conditional rendering + +Never wrap a JSX subtree in parentheses as the branch of a ternary. Use the "line-break ternary" form with the `?`, JSX, and `: null` on their own lines. + +### ✅ Correct + +```tsx +{isRequired + ? + + : null +} +``` + +For simple inline branches (single `` / primitive), keeping everything on a single line is fine: + +```tsx +{title ? {title} : null} +``` + +### ❌ Wrong + +```tsx +{isRequired ? ( + +) : null} +``` + +**Why:** Wrapping JSX in `()` as a ternary branch hides the structure — the `?` and `: null` visually collide with the JSX, and diffs become noisier when props change. The line-break form keeps the three pieces (`condition`, `JSX branch`, `else branch`) on their own axes and scans top-to-bottom. + +**How to apply:** +- Any time you render JSX conditionally inside another JSX tree. +- Applies equally to `?:` with `null` and to `?:` with another element. +- When both branches are JSX, keep each on its own line with the `?` / `:` on their own lines too. +- Never introduce `(` `)` around a JSX branch purely for ternary grouping. + +## `&&` guard + +Prefer `{cond ? : null}` over `{cond && }` when `cond` can be a falsy-but-renderable value (`0`, `''`, `NaN`) — React Native will render a stray `0` as text. Use `&&` only when `cond` is strictly boolean. diff --git a/src/rules/skills-format.md b/src/rules/skills-format.md index a98af8e..373c9c2 100644 --- a/src/rules/skills-format.md +++ b/src/rules/skills-format.md @@ -2,12 +2,12 @@ ## User-invokable commands (`/name`) -Commands are invoked **only** when the user explicitly types `/name`. Claude must never auto-trigger a command based on context — that is exclusively for skills. Use `commands//SKILL.md`: +Commands are invoked **only** when the user explicitly types `/name`. Claude must never auto-trigger a command based on context — that is exclusively for skills. Always include `user-invocable: true` in frontmatter. Use `commands//SKILL.md`: ``` commands/ └── / - ├── SKILL.md ← required + ├── SKILL.md ← required (must have user-invocable: true) ├── references/ ← optional ├── examples/ ← optional └── scripts/ ← optional diff --git a/src/skills/commit/SKILL.md b/src/skills/commit/SKILL.md index ee9e759..5680808 100644 --- a/src/skills/commit/SKILL.md +++ b/src/skills/commit/SKILL.md @@ -1,6 +1,6 @@ --- name: commit -description: This skill should be used when the user asks to "commit", "create commits", "commit changes", or wants to commit staged/unstaged changes following the Conventional Commits standard. +description: This skill should be used whenever the user wants to save, record, or commit changes to git — regardless of the language or phrasing used. argument-hint: [scope opcional] allowed-tools: [Agent] user-invocable: false @@ -22,6 +22,8 @@ To get the model ID: look in your system context for the line "The exact model I Your job is to analyze the git changes and create conventional commits. +Read `src/rules/conventional-commits.md` and follow it strictly for commit types, format, and rules. + ## Pre-flight check 1. Run `git branch --show-current` to get the current branch. @@ -36,39 +38,6 @@ Your job is to analyze the git changes and create conventional commits. 4. For each group, determine the commit type and create the commit 5. Print each commit name as it is created -## Commit types - -| Type | When to use | -|---|---| -| `feat` | New feature | -| `fix` | Bug fix | -| `docs` | Documentation only | -| `style` | Formatting, whitespace (no logic change) | -| `refactor` | Code restructuring without feature/fix | -| `perf` | Performance improvement | -| `test` | Adding or updating tests | -| `build` | Build system, dependencies | -| `ci` | CI/CD configuration | -| `chore` | Maintenance, tooling | -| `raw` | Raw data, config files | -| `cleanup` | Dead code removal, cleanup | -| `remove` | Removing features or files | - -## Commit format - -``` -(): - -[optional body if subject is not enough] - -Co-Authored-By: Claude Haiku 4.5 -``` - -- Subject: max 50 characters, imperative mood ("add", not "added") -- Scope: optional, keep it short (1 word max: `auth`, `ui`, `config`) -- Description: 2–4 words only — no full sentences -- Body: only when the subject alone is insufficient - ## Creating each commit For each group of changes: @@ -87,13 +56,4 @@ EOF 3. Print to the user: `✓ feat(auth): add JWT token refresh` Commit names appear one below the other as commits are created. - -## Rules - -- Never mix unrelated changes in one commit -- Prefer smaller, focused commits -- If a file contains changes of different natures, split them and mention in the body -- Use `git diff HEAD -- ` to inspect specific changes before deciding grouping -- Never use `git add .` or `git add -A` — always stage specific files by name -- Never run `git push` — this command only commits, pushing is the user's responsibility ```