diff --git a/.claude/memory/area-dropdowns.json b/.claude/memory/area-dropdowns.json new file mode 100644 index 0000000..4b767a2 --- /dev/null +++ b/.claude/memory/area-dropdowns.json @@ -0,0 +1,139 @@ +{ + "$schema": "https://kun.databayt.org/schemas/area-dropdowns.v1.json", + "version": "1.0.0", + "description": "Per-repo `area` dropdown options used in .github/ISSUE_TEMPLATE/*.yml. The replicate-github-config.sh script reads this when copying templates so each repo gets the right dropdown without manual editing.", + "lastUpdated": "2026-04-26", + "repos": { + "kun": [ + "agents", + "skills", + "rules", + "hooks", + "scripts", + "memory", + "mcp", + "workflow", + "docs", + "other" + ], + "codebase": [ + "components", + "registry", + "atoms", + "templates", + "blocks", + "agents", + "docs", + "other" + ], + "hogwarts": [ + "platform", + "auth", + "students", + "teachers", + "parents", + "finance", + "attendance", + "timetable", + "exams", + "reports", + "settings", + "marketing", + "i18n", + "docs", + "other" + ], + "souq": [ + "cart", + "checkout", + "vendor", + "catalog", + "orders", + "search", + "auth", + "payments", + "i18n", + "docs", + "other" + ], + "mkan": [ + "listings", + "booking", + "search", + "calendar", + "reviews", + "payments", + "auth", + "host", + "guest", + "i18n", + "docs", + "other" + ], + "shifa": [ + "appointments", + "patients", + "doctors", + "prescriptions", + "schedule", + "billing", + "auth", + "i18n", + "docs", + "other" + ], + "marketing": [ + "landing", + "blog", + "i18n", + "seo", + "analytics", + "docs", + "other" + ], + "swift-app": [ + "ios", + "watchos", + "auth", + "sync", + "ui", + "i18n", + "docs", + "other" + ], + "shadcn": [ + "components", + "registry", + "themes", + "docs", + "other" + ], + "radix": [ + "primitives", + "accessibility", + "docs", + "other" + ], + "apple": [ + "design-tokens", + "patterns", + "docs", + "other" + ], + "distributed-computer": [ + "p2p", + "token", + "consensus", + "infra", + "docs", + "other" + ], + ".github": [ + "templates", + "workflows", + "profile", + "docs", + "other" + ] + } +} diff --git a/.claude/memory/team.json b/.claude/memory/team.json index 2916bdc..23d73ad 100644 --- a/.claude/memory/team.json +++ b/.claude/memory/team.json @@ -1,6 +1,6 @@ { - "version": "1.0", - "updated": "2026-03-31", + "version": "1.1", + "lastUpdated": "2026-04-28", "company": { "name": "Databayt", "license": "SSPL", @@ -10,22 +10,39 @@ "team": [ { "name": "Abdout", + "category": "tech", "role": "founder-tech-lead", "installRole": "engineer" }, + { + "name": "Ibrahim", + "category": "tech", + "role": "engineer", + "installRole": "engineer" + }, { "name": "Ali", - "role": "business", + "category": "business", + "role": "sales-qa", + "installRole": "business" + }, + { + "name": "Mutaz", + "category": "business", + "role": "general-business", "installRole": "business" }, { "name": "Samia", - "role": "creative-content", + "category": "rnd", + "role": "research-and-development", "installRole": "content" }, { "name": "Sedon", - "role": "facilitator-ops", + "category": "facilitator", + "role": "facilitator-business", + "facilitates": ["Ali", "Mutaz"], "installRole": "ops" } ] diff --git a/.claude/rules/github-workflow.md b/.claude/rules/github-workflow.md index 0ea94b4..4e1f093 100644 --- a/.claude/rules/github-workflow.md +++ b/.claude/rules/github-workflow.md @@ -1,163 +1,197 @@ +--- +paths: [".github/**", "**/CHANGELOG.md", ".gitignore", "**/PULL_REQUEST_TEMPLATE.md", "CONTRIBUTING.md"] +--- + # GitHub Workflow Cycle -The state-of-the-art GitHub workflow for all databayt repos. Every piece of work follows this clean chain. +The state-of-the-art GitHub workflow for all databayt repos. Every piece of work follows this clean chain. Git and GitHub are the **sole evidence base** for the sharing-economy revenue model — every artifact is a Contribution Unit (CU) credit when issues close. -## The Cycle +## The cycle ``` ┌──────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌───────┐ ┌───────┐ ┌────────┐ ┌───────┐ │ IDEA │───▶│ ISSUE │───▶│ BRANCH │───▶│ COMMIT │───▶│ PUSH │───▶│ PR │───▶│REVIEW │───▶│ MERGE │───▶│ CLOSE │ └──────┘ └────────┘ └────────┘ └────────┘ └────────┘ └───────┘ └───────┘ └────────┘ └───────┘ - │ │ │ │ - │ │ │ │ - Tracks work Discussion Approval Auto-deploy - Labels + assign Comments CI gates Verify live + │ │ │ │ │ │ │ │ + Memory + /<#>- Conventional Triggers Closes CI gates + auto-status status/done + Acceptance slug + signed + auto- #N body contribution flips to + CU credit + Refs #N status declaration in-review ``` -## Each Step +## Each step ### 1. IDEA → ISSUE -Every change starts as a GitHub issue. No exceptions. +Every change starts as a GitHub issue. No exceptions, including hotfixes and typos. ```bash gh issue create \ --repo databayt/ \ - --title ": " \ - --body "" \ - --label "," \ - --assignee "" + --title "[]: " \ + --body "$body" \ + --label "type/,priority/p,status/triage" ``` -**Labels:** +Or use the in-product `/issue` skill, or let the `auto-issue.sh` UserPromptSubmit hook do it from a work-regex prompt. + +**Type → label → branch-prefix:** + | Type | Label | Branch prefix | |------|-------|---------------| -| Feature | `type:feature` | `feat/` | -| Bug fix | `type:bug` | `fix/` | -| Chore | `type:chore` | `chore/` | -| Docs | `type:docs` | `docs/` | -| Refactor | `type:refactor` | `refactor/` | - -**Priority:** `P0` (drop everything), `P1` (this week), `P2` (this sprint), `P3` (backlog) +| Feature | `type/feat` | `feat/` | +| Fix | `type/fix` | `fix/` | +| Chore | `type/chore` | `chore/` | +| Docs | `type/docs` | `docs/` | +| Refactor | `type/refactor` | `refactor/` | +| Performance | `type/perf` | `perf/` | +| Test | `type/test` | `test/` | +| Style | `type/style` | `style/` | +| CI | `type/ci` | `ci/` | +| Build | `type/build` | `build/` | +| Revert | `type/revert` | `revert/` | +| i18n | `type/i18n` | `i18n/` | +| Hotfix | `type/fix` + `priority/p0` | `hotfix/` | + +**Priority:** `priority/p0` (drop everything), `priority/p1` (this week), `priority/p2` (this sprint), `priority/p3` (backlog). + +**Status (managed by `auto-status.yml`):** `status/triage` → `status/ready` → `status/in-progress` → `status/in-review` → `status/done`. `status/blocked` is added manually when work is paused. + +**Size (Fibonacci):** issue includes 1/2/3/5/8/13 estimate. Locks at `status/ready` — drives the CU multiplier. ### 2. ISSUE → BRANCH -One branch per issue. Branch name references the issue. +One branch per issue. Branch name encodes the issue number, which is the primary key for the entire workflow. ```bash -git checkout -b / -# Examples: -# feat/admission-form -# fix/rtl-sidebar-overlap -# chore/analyze-config +git switch -c feat/9-unified-git-github-workflow origin/main +``` + +Or `/branch` derives the name from the active issue automatically. + +CI regex (in `pr-check.yml`): + +``` +^(feat|fix|chore|docs|refactor|test|perf|style|ci|build|revert|i18n|hotfix)\/[0-9]+-[a-z0-9][a-z0-9-]*$ ``` **Rules:** -- Branch from `main` (always fresh) +- Branch from `origin/main` (always fresh) - One issue = one branch = one PR - Delete branch after merge ### 3. BRANCH → COMMITS -Atomic, conventional commits. Each commit is a logical unit. +Atomic, conventional, signed. ```bash -git commit -m "$(cat <<'EOF' -feat: add admission form with validation +git commit -S -m "$(cat <<'EOF' +feat(workflow): wire UserPromptSubmit auto-issue hook -- Zod schema for student data -- Server action with auth + tenant isolation -- RTL-compatible form layout +Triggers only on work-regex prompts (add|fix|build|create|...). Caps 20 +issues per day; resolves repo from cwd via repositories.json. Writes +.claude/state/active-issue.json so subsequent /branch /commit /pr /close +can attribute the rest of the session. -Refs #42 +Refs #9 -Co-Authored-By: Claude Opus 4.6 +Co-Authored-By: Claude Opus 4.7 EOF )" ``` **Conventional format:** + ``` -: +(): -[optional body — what and why, not how] + [Refs #N | Closes #N] -Co-Authored-By: Claude Opus 4.6 +Co-Authored-By: Claude Opus 4.7 ``` -**Types:** `feat`, `fix`, `chore`, `docs`, `refactor`, `test`, `perf`, `style` +Allowed types: `feat | fix | docs | chore | refactor | test | perf | style | ci | build | revert | i18n`. **Rules:** -- Present tense ("add" not "added") -- Under 72 chars for subject line -- Body explains WHY, not what (the diff shows what) -- Reference issue number +- Imperative ("add" not "added") +- Subject ≤ 72 chars, lowercase first letter, no trailing period +- Body explains WHY +- `Refs #N` for work-in-progress; `Closes #N` for the final commit on the branch +- All commits signed (`-S`) — required by `signed-commits.yml` CI +- `Co-Authored-By:` trailer for AI-assisted commits (records attribution; AI earns 0 CU) -### 4. COMMITS → PUSH +The husky `commit-msg` hook validates via commitlint. CI runs commitlint against every commit in the PR. -Push branch to origin with upstream tracking. +### 4. COMMITS → PUSH ```bash git push -u origin ``` +The `post-push.sh` hook captures any draft PR URL into `.claude/state/active-issue.json.pr_url` automatically. + ### 5. PUSH → PR -Create PR that links to the issue. +PR closes the issue and declares contribution credits. ```bash gh pr create \ - --title ": " \ - --body "$(cat <<'EOF' -## Summary -<1-3 bullet points of what changed and why> + --draft \ + --title "feat(workflow): unified git/github workflow + contribution-as-evidence layer" \ + --body "$body" +``` -## Changes -- : -- : +The body uses `.github/PULL_REQUEST_TEMPLATE.md` and includes: +- Summary (1-3 bullets, why) +- `Closes #` +- Test plan checklist +- Screenshots (Before/After for UI) +- Standard checklist (CLA + lint + typecheck + secrets) +- **Contribution declaration block** (parsed by `contribution-declaration.yml` CI) -## Test plan -- [ ] -- [ ] +#### Contribution declaration -## Screenshots - +```markdown +## Contribution declaration -Closes # +Closes # (size: ) -🤖 Generated with [Claude Code](https://claude.com/claude-code) -EOF -)" +- Author: @ +- Pair (50% of size): @ | none +- Reviewers (10% each, max 3): GitHub auto-lists +- Design credit (20% of size): @ | none — link: +- AI co-author: claude-opus-4-7 | claude-sonnet-4 | none + +By opening this PR I confirm credits above are accurate. False declarations +forfeit Contribution Units for this PR and reduce the contributor's monthly +cap by 25%. ``` +`/pr` auto-fills it from `.claude/state/active-issue.json` (size from the issue's locked Size field; author from `git log`; AI co-author from the commit trailers; design from a `figma.com` URL in the issue body if present). + **Rules:** - Title matches the primary commit message -- `Closes #N` auto-closes the issue on merge -- Summary is human-readable (not a commit log dump) -- Test plan tells reviewer how to verify +- `Closes #N` auto-closes the issue on merge (only on the PR body, not commit messages) +- Always open as draft; `gh pr ready` when CI passes + self-review done +- Declaration block is required — `contribution-declaration.yml` rejects PRs missing it -### 6. PR → REVIEW + DISCUSSION +### 6. PR → REVIEW -The PR is a conversation space. +The PR is the conversation space. ```bash -# Request review gh pr edit --add-reviewer - -# Add comment gh pr comment --body "Addressed feedback: changed X to Y because Z" - -# View review comments gh api repos/databayt//pulls//reviews ``` **Discussion rules:** - Respond to every review comment - If disagreeing, explain why with evidence -- If agreed, fix and comment "Fixed in " +- If agreed, fix and comment "Fixed in " - Discussion happens ON the PR, not in Slack +- Reviews require >2 substantive comments to count toward CU credit ### 7. REVIEW → MERGE @@ -170,54 +204,76 @@ gh pr merge --squash --delete-branch **Merge rules:** - Squash merge (clean history) - Delete branch after merge -- CI must pass before merge -- At least 1 approval (or self-merge for solo work with explanation) +- All CI checks must pass: `pr-check`, `signed-commits`, `contribution-declaration`, `labeler`, `auto-status` +- At least 1 approval (or self-merge for solo work with documented reason) +- Never `--no-verify`, never force-push to `main` ### 8. MERGE → CLOSE + DEPLOY -`Closes #N` in the PR body auto-closes the issue. Vercel auto-deploys on push to main. +`Closes #N` in the PR body auto-closes the issue. `auto-status.yml` ensures `status/done` label. Vercel auto-deploys on push to `main`. ```bash -# Verify issue closed -gh issue view --repo databayt/ - -# Verify deployment +gh issue view --repo databayt/ # verify closed gh api repos/databayt//deployments --jq '.[0].statuses_url' ``` -### 9. DEPLOY → VERIFY +The `/close` skill is for explicit issue closure when the PR body's `Closes #N` is missing or when closing for `wontfix`/`duplicate`. -Post-deploy health check (the `/watch` command). +### 9. DEPLOY → VERIFY -```bash -# Screenshot production page -# Check console errors -# Check network requests -# Verify the fix/feature works in production -``` +Post-deploy health check via `/watch` skill: production screenshot + console errors + network requests check. -## Quick Reference +## Quick reference -| Action | Command | -|--------|---------| -| Create issue | `gh issue create --repo databayt/` | -| Create branch | `git checkout -b feat/` | -| Commit | `git commit -m "feat: description"` | -| Push | `git push -u origin ` | -| Create PR | `gh pr create --title "feat: X" --body "Closes #N"` | -| Review | `gh pr review --approve` | -| Merge | `gh pr merge --squash --delete-branch` | -| Verify | `gh issue view ` + `/watch` | +| Action | Skill | Command | +|--------|-------|---------| +| Create issue | `/issue` | `gh issue create --repo databayt/` | +| Resume issue | `/issue resume ` | hydrates `.claude/state/active-issue.json` | +| List my issues | `/issue list` | `gh search issues --owner databayt --assignee @me` | +| Create branch | `/branch` | `git switch -c /<#>- origin/main` | +| Commit | `/commit` | `git commit -S -m "..."` (commitlint via husky) | +| Push | — | `git push -u origin ` | +| Create PR | `/pr` | `gh pr create --draft ...` | +| Review | — | `gh pr review --approve` | +| Merge | — | `gh pr merge --squash --delete-branch` | +| Close | `/close` | `gh issue close --comment "..."` | +| Verify | `/watch` | `gh issue view ` + production screenshot | -## Anti-Patterns +## Anti-patterns -| Don't | Do Instead | +| Don't | Do instead | |-------|-----------| | Commit directly to main | Branch + PR | -| PR without issue | Create issue first | -| Mega PR (20+ files) | Split into focused PRs | -| Force push to main | Never. Ever. | -| Merge without CI passing | Fix CI first | -| Leave stale branches | Delete after merge | -| Squash commit messages like "fix stuff" | Meaningful conventional commit | -| Close issue manually | Use `Closes #N` in PR | +| PR without an issue | Create issue first via `/issue` | +| Mega-PR (50+ unrelated files) | Split into focused PRs, one concern each | +| Force-push to main | Denied by branch protection. Never. | +| Merge without all CI green | Fix CI first | +| Leave stale branches | Squash + `--delete-branch` | +| `--no-verify` to skip commitlint | Fix the message | +| Skip signing | Set up SSH signing once (see CONTRIBUTING.md) | +| False Contribution declaration | Forfeits CU; 25% monthly cap reduction | +| Hardcoded `Co-Authored-By: Claude` in PR body | Goes in commit trailer, not PR body | +| Branch without issue number | CI rejects | + +## Hooks that fire automatically + +| Hook | When | What | +|------|------|------| +| `auto-issue.sh` | UserPromptSubmit | Creates GitHub issue from work-regex prompt; writes `active-issue.json` | +| `post-commit.sh` | PostToolUse(git commit) | Comments commit SHA + subject on active issue | +| `post-push.sh` | PostToolUse(git push) | Captures PR URL into `active-issue.json.pr_url` | +| `session-start.sh` | SessionStart | Lists active issue + uncommitted work + report queue + signed-commit warning | +| `session-end.sh` | Stop | Posts session summary to active issue if 2+ commits | + +## CI workflows + +| Workflow | When | Effect | +|----------|------|--------| +| `pr-check.yml` | every PR push | typecheck/lint/test/build/commit-lint/branch-name/pr-body parallel jobs | +| `auto-status.yml` | branch create + PR open/merge + issue close/reopen | flips `status/*` labels | +| `labeler.yml` | every PR push | applies `area/*` labels by file path | +| `stale.yml` | weekly Mondays | marks issues stale at 30 days, closes at 37; exempts P0/P1, in-progress, in-review, report, pinned, security, monthly-report | +| `signed-commits.yml` | every PR push | rejects PRs with unsigned commits | +| `contribution-declaration.yml` | every PR push | validates the declaration block, links issue exists | + +See also: `.claude/rules/cowork-bridge.md` for cross-session handoff via GitHub Issues + bridge.md. diff --git a/.claude/settings.json b/.claude/settings.json index 1e3fc1d..6d0cc28 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -8,7 +8,113 @@ "OSS_PATH": "/Users/abdout/oss", "GITHUB_USER": "abdout" }, + "permissions": { + "allow": [ + "Read", + "Glob", + "Grep", + "Edit", + "Write", + "WebFetch", + "WebSearch", + + "Bash(pnpm:*)", + "Bash(npm run:*)", + "Bash(npm test:*)", + "Bash(npm install)", + "Bash(npx:*)", + + "Bash(git status)", + "Bash(git status:*)", + "Bash(git diff:*)", + "Bash(git log:*)", + "Bash(git add:*)", + "Bash(git commit:*)", + "Bash(git push:*)", + "Bash(git pull:*)", + "Bash(git checkout:*)", + "Bash(git branch:*)", + "Bash(git fetch:*)", + "Bash(git remote:*)", + "Bash(git restore:*)", + "Bash(git stash:*)", + "Bash(git reflog:*)", + "Bash(git rev-parse:*)", + "Bash(git config:*)", + "Bash(git show:*)", + + "Bash(gh issue:*)", + "Bash(gh pr:*)", + "Bash(gh repo:*)", + "Bash(gh api:*)", + "Bash(gh run:*)", + "Bash(gh workflow:*)", + "Bash(gh deployment:*)", + "Bash(gh search:*)", + "Bash(gh label:*)", + "Bash(gh release:*)", + + "Bash(ls:*)", + "Bash(find:*)", + "Bash(grep:*)", + "Bash(cat:*)", + "Bash(jq:*)", + "Bash(echo:*)", + "Bash(pwd)", + "Bash(which:*)", + "Bash(file:*)", + "Bash(wc:*)", + "Bash(head:*)", + "Bash(tail:*)", + "Bash(chmod:*)", + "Bash(mkdir:*)", + "Bash(mktemp)", + "Bash(date:*)", + "Bash(sed:*)", + "Bash(awk:*)" + ], + "deny": [ + "Bash(rm -rf /*)", + "Bash(rm -rf /)", + "Bash(rm -rf ~)", + "Bash(rm -rf ~/*)", + "Bash(curl * | sh)", + "Bash(curl * | bash)", + "Bash(wget * | sh)", + "Bash(sudo *)", + "Bash(chmod 777 *)", + "Bash(git push --force *main*)", + "Bash(git push -f *main*)", + "Bash(git reset --hard origin/main)", + "Bash(git rebase -i*)", + "Bash(gh repo delete:*)", + "Bash(gh release delete:*)" + ] + }, "hooks": { + "SessionStart": [ + { + "matcher": "startup|resume", + "hooks": [ + { + "type": "command", + "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/session-start.sh 2>/dev/null; exit 0", + "timeout": 30 + } + ] + } + ], + "UserPromptSubmit": [ + { + "hooks": [ + { + "type": "command", + "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/hooks/auto-issue.sh 2>/dev/null; exit 0", + "timeout": 15 + } + ] + } + ], "PreToolUse": [ { "matcher": "Bash(pnpm dev)", @@ -38,6 +144,26 @@ "command": "if [[ \"$FILE_PATH\" =~ \\.(ts|tsx|js|jsx|json|css|md)$ ]]; then npx prettier --write \"$FILE_PATH\" 2>/dev/null; fi; exit 0" } ] + }, + { + "matcher": "Bash(git commit:*)", + "hooks": [ + { + "type": "command", + "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/hooks/post-commit.sh 2>/dev/null; exit 0", + "timeout": 10 + } + ] + }, + { + "matcher": "Bash(git push:*)", + "hooks": [ + { + "type": "command", + "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/hooks/post-push.sh 2>/dev/null; exit 0", + "timeout": 10 + } + ] } ], "Stop": [ @@ -46,7 +172,8 @@ "hooks": [ { "type": "command", - "command": "echo \"[$(date '+%Y-%m-%d %H:%M:%S')] Session ended\" >> ~/.claude/session-log.txt" + "command": "bash \"$CLAUDE_PROJECT_DIR\"/scripts/hooks/session-end.sh 2>/dev/null; echo \"[$(date '+%Y-%m-%d %H:%M:%S')] Session ended\" >> ~/.claude/session-log.txt; exit 0", + "timeout": 15 } ] } diff --git a/.claude/skills/branch/SKILL.md b/.claude/skills/branch/SKILL.md new file mode 100644 index 0000000..0df95c0 --- /dev/null +++ b/.claude/skills/branch/SKILL.md @@ -0,0 +1,73 @@ +--- +name: branch +description: Create a feature branch from the active issue. Branch name follows /-, which is what auto-status, contribution-tally, and signed-commits all key off. +--- + +# /branch + +Create a properly named feature branch from the currently active GitHub issue. The branch name encodes the issue number, which is the primary key for the entire workflow (CI, status flips, contribution attribution). + +## Format + +``` +/- +``` + +Examples: + +``` +feat/9-unified-git-github-workflow +fix/108-rtl-sidebar-overlap +chore/42-bump-eslint-to-9 +docs/56-add-deploy-runbook +``` + +The PR-check workflow's `branch-name` job rejects anything that doesn't match the regex `^(feat|fix|chore|docs|refactor|test|perf|style|ci|build|revert|i18n|hotfix)\/[0-9]+-[a-z0-9][a-z0-9-]*$`. + +## Steps + +1. Read `.claude/state/active-issue.json`. If absent → tell the user to run `/issue` first. +2. Determine `` from the issue's labels (`type/feat` → `feat`, etc.). Fallback `feat`. +3. Generate `` from the issue title: + - Strip `[Type]: ` prefix + - Lowercase + - Replace non-`[a-z0-9]+` runs with single hyphens + - Trim leading/trailing hyphens + - Limit to 40 chars +4. Compose branch name `/-`. +5. If branch already exists locally → `git switch `. Else → `git switch -c ` from `main` (refresh first: `git fetch origin main && git switch -c origin/main`). +6. Update `.claude/state/active-issue.json.branch = ""`. +7. Print: "Branch ready: . Make changes, then /commit." + +## Edge cases + +- **Active issue exists but on a different repo than cwd**: error and ask user to `cd` to the right repo. +- **Branch name regex would fail**: shorten the slug; if title has nothing kebab-able, use `/-update`. +- **`main` has unpushed local commits**: pull first; warn if pull fails. +- **Currently on `main` with uncommitted changes**: stash them, switch, then `git stash pop` (carry to new branch). + +## Rebase or fork from current? + +This skill always branches from `origin/main`, never from the current branch. Avoid stacking by accident. If the user wants a stacked branch, they do it manually. + +## Integration + +- Triggers `auto-status.yml` on push: `status/triage` → `status/in-progress`. +- Used by `/commit` (validates branch name in commit-msg footer). +- Used by `/pr` (PR title derives from branch name's `` and the issue title). + +## Example + +``` +$ /branch +Active issue: databayt/kun#9 [Feat]: unified git/github workflow + contribution-as-evidence layer +Type: feat (from label type/feat) +Slug: unified-git-github-workflow (40 chars max) +Branch: feat/9-unified-git-github-workflow + +$ git switch -c feat/9-unified-git-github-workflow origin/main +Switched to a new branch 'feat/9-unified-git-github-workflow' + +Branch ready: feat/9-unified-git-github-workflow. +Make changes, then /commit. +``` diff --git a/.claude/skills/close/SKILL.md b/.claude/skills/close/SKILL.md new file mode 100644 index 0000000..a1f4d63 --- /dev/null +++ b/.claude/skills/close/SKILL.md @@ -0,0 +1,84 @@ +--- +name: close +description: Close the active issue with a summary comment + link to merged PR. Clears active-issue.json. +--- + +# /close + +Close the currently active GitHub issue and clear the active-issue pointer. Use after the linked PR has merged (or when intentionally closing without a PR — wontfix, duplicate, etc.). + +## Steps + +1. Read `.claude/state/active-issue.json`. +2. Branch on PR state: + - **PR merged**: build a summary (commit count, files changed, PR URL); proceed to close. + - **PR open or none**: prompt for confirmation. Closing without a merge implies wontfix/duplicate/superseded — warn the user; ask for a reason; record it. +3. `gh issue close --repo --comment "$summary" --reason "completed"` (or `--reason "not planned"` for wontfix). +4. Move `.claude/state/active-issue.json` → `.claude/state/history/issue--.json`. +5. Auto-status workflow ensures `status/done` label is set on the closed issue. + +## Summary template + +```markdown +## Closed via # + +This issue is closed. Summary of work: + +- **Commits**: +- **PR**: # — merged +- **Files changed**: +- **Lines**: + / - + +Key changes: +- +- +- + +Verification: +- [x] CI passed +- [x] PR merged to main + +Resume any related work with `/issue resume `. +``` + +The summary is *not* a release note — it's a closing receipt. Detailed change notes go in the PR body and the merged commit messages. + +## When NOT to use /close + +- **Issue auto-closed by `Closes #N` in PR body**: the auto-status workflow handles labels; just clear active-issue.json manually if needed (or `/issue resume ` to verify closed state, which auto-archives the pointer). +- **Issue blocked**: don't close; comment + add `status/blocked` label; keep open. +- **Issue duplicates another**: close with `--reason "not planned"` and link the canonical issue. + +## Integration + +- Triggers `auto-status.yml` (issues.closed event) → ensures `status/done` label. +- Archives `active-issue.json` to `.claude/state/history/`. +- Future `/issue list` will not show this issue (closed). + +## Example + +``` +$ /close +Active issue: databayt/kun#9 [Feat]: unified git/github workflow ... +Linked PR: #10 — MERGED 2026-04-26 + +Summary: + - Commits: 11 + - PR: #10 merged 2026-04-26 + - Files: 38 changed, +3427 / -89 + +Key changes: + - Add 5 issue YAML forms + PR template + CODEOWNERS + labeler + dependabot + - Add 6 GitHub Actions workflows + - Wire commitlint + husky + lint-staged + - Wire 4 git/github automation hooks + - Rewrite /issue and add /branch /commit /pr /close skills + +OK? [Y/n]: y + +→ Closed databayt/kun#9 with summary comment. +→ Archived .claude/state/active-issue.json → .claude/state/history/issue-9-20260426-143022.json +→ status/done label confirmed. + +Next: /issue list to pick up the next task. +``` diff --git a/.claude/skills/commit/SKILL.md b/.claude/skills/commit/SKILL.md new file mode 100644 index 0000000..56cec7e --- /dev/null +++ b/.claude/skills/commit/SKILL.md @@ -0,0 +1,90 @@ +--- +name: commit +description: Draft and create a Conventional Commit from the staged diff. Always signed, always references the active issue. +--- + +# /commit + +Compose a Conventional Commits 1.0.0 message from the staged diff, attach `Refs #`, sign the commit, and push through husky's commit-msg hook (commitlint). + +## Steps + +1. Verify there are staged changes: `git diff --staged --stat`. If empty → suggest `git add ` first. +2. Read `.claude/state/active-issue.json`. If absent → run `/issue` first (or proceed without `Refs` and warn). +3. Build the message: + - **Type**: from active-issue's `type/*` label, fallback `feat`. + - **Scope** (optional): inferred from the dominant directory in the staged diff (`agents`, `skills`, `rules`, `hooks`, `workflow`, etc.). Skip scope when changes span >2 areas. + - **Subject**: imperative, ≤ 72 chars, lowercase, no trailing period. Generated from the diff's most important file or from the issue title. + - **Body** (optional): paragraph explaining *why*. Skip for tiny changes. + - **Footer**: `Refs #` if work-in-progress, or `Closes #` if this is the final commit on the branch (user confirms). + - **Trailer**: `Co-Authored-By: Claude Opus 4.7 `. +4. Show the user the proposed message; allow edits. +5. `git commit -S -m ""` (signed). +6. The husky `commit-msg` hook runs commitlint — validates type, header length, lowercase. +7. The `post-commit.sh` PostToolUse hook posts a comment on the active issue with the SHA. + +## Conventional types + +`feat | fix | docs | chore | refactor | test | perf | style | ci | build | revert | i18n` + +Custom: `i18n` for translation-only changes (databayt convention). + +## Subject rules + +- Imperative ("add" not "added", "fix" not "fixed") +- Lowercase first letter +- ≤ 72 chars total (including `(): `) +- No trailing period + +## Refs vs Closes + +- `Refs #N` — work in progress, this commit is part of the issue +- `Closes #N` — this is the final commit; merging will close the issue + +`Closes` should appear in **at most one commit per issue** — usually the last one before opening the PR. The PR body's `Closes #N` is what actually closes the issue on merge; commit-message `Closes` is informational. + +## Signed commits + +- Required after this PR ships (signed-commits.yml CI gate). +- Set up once: `git config --global commit.gpgsign true && git config --global gpg.format ssh && git config --global user.signingkey ~/.ssh/id_ed25519.pub`. Add the public key to GitHub as a *signing* key (not auth key). +- `/commit` always passes `-S`. If signing fails (key missing), commit fails — that's intentional. + +## Edge cases + +- **Pre-commit hook fails**: the husky `pre-commit` runs lint-staged. If it edits files, those edits aren't yet staged — re-stage and retry. Don't bypass with `--no-verify`. +- **commitlint rejects the message**: rewrite (don't `--no-verify`). Common rejections: subject too long, missing type, uppercase first letter. +- **Diff is too large for sane summarization**: ask the user to split into multiple commits. +- **Active issue is in a different repo than cwd**: warn, don't auto-add `Refs` for the wrong repo. + +## Integration + +- `post-commit.sh` PostToolUse hook captures the SHA on the active issue. +- `pr-check.yml` CI runs commitlint on every commit in the PR. +- `signed-commits.yml` CI rejects unsigned commits on PRs. + +## Example + +``` +$ git add scripts/hooks/auto-issue.sh + +$ /commit +Active issue: #9 (type/feat, area: hooks) + +Proposed message: + feat(hooks): wire UserPromptSubmit auto-issue hook + + Trigger only on work-regex prompts; cap 20 issues/day; resolve repo from + cwd via repositories.json. Writes .claude/state/active-issue.json so + branch/commit/pr/close skills can attribute the rest of the session. + + Refs #9 + + Co-Authored-By: Claude Opus 4.7 + +OK? [Y/n]: y + +$ git commit -S -m "..." +[feat/9-unified-git-github-workflow a11d313] feat(hooks): wire UserPromptSubmit auto-issue hook + 1 file changed, 124 insertions(+) + create mode 100755 scripts/hooks/auto-issue.sh +``` diff --git a/.claude/skills/issue/SKILL.md b/.claude/skills/issue/SKILL.md new file mode 100644 index 0000000..e2c48c2 --- /dev/null +++ b/.claude/skills/issue/SKILL.md @@ -0,0 +1,139 @@ +--- +name: issue +description: Create or resume a GitHub issue. Issues are the canonical memory channel — every task starts here, ends here, and can be paused/resumed by reading here. +--- + +# /issue + +Issues are the primary communication channel and the resumable memory of every task. The `/issue` skill creates, hydrates, and lists them. + +## Modes + +``` +/issue interactive — prompt for title/type/area/size, create +/issue one-shot — expand into a full issue, create +/issue resume load issue #N as the active context (the *resume* primitive) +/issue list table of open issues assigned to me across all databayt repos +/issue close close the active issue with a summary comment +``` + +## Active issue contract + +After any non-`list` mode, `/issue` writes `.claude/state/active-issue.json`: + +```json +{ + "repo": "databayt/", + "number": 42, + "title": "[Feat]: ...", + "url": "https://github.com/databayt//issues/42", + "branch": null, + "commits": [], + "pr_url": null, + "started_at": "2026-04-26T13:00:00Z" +} +``` + +This file is the session pointer. Hooks read it (`post-commit.sh`, `post-push.sh`, `session-end.sh`). Branch + commit + PR skills read it. Resume rehydrates from it. + +## /issue (interactive) + +1. Determine the target repo from cwd via `.claude/memory/repositories.json`. +2. Prompt the user for: type (feat | fix | chore | docs | report), title (≤ 65 chars, imperative), area (from the repo's `area-dropdowns.json`), size (1/2/3/5/8/13). +3. Compose the body using the matching `.github/ISSUE_TEMPLATE/-.yml` form: Description / Acceptance criteria checklist / Verification. +4. `gh issue create --repo "$REPO" --title "[$TYPE]: $TITLE" --body "$BODY" --label "type/$TYPE,priority/p2,status/triage"`. +5. Write `.claude/state/active-issue.json`. +6. Print the issue URL. + +## /issue \ + +Same as interactive, but type/area/size are inferred from ``: +- Type from regex (matches `auto-issue.sh`'s detection). +- Area defaults to first match in the repo's area dropdown, or `other`. +- Size defaults to `2`. + +The user can edit before confirming. + +## /issue resume \ + +The resume primitive — pick up exactly where the last session left off. + +1. `gh issue view --repo "$REPO" --json title,body,labels,assignees,state,comments` — full thread. +2. `gh pr list --search "linked:issue #" --repo "$REPO" --json number,url,state` — linked PRs. +3. Hydrate `.claude/state/active-issue.json`: + - `commits[]` — collect SHAs from every comment matching `**Commit \`\`**:` + - `pr_url` — first non-null linked PR + - `branch` — derive from `/-` if branch exists locally +4. Dump the entire issue thread + PR descriptions into the conversation as additional context. +5. Print: "Resumed #. commits made previously. PR: (state). Continue with /branch / /commit / /pr / /close." + +## /issue list + +```bash +gh search issues \ + --owner databayt \ + --assignee @me \ + --state open \ + --json repository,number,title,labels,updatedAt \ + --limit 30 +``` + +Group by `repository.name`, sort by `updatedAt` desc, format as a table: + +``` +databayt/kun + #9 [Feat]: unified git/github workflow + contribution-as-evidence layer status/in-progress 2026-04-26 + #1 [Chore]: configure API keys for 7 missing MCP servers status/triage 2026-04-15 + +databayt/hogwarts + #115 [QA]: King Fahad pilot — pre-launch checklist status/in-progress 2026-04-25 +``` + +## /issue close + +Close the active issue: + +1. Read `.claude/state/active-issue.json`. +2. If `pr_url` is set and PR is merged, comment with summary + PR link. +3. If PR is not merged, prompt for confirmation (might be wontfix/duplicate). +4. `gh issue close --comment "" --repo "$REPO"`. +5. Move `.claude/state/active-issue.json` → `.claude/state/history/issue--.json`. + +## Defaults + +- Repo resolution: `repositories.json` lookup by cwd. Fallback `databayt/kun`. +- Default labels: `type/`, `priority/p2`, `status/triage`. +- Default size: `2` (small, 1-2 hours). +- Title format: `[Type]: imperative-verb description ≤ 65 chars`. +- Body must include Acceptance criteria checklist + Verification. + +## Integration + +- `auto-issue.sh` UserPromptSubmit hook auto-creates issues for work-regex prompts. `/issue` is the explicit form. +- `/branch` requires an active issue; the branch name is `/-`. +- `/commit` references the active issue with `Refs #N`. +- `/pr` opens the PR with `Closes #N` and the Contribution declaration filled. +- `/close` closes the issue and clears active state. + +## Examples + +``` +/issue +> type: feat +> title: add dark mode toggle to docs site +> area: docs +> size: 3 +→ databayt/kun#42 created. https://github.com/databayt/kun/issues/42 + +/issue add OpenTelemetry tracing to auto-issue.sh +→ databayt/kun#43 created with type/feat, area: hooks, size: 2. + +/issue resume 9 +→ Loaded #9 (8 commits made previously, PR draft). Continue with /commit. + +/issue list +→ 12 open issues assigned to @abdout across 4 repos. + +/issue close +→ Closed databayt/kun#9 with summary referencing 11 commits + merged PR #99. +``` diff --git a/.claude/skills/pr/SKILL.md b/.claude/skills/pr/SKILL.md new file mode 100644 index 0000000..a57759f --- /dev/null +++ b/.claude/skills/pr/SKILL.md @@ -0,0 +1,123 @@ +--- +name: pr +description: Open a draft pull request linked to the active issue. PR body uses the template, fills the Contribution declaration block, applies labels. +--- + +# /pr + +Open a draft GitHub pull request from the current branch, with body filled from `.github/PULL_REQUEST_TEMPLATE.md`, `Closes #`, and the auto-filled Contribution declaration block. + +## Steps + +1. Read `.claude/state/active-issue.json` (`number`, `title`, `repo`, `branch`). +2. Verify branch is pushed: `git rev-parse @{u}` succeeds. If not, `git push -u origin `. +3. Pull `.github/PULL_REQUEST_TEMPLATE.md` content. +4. Fill template: + - `## Summary` — from the issue's description + this branch's commit subjects. + - `## Linked issue` — `Closes #` + - `## Test plan` — from the issue's Acceptance criteria checklist. + - `## Contribution declaration` block — see "Auto-fill rules" below. +5. `gh pr create --draft --title "(): " --body "$body" --label ""`. +6. Capture URL into `.claude/state/active-issue.json.pr_url`. +7. Print: "Draft PR opened: . Use /commit for more changes; mark ready when done; CI will run on push." + +## Auto-fill rules — Contribution declaration + +| Field | Source | +|------|--------| +| `Closes # (size: )` | active-issue + issue's Size custom field | +| `Author: @` | `git log` author of branch's first commit (or `gh api user`) | +| `Pair (50%): @ \| none` | leave as `none`; user edits if pairing | +| `Reviewers (10% each)` | leave blank; GitHub auto-lists when reviews land | +| `Design credit (20%): @ \| none` | scan issue body for `figma.com` or `RFC #N` link; else `none` | +| `AI co-author` | from the most-recent `Co-Authored-By:` trailer in branch commits; else `none` | + +## Title rules + +- Mirror the primary commit's type + scope: `feat(workflow): unified git/github workflow + contribution-as-evidence layer`. +- Strip the issue's `[Feat]:` prefix. +- ≤ 72 chars. +- No issue number in the title (it's in the body via `Closes #N`). + +## Labels + +Inherit from the issue, but transform: +- `status/in-progress` → drop (PR opening triggers `status/in-review` via auto-status.yml) +- `auto-created` → drop (only relevant for the issue itself) +- Keep `type/*`, `priority/*`, `area/*` + +`labeler.yml` will add additional `area/*` labels based on changed paths. + +## Draft vs ready + +`/pr` always opens **draft**. Mark ready with `gh pr ready` when: +- All commits land +- Local pre-flight passes (`pnpm typecheck && pnpm build`) +- `pnpm exec commitlint --from origin/main --to HEAD` passes +- Self-review of the diff complete + +Drafts skip required reviewers but still run CI. + +## CI gates + +After `/pr`, CI runs: +- `pr-check.yml` — typecheck/lint/test/build/commit-lint/branch-name/pr-body +- `signed-commits.yml` — every commit must be signed +- `contribution-declaration.yml` — declaration block parses, links a real issue +- `labeler.yml` — auto-applies area:* labels +- `auto-status.yml` — flips issue's status label to `status/in-review` + +## Edge cases + +- **No active issue**: refuse; suggest `/issue` first. (Every PR must close an issue — that's the contribution attribution chain.) +- **Branch is stacked on another open PR**: warn; pick base intentionally with `--base `. +- **PR already exists for branch**: print URL, refresh `.claude/state/active-issue.json.pr_url`, exit. + +## Integration + +- Reads `.github/PULL_REQUEST_TEMPLATE.md` (so any change to the template flows automatically). +- Writes `pr_url` back into active-issue.json. +- Triggers all CI workflows including `auto-status.yml` flipping labels. +- `post-push.sh` hook also captures PR URL after `git push`; `/pr` is the explicit form. + +## Example + +``` +$ /pr +Active issue: #9 [Feat]: unified git/github workflow + contribution-as-evidence layer +Branch: feat/9-unified-git-github-workflow (4 commits ahead of main, pushed) + +Title: feat(workflow): unified git/github workflow + contribution-as-evidence layer + +Body draft: + ## Summary + - Add 5 issue YAML forms + PR template + CODEOWNERS + labeler + dependabot + - Add 6 GitHub Actions workflows + - Wire commitlint + husky + lint-staged + - Wire 4 git/github automation hooks + - ... + + ## Linked issue + Closes #9 + + ## Test plan + - [ ] commitlint rejects "fix stuff" + - [ ] auto-issue.sh fires on a work prompt + - ... + + ## Contribution declaration + Closes #9 (size: 13) + - Author: @abdout + - Pair (50%): none + - Reviewers: _GitHub will list reviewers automatically_ + - Design credit (20%): none + - AI co-author: claude-opus-4-7 + +Labels: type/feat, priority/p1, area/workflow + +OK? [Y/n]: y + +→ Draft PR opened: https://github.com/databayt/kun/pull/10 +→ Updated .claude/state/active-issue.json.pr_url +→ CI will run on push. Use `gh pr checks --watch`. +``` diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..4a31a23 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,43 @@ +# CODEOWNERS — databayt/kun +# +# Default: founder reviews everything. Per-area entries narrow accountability +# without blocking the default. Order matters: later rules win. + +* @abdout + +# Engine — captain & decision matrix +/.claude/agents/captain.md @abdout +/.claude/captain/ @abdout +/.claude/memory/runway.json @abdout +/.claude/memory/captain-state.json @abdout +/.claude/memory/capacity.json @abdout + +# Workflow & GitHub config — touches every repo +/.github/ @abdout +/.husky/ @abdout +/commitlint.config.js @abdout +/.lintstagedrc.json @abdout + +# Cost & routing +/.claude/cost/ @abdout + +# Skills that touch git/github directly +/.claude/skills/issue/ @abdout +/.claude/skills/branch/ @abdout +/.claude/skills/commit/ @abdout +/.claude/skills/pr/ @abdout +/.claude/skills/close/ @abdout +/.claude/skills/report/ @abdout +/.claude/skills/dispatch/ @abdout + +# Hooks scripts +/scripts/hooks/ @abdout +/scripts/session-start.sh @abdout +/scripts/replicate-github-config.sh @abdout +/scripts/contribution-report.sh @abdout + +# Docs site (published) +/content/docs/ @abdout + +# Org-wide rules +/.claude/rules/ @abdout diff --git a/.github/ISSUE_TEMPLATE/1-feat.yml b/.github/ISSUE_TEMPLATE/1-feat.yml new file mode 100644 index 0000000..2743372 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1-feat.yml @@ -0,0 +1,92 @@ +name: Feature +description: Propose a new feature or enhancement +title: "[Feat]: " +labels: ["type/feat", "priority/p2", "status/triage"] +body: + - type: markdown + attributes: + value: | + Thanks for proposing a feature. This issue is the canonical record — every commit, PR, and review on this work links back here. Fill in enough that anyone (human or AI) can pick up the work cold. + + - type: textarea + id: description + attributes: + label: Description + description: What is the feature, and why does it matter? Include the user/system problem it solves. + placeholder: | + Currently the engine has no auto-issue creation hook, so prompts that should produce work-tracked items get lost. + We need a UserPromptSubmit hook that creates a GitHub issue and writes its number to .claude/state/active-issue.json. + validations: + required: true + + - type: textarea + id: acceptance + attributes: + label: Acceptance criteria + description: Markdown checklist. The PR is mergeable only when every box is checked. + value: | + - [ ] criterion 1 (specific, testable) + - [ ] criterion 2 + - [ ] verification step (command + expected output, or URL + expected screenshot) + validations: + required: true + + - type: dropdown + id: area + attributes: + label: Area + description: Which part of the engine does this touch? + options: + - agents + - skills + - rules + - hooks + - scripts + - memory + - mcp + - workflow + - docs + - other + validations: + required: true + + - type: dropdown + id: size + attributes: + label: Size estimate (story points) + description: Locked at status/ready. Drives Contribution Unit calculation in databayt/revenue. + options: + - "1 — trivial (single file, <30 min)" + - "2 — small (1-2 hours)" + - "3 — medium (half day)" + - "5 — large (full day)" + - "8 — heavy (multi-day, may need split)" + - "13 — epic (must split before status/ready)" + validations: + required: false + + - type: textarea + id: design + attributes: + label: Design notes + description: Sketch of approach, file names, data flow, alternatives. Keep it tight — the PR is the canonical implementation. + placeholder: Files to create / modify; key contracts; non-obvious tradeoffs. + + - type: textarea + id: linked + attributes: + label: Related + description: Other issues, PRs, or external docs this depends on or relates to. + placeholder: | + Refs # + Depends on # + + - type: checkboxes + id: ready + attributes: + label: Submission checklist + options: + - label: I read CLAUDE.md and CONTRIBUTING.md + required: true + - label: I searched existing issues — this is not a duplicate + required: true diff --git a/.github/ISSUE_TEMPLATE/2-fix.yml b/.github/ISSUE_TEMPLATE/2-fix.yml new file mode 100644 index 0000000..227c972 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-fix.yml @@ -0,0 +1,109 @@ +name: Fix +description: Report a bug or regression +title: "[Fix]: " +labels: ["type/fix", "priority/p2", "status/triage"] +body: + - type: markdown + attributes: + value: | + Thanks for reporting. The clearer the reproduction, the faster the fix. + + - type: textarea + id: description + attributes: + label: What's wrong + description: What happened? What did you expect? Include exact error messages if any. + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to reproduce + description: Numbered steps. Anyone reading this should be able to hit the bug. + placeholder: | + 1. Run `pnpm dev` + 2. Navigate to /ar/dashboard + 3. Click "Add student" + 4. Observe console error: ... + render: bash + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected vs actual + placeholder: | + Expected: form submits, redirects to /students/ + Actual: form throws "tenantId not set" + validations: + required: true + + - type: dropdown + id: severity + attributes: + label: Severity + options: + - "critical — data loss, app down, security" + - "high — major feature broken, no workaround" + - "medium — feature partially broken, workaround exists" + - "low — cosmetic, minor inconvenience" + validations: + required: true + + - type: dropdown + id: area + attributes: + label: Area + options: + - agents + - skills + - rules + - hooks + - scripts + - memory + - mcp + - workflow + - docs + - other + validations: + required: true + + - type: dropdown + id: size + attributes: + label: Size estimate (story points) + description: Time-to-fix estimate. Locked at status/ready. + options: + - "1 — trivial (typo, one-line)" + - "2 — small (clear root cause, isolated fix)" + - "3 — medium (some investigation needed)" + - "5 — large (multi-file fix, needs tests)" + - "8 — heavy (deep investigation)" + validations: + required: false + + - type: textarea + id: env + attributes: + label: Environment + placeholder: | + OS: macOS 14.5 + Node: 22.10.0 + pnpm: 9.12.0 + Browser: Chrome 130 + + - type: textarea + id: logs + attributes: + label: Logs / screenshots + description: Console output, network errors, screenshots. Drag and drop images. + + - type: checkboxes + id: ready + attributes: + label: Submission checklist + options: + - label: I searched existing issues — this is not a duplicate + required: true diff --git a/.github/ISSUE_TEMPLATE/3-chore.yml b/.github/ISSUE_TEMPLATE/3-chore.yml new file mode 100644 index 0000000..0f59050 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3-chore.yml @@ -0,0 +1,50 @@ +name: Chore +description: Maintenance, dependencies, infrastructure, cleanup +title: "[Chore]: " +labels: ["type/chore", "priority/p3", "status/triage"] +body: + - type: textarea + id: description + attributes: + label: What needs doing + description: The maintenance task and the reason it's needed. + placeholder: | + Bump @commitlint/cli from 19 to 20 — required for the new ESM config format. + validations: + required: true + + - type: dropdown + id: scope + attributes: + label: Scope + options: + - deps + - ci + - infra + - cleanup + - tooling + - other + validations: + required: true + + - type: textarea + id: acceptance + attributes: + label: Acceptance criteria + value: | + - [ ] criterion 1 + - [ ] verification (command + expected output) + validations: + required: true + + - type: dropdown + id: size + attributes: + label: Size estimate + options: + - "1 — trivial" + - "2 — small" + - "3 — medium" + - "5 — large" + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/4-docs.yml b/.github/ISSUE_TEMPLATE/4-docs.yml new file mode 100644 index 0000000..a527843 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/4-docs.yml @@ -0,0 +1,54 @@ +name: Docs +description: Fix or improve documentation +title: "[Docs]: " +labels: ["type/docs", "priority/p3", "status/triage"] +body: + - type: input + id: page + attributes: + label: Page or file + description: URL or repo path + placeholder: "https://kun.databayt.org/docs/keywords OR content/docs/keywords.mdx" + validations: + required: true + + - type: dropdown + id: kind + attributes: + label: Kind + options: + - incorrect information + - missing information + - typo / grammar + - broken link + - unclear / hard to follow + - code example broken + - other + validations: + required: true + + - type: textarea + id: description + attributes: + label: Description + description: What's wrong, what's missing, or what could be clearer. + validations: + required: true + + - type: textarea + id: suggested + attributes: + label: Suggested fix + description: Optional — propose the wording or example you'd add. + + - type: dropdown + id: size + attributes: + label: Size estimate + options: + - "1 — trivial (typo, one-line)" + - "2 — small (paragraph rewrite)" + - "3 — medium (section rewrite)" + - "5 — large (new doc page)" + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/5-report.yml b/.github/ISSUE_TEMPLATE/5-report.yml new file mode 100644 index 0000000..7ea02e2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/5-report.yml @@ -0,0 +1,75 @@ +name: Report (in-product) +description: Issue auto-filed by the in-product Report dialog. End users — please use the dialog instead. +title: "[Report]: " +labels: ["type/report", "priority/p1", "status/triage"] +body: + - type: markdown + attributes: + value: | + > This template exists to receive automated reports from the in-product **Report an Issue** dialog. The `/report` skill processes issues with the `type/report` label and auto-fixes the smaller ones. + > + > End users: please use the in-product dialog. Maintainers: use this form only when you're manually replicating a report. + + - type: input + id: page + attributes: + label: Page URL + placeholder: https://kingfahad.databayt.org/dashboard/students + validations: + required: true + + - type: textarea + id: what-happened + attributes: + label: What happened + description: User's description of the problem. + validations: + required: true + + - type: textarea + id: expected + attributes: + label: What was expected + validations: + required: false + + - type: input + id: time + attributes: + label: Time observed (ISO) + placeholder: 2026-04-26T14:23:00Z + validations: + required: false + + - type: input + id: browser + attributes: + label: Browser + placeholder: "Chrome 130 / Safari 18 / Firefox 131" + + - type: input + id: os + attributes: + label: Operating system + placeholder: "macOS 14.5 / Windows 11 / iOS 18" + + - type: dropdown + id: role + attributes: + label: Role + options: + - student + - teacher + - parent + - admin + - school-owner + - public + - other + validations: + required: false + + - type: textarea + id: screenshots + attributes: + label: Screenshots / video + description: Drag and drop. Helps verify the bug. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 0086358..d5e8596 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1 +1,11 @@ -blank_issues_enabled: true +blank_issues_enabled: false +contact_links: + - name: Discussion / question + url: https://github.com/databayt/kun/discussions + about: Open-ended questions, ideas, RFCs go in Discussions — not Issues. + - name: Slack #dev + url: https://hogwarts-wve9301.slack.com + about: Real-time chat for the databayt team. Issues remain the canonical record. + - name: Documentation + url: https://kun.databayt.org/docs + about: Read the docs first — most "how do I…" answers live there. diff --git a/.github/ISSUE_TEMPLATE/docs.yml b/.github/ISSUE_TEMPLATE/docs.yml deleted file mode 100644 index 860c9dc..0000000 --- a/.github/ISSUE_TEMPLATE/docs.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Documentation -description: Report an issue or suggest an improvement to the documentation -labels: ["documentation"] -body: - - type: input - id: page-url - attributes: - label: Page URL - description: Which documentation page has the issue? - placeholder: /docs/agents - validations: - required: true - - - type: dropdown - id: type - attributes: - label: Issue type - options: - - Incorrect information - - Missing information - - Typo or grammar - - Broken link - - Unclear explanation - - Code example doesn't work - - Other - validations: - required: true - - - type: textarea - id: description - attributes: - label: Description - description: What's wrong or could be improved? - validations: - required: true - - - type: textarea - id: suggestion - attributes: - label: Suggested fix - description: If you know what the correction should be - validations: - required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..5e68a36 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,67 @@ + + +## Summary + + + +- +- + +## Linked issue + +Closes # + + + +## Test plan + + + +- [ ] +- [ ] + +## Screenshots + + + +| Before | After | +| ------ | ----- | +| | | + +## Checklist + +- [ ] I read CLAUDE.md and CONTRIBUTING.md +- [ ] Branch name follows `/-` (e.g. `feat/9-unified-workflow`) +- [ ] Every commit follows Conventional Commits — `pnpm exec commitlint --from origin/main --to HEAD` passes +- [ ] Every commit is signed (`git log --show-signature -1` shows `gpg/ssh: Good`) +- [ ] `pnpm typecheck` passes +- [ ] `pnpm lint` passes +- [ ] `pnpm test` passes (if applicable) +- [ ] `pnpm build` passes +- [ ] No secrets, API keys, or credentials in the diff +- [ ] CLA acknowledged (SSPL-1.0 + commercial license grant — see CONTRIBUTING.md) + +## Contribution declaration + + + +Closes # (size: ) + +- Author: @ +- Pair (50% of size): @ | none +- Reviewers (10% each, max 3): _GitHub will list reviewers automatically_ +- Design credit (20% of size): @ | none — link: +- AI co-author: claude-opus-4-7 | claude-sonnet-4 | none + +By opening this PR I confirm the credits above are accurate. False declarations +forfeit Contribution Units for this PR and reduce the contributor's monthly cap by 25%. +See `databayt/revenue/RULES.md` for the CU model. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..2454ebc --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,63 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "09:00" + timezone: "Africa/Khartoum" + open-pull-requests-limit: 5 + reviewers: + - "abdout" + labels: + - "type/chore" + - "area: deps" + - "priority/p3" + commit-message: + prefix: "chore(deps)" + include: "scope" + groups: + development: + patterns: + - "@types/*" + - "eslint*" + - "@typescript-eslint/*" + - "prettier*" + - "vitest*" + - "@vitest/*" + next-core: + patterns: + - "next" + - "react" + - "react-dom" + update-types: + - "minor" + - "patch" + fumadocs: + patterns: + - "fumadocs-*" + anthropic: + patterns: + - "@anthropic-ai/*" + ignore: + - dependency-name: "next" + update-types: ["version-update:semver-major"] + - dependency-name: "react" + update-types: ["version-update:semver-major"] + - dependency-name: "react-dom" + update-types: ["version-update:semver-major"] + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + reviewers: + - "abdout" + labels: + - "type/chore" + - "area: workflow" + - "priority/p3" + commit-message: + prefix: "chore(ci)" diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..a7d0202 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,63 @@ +# actions/labeler@v5 config — auto-applies area:* labels by file path on PR open/sync. +# Format: