From 26ab426410135aa5da0dd4cd6f3a611b65a3b385 Mon Sep 17 00:00:00 2001 From: zawakin Date: Sun, 8 Feb 2026 12:20:43 +0900 Subject: [PATCH] chore: add mise tasks, update git-workflow skill, and rewrite CLAUDE.md Co-Authored-By: Claude Opus 4.6 --- .claude/skills/git-workflow/SKILL.md | 288 ++++++++++++++------------- AGENTS.md | 132 +----------- CLAUDE.md | 144 +++++++++++++- mise.toml | 2 + tasks.toml | 184 +++++++++++++++++ 5 files changed, 478 insertions(+), 272 deletions(-) mode change 100644 => 120000 AGENTS.md mode change 120000 => 100644 CLAUDE.md create mode 100644 mise.toml create mode 100644 tasks.toml diff --git a/.claude/skills/git-workflow/SKILL.md b/.claude/skills/git-workflow/SKILL.md index 7d487977..387faf5d 100644 --- a/.claude/skills/git-workflow/SKILL.md +++ b/.claude/skills/git-workflow/SKILL.md @@ -5,210 +5,218 @@ description: Git workflow standards - branch management, commit conventions, and # Git Workflow and Conventions -Standard Git workflow including branching strategy, commit message format, and pull request creation. +Worktree-aware Git workflow using `mise run git:*` tasks. -## Quick Start Workflow +## Quick Reference ```sh -# Step 1: Setup -git fetch --prune +# Basic operations +mise run git:status # Show current state + next action +mise run git:home # Switch to home branch + sync with origin/main +mise run git:new # Create new branch from origin/main +mise run git:cleanup [branch] # Delete merged branch + return to home + +# PR lifecycle (CI wait -> browser open -> merge watch -> cleanup) +mise run git:open-pr # All-in-one: CI -> open -> watch -> cleanup + +# Pause / discard / undo +mise run git:pause [message] # WIP commit + return to home (for switching tasks) +mise run git:abandon # Discard all changes + return to home +mise run git:undo # Soft reset HEAD~1 (undo last commit) + +# Stacked PRs +mise run git:sync # Sync current branch after base PR merge +``` + +> **Note**: These tasks use the `gw` Rust CLI ([crates.io](https://crates.io/crates/git-workflow)). Install with `cargo install git-workflow`. -# Step 2: Create feature branch -git switch -c feature/your-branch-name origin/main +> **Pitfalls** +> - **Do not run `git checkout main`** — use `mise run git:home` instead (worktree conflict) +> - **Do not use `git stash`** — use `mise run git:pause` instead (creates WIP commit for safer worktree switching) +> - **Do not manually rebase stacked PRs** — use `mise run git:sync` instead (updates GitHub PR base + rebases) -# Step 3: Make changes and commit -git add [] -git commit -m "[commit message]" -git push --set-upstream origin feature/your-branch-name +## Standard Workflow: Code -> PR -# Step 4: Create Pull Request -gh pr create -a "@me" -t "[title]" +**Every code change should become a PR.** Follow this flow: -# Step 5: Check CI Status -gh pr checks --watch +``` +1. Branch -> mise run git:new -- feature/your-feature +2. Code -> make changes +3. Commit -> git add -A && git commit -m "feat: ..." +4. Push -> git push -u origin feature/your-feature +5. PR -> gh pr create -a "@me" -t "feat: ..." +6. Open -> mise run git:open-pr (CI wait -> browser -> merge watch -> cleanup) +7. Cleanup -> (auto: merge detected -> git:cleanup runs) +``` -# Step 6: Open PR in browser for review -gh pr view --web +### git:open-pr — PR Lifecycle Management (Claude Code Background Task) -# Step 7: After merging, clean up branches -# Standard: -git switch main && git pull -git branch -d -# Worktree (when main is used elsewhere): -git switch && git pull origin main -git branch -d +After creating a PR, run in background: + +``` +Claude: [Bash(run_in_background=true)] mise run git:open-pr -- ``` -## Branching Strategy +3 phases run automatically: +1. **CI wait** — `gh pr checks --watch` waits for CI to pass +2. **Open in browser** — Opens PR page in default browser +3. **Merge watch** — Polls PR state every 30s + - MERGED -> macOS notification + `mise run git:cleanup` -> exit + - CLOSED -> message -> exit + +**Claude behavior**: When background task output arrives via ``, Claude MUST: +1. Read the output file with `TaskOutput` or `Read` +2. Report the result to the user immediately +3. Show key information: merged/closed status, cleanup success/failure -### Always Branch from `origin/main` +**Run `mise run git:status` at any point to see what to do next.** -Create all feature branches from the latest `origin/main`: +### If you have uncommitted changes on home branch + +This happens when you made changes before creating a branch. Fix it: ```sh -git fetch --prune -git switch -c feature/your-branch-name origin/main +# 1. Create branch (keeps your changes) +mise run git:new -- feature/your-feature + +# 2. Now follow git:status +mise run git:status +# -> Will suggest: commit, push, create PR ``` -### Git Worktree Support +## Proactive Workflow -When working in a git worktree (e.g., `wt-2` directory), the `main` branch is used by another worktree and cannot be checked out directly. In this case: +**Always run `mise run git:status` and follow the "Next:" action.** -1. **The directory name (e.g., `wt-2`) acts as the local main branch equivalent** -2. **Always branch from `origin/main`** (not local main) -3. **After merge, update with**: `git pull origin main` (instead of `git switch main && git pull`) +The status command automatically detects: +- Working directory state (clean/uncommitted changes) +- Sync state with upstream (pushed/unpushed/behind) +- PR state (none/open/merged/closed) -```sh -# In worktree environment - post-merge cleanup: -git switch # e.g., wt-2 -git pull origin main -git branch -d -``` +And suggests the appropriate next action: -### Branch Naming Convention +| Status Output | Action | +|--------------|--------| +| `Next: start new work` | `mise run git:new -- feature/...` | +| `Next: commit changes` | `git add -A && git commit -m "..."` | +| `Next: push to remote` | `git push -u origin ` | +| `Next: create pull request` | `gh pr create -a "@me" -t "..."` | +| `Waiting: PR #N in review` | Wait for CI/review, or start parallel work | +| `Next: cleanup merged branch` | `mise run git:cleanup` | +| `Next: rebase on latest main` | `git fetch && git rebase origin/main` | +| `Next: sync (base 'X' was merged)` | `mise run git:sync` | + +## Branch Naming Convention - `feature/` - New features - `fix/` - Bug fixes +- `chore/` - Maintenance tasks - `docs/` - Documentation updates - `refactor/` - Code refactoring - `test/` - Test additions or fixes ## Commit Message Format -Use Conventional Commits format: +Use Conventional Commits (one-line only): ``` [optional scope]: - -[optional body] - -[optional footer] ``` -### Commit Types +### Types -- **fix**: Patches a bug in your codebase -- **feat**: Introduces a new feature to the codebase -- **chore**: Maintenance tasks (dependencies, configs, etc.) +- **feat**: New feature +- **fix**: Bug fix +- **chore**: Maintenance tasks - **docs**: Documentation changes -- **style**: Code style changes (formatting, white-space, etc.) -- **refactor**: Code refactoring without changing functionality +- **refactor**: Code refactoring - **perf**: Performance improvements - **test**: Adding or modifying tests -### Commit Examples - -**No body**: +### Examples ``` -docs: correct spelling of CHANGELOG +feat(providers): add Gemini log parser +fix: correct token count in session summary +chore: bump version to 0.8.0 ``` -**With scope**: - -``` -feat(api): add user authentication endpoint -``` +## PR Standards -**With body and footer**: +- **Language**: English +- **Title**: Descriptive. Use commit message if single commit +- **Body**: Explain changes and context +- **Size**: Keep PRs small and focused -``` -fix: correct minor typos in code +## About Worktrees -see the issue for details on the typos fixed +This project uses git worktree. Each worktree has a **home branch**. -closes issue #12 -``` +- Home branch = directory name (e.g., `agtrace-2/` -> `agtrace-2` branch) +- Never checkout `main` directly (used by another worktree) +- Always branch from `origin/main` -## Pull Request Creation +The `mise run git:*` tasks handle this automatically. -### PR Standards +## Workflow: Stacked PRs -- **Language**: English -- **Title**: Descriptive of changes. Use commit message if branch has 1 commit -- **Body**: Explain changes, why they were made, and any relevant context -- **Keep PRs small and focused**: Easy to review and test -- **Keep PR Body up to date**: Reflect current state of changes +When working on features that depend on unmerged work: -### Create PR with GitHub CLI +### Creating Stacked PRs ```sh -# Basic PR creation -gh pr create -a "@me" -t "[title]" - -# Wait for CI checks to complete -gh pr checks --watch - -# Open in browser for review -gh pr view --web +# 1. Create base PR (depends on main) +mise run git:new -- feature/base +# ... commit, push, create PR ... + +# 2. Create child PR (depends on base) +git checkout feature/base +git checkout -b feature/child +# ... commit, push ... +gh pr create --base feature/base -t "feat: child feature" ``` -## Post-Merge Cleanup +### After Base is Merged -After PR is merged: +When the base PR is merged, `gw status` will detect this and suggest syncing: -```sh -# Standard environment: -git switch main -git pull -git branch -d - -# Git worktree environment (when main is used by another worktree): -git switch # e.g., wt-2 -git pull origin main -git branch -d ``` +Base PR: #123 [MERGED] +-> Next: sync (base 'feature/base' was merged) -## Workflow: Incidental Refactoring (Yak Shaving Protocol) + mise run git:sync +``` -When you identify necessary refactoring while working on a feature branch (but it's outside the scope or too large): +Run `mise run git:sync` to: +1. Update child PR's base to `main` +2. Rebase child branch on `origin/main` +3. Force push the updated branch -**Do not mix refactoring into the feature branch.** Use a Draft PR as your "base camp" to avoid getting lost in Yak Shaving. +**Do not manually `git rebase`** — always use `git:sync` to keep GitHub PR base and local branch in sync. -### Why Draft PR as Base Camp? +## Workflow: Incidental Refactoring (Yak Shaving Protocol) -- **Outsource memory to GitHub**: Free your brain's stack by writing down what you're doing -- **Always have a way back**: No matter how deep the refactoring rabbit hole, your Draft PR anchors you -- **Terminal-first**: Use `gh` commands to stay focused without browser context-switching +When you discover necessary refactoring during feature work, **don't mix it into the feature branch**. ### The Flow -1. **Anchor the Context (Don't forget why!)**: - Before leaving, ensure a Draft PR exists for your current feature and document what you were doing. - ```sh - # If PR doesn't exist yet, create a Draft PR as a notepad - gh pr create --draft -a "@me" -t "WIP: [Current Feature]" -b "- [ ] Implement X (Paused for refactoring Y)" - - # If PR exists, add a comment about the distraction - gh pr comment --body "Paused to refactor [Component Y]. Will resume after merging that." - ``` - -2. **Stash current changes**: - ```sh - git stash -u -m "Paused: [Current Feature] - waiting for refactor" - ``` - -3. **Create & Ship Refactor** (works in both standard and worktree environments): - ```sh - git fetch --prune - git switch -c refactor/descriptive-name origin/main - # ... Implementation ... - git push --set-upstream origin refactor/descriptive-name - gh pr create -a "@me" -t "refactor: [description]" - ``` - -4. **Resume Feature Work**: - ```sh - git switch feature/original-branch - # Option A: Rebase onto the refactor branch to use it immediately - git rebase refactor/descriptive-name - # Option B: Wait for merge, then rebase on main - # git fetch --prune && git rebase origin/main - git stash pop - ``` - -5. **Review the Anchor**: - Check your Draft PR to remember the original goal. - ```sh - gh pr view --web - ``` +1. **Pause current work** (WIP commit + return to home): + ```sh + mise run git:pause -- "waiting for refactor Y" + # Creates WIP commit, comments on PR if exists, switches to home + ``` + +2. **Create & ship the refactor**: + ```sh + mise run git:new -- refactor/descriptive-name + # ... implement the fix ... + mise run git:status # Follow the "Next:" action + # ... commit, push, PR, merge, cleanup ... + ``` + +3. **Resume feature work**: + ```sh + git checkout feature/original-branch + mise run git:undo # Undo the WIP commit (changes return to staged area) + mise run git:status # Continue from where you left off + ``` diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index fb6ad92c..00000000 --- a/AGENTS.md +++ /dev/null @@ -1,131 +0,0 @@ -## Project Summary - -Based on the codebase analysis, here are the project goals and non-goals for agtrace: - -### Project Goals - -* Universal Normalization: Unify diverse agent log formats (Claude, Codex, Gemini) into a standardized, type-safe `AgentEvent` timeline for consistent analysis. -* Fail-Safe Observability: Employ a "Schema-on-Read" architecture where raw logs are the source of truth, ensuring parsing errors or schema updates never cause data loss. -* Zero-Copy Indexing: maintain a lightweight SQLite pointer index that references original log files rather than duplicating content, minimizing storage bloat. -* Deep Diagnostics: Provide high-fidelity debugging tools (`doctor`, `lab`, `watch`) to inspect raw payloads, token usage, and complex reasoning chains without abstraction layers hiding details. -* Project Isolation: Enforce strict, hash-based project separation to ensure reliable session grouping across different providers' filesystem conventions. - -### Non-Goals - -* Real-Time Interception: It is not a proxy or middleware that sits between the user and the agent; it analyzes logs post-write (or via tailing). -* Schema-on-Write: It deliberately avoids normalizing data at ingestion time to prevent "baking in" parsing logic that might become obsolete. -* Hierarchical Organization: It does not support nested project structures (e.g., parent/child directories), opting for flat, exact-match isolation to avoid inconsistency. -* Centralized Storage: It does not aim to be a monolithic data store; the database is disposable and rebuildable from the raw log files at any time. - -## Project Rules - -- Keep minimal comments and documents. -- Write comments in English. -- Read `docs`. -- When you make a commit, the commit message must be oneline not multiline. -- Rather than rushing to complete tasks, please focus on a quality-driven approach: reviewing implementations, running lint and fmt checks, and committing with concise, one-line messages (messages like "Claude's co-author" are unnecessary—keep them one-line). -- Rules for snapshot tests: After running `cargo insta accept`, use `git diff` to check the differences. If there are issues, fix the implementation. If there are no issues, include it in the same commit as the implementation. -- Use `tree2md` command for full file tree. -- Design principle: Always choose the complete, unified solution over partial fixes. Never offer half-measures like "delete unused code" or "suppress warnings" without fixing the root cause. When facing implementation choices, default to the option that improves consistency and type safety across the codebase. -- Leave a TODO when you are consciously deferring a specific, necessary action due to immediate constraints like scope or dependencies. -- When investigating actual event/tool structures: Run `cargo build --release && ./target/release/agtrace lab grep "pattern" --json --limit 5` to see real data instead of reading raw files. `./target/release/agtrace lab grep -h` helps to learn how to use it. -- Use `git-workflow` skill in dev. - -### Test-Driven Bug Fixes - -When fixing bugs, ensure tests actually validate the fix: - -**Core Principle**: Tests should fail before the fix and pass after the fix. - -**Recommended Approach**: -1. Write a test that reproduces the bug (should fail on current main) -2. Verify the test actually fails without your fix -3. Implement the fix -4. Verify the test now passes - -**Commit Strategy** (choose based on context): -- **Separate commits** (preferred for complex bugs): - - First commit: `test: add failing test for issue #N (documents bug behavior)` - - Second commit: `fix: resolve issue #N (description)` - - Keep both commits in the same PR for easier review -- **Single commit** (acceptable for simple fixes): - - Include both test and fix in one commit - - Ensure test would fail without the fix - -**Verification**: -- Before finalizing: Temporarily revert your implementation changes and confirm tests fail -- This proves your test actually validates the fix -- If tests pass without your fix, the test isn't testing the right thing - -**Anti-patterns to avoid**: -- Writing tests that always pass (even before the fix) -- Implementing fix without any test coverage -- Tests that check indirect effects instead of the actual bug - -**Example** (issue #5): -- Test commit: Documents that `init` reports `session_count: 0` before indexing (current bug) -- Fix commit: Modifies `InitService::run()` to index before counting + updates test to assert `session_count: 1` - -## Overview of agtrace - -A Rust Workspace following layered architecture: CLI → SDK → Runtime → (Engine + Index + Providers) → (Core + Types). - -### Crate Architecture & Design Principles - -**1. Foundation Layer** - -* `agtrace-types` (`crates/agtrace-types/`) - - **Principle**: Minimal logic. Only stable type definitions and schemas that rarely change. - - Dependencies: None - -* `agtrace-core` (`crates/agtrace-core/`) - - **Principle**: Handles file paths, environment variables, and workspace utilities. - - Dependencies: `types` - -* `agtrace-testing` (`crates/agtrace-testing/`) - - **Principle**: Shared test utilities for `sdk` and `cli`. - - Dependencies: Internal crates as needed - -**2. Data Layer** - -* `agtrace-engine` (`crates/agtrace-engine/`) - - **Principle**: Provider-agnostic and environment-agnostic domain logic accumulation. - - Dependencies: `types` only - -* `agtrace-providers` (`crates/agtrace-providers/`) - - **Principle**: Aggregates all provider-specific implementations (`claude/`, `codex/`, `gemini/`). - - Dependencies: `types`, `core` - -* `agtrace-index` (`crates/agtrace-index/`) - - **Principle**: Provider-agnostic. Handles only local SQLite DB operations (zero-copy, pointer-based). - - Dependencies: `types` - -**3. Orchestration Layer** - -* `agtrace-runtime` (`crates/agtrace-runtime/`) - - **Principle**: Orchestrates `engine`, `index`, and `providers` without business logic. - - Dependencies: `types`, `core`, `providers`, `index`, `engine` - -**4. Public API Layer** - -* `agtrace-sdk` (`crates/agtrace-sdk/`) - - **Principle**: Public SDK for external observability tools. - - Dependencies: All internal crates - -**5. Presentation Layer** - -* `agtrace-cli` (`crates/agtrace-cli/`) - - **Principle**: Depends only on `sdk`. Acts as a sophisticated example of SDK usage. - - Dependencies: `sdk` only - -### Dependency Rules - -`types` has no internal dependencies. `core`, `index`, and `engine` depend only on `types`. `providers` depends on `types` and `core`. `runtime` orchestrates all data layer crates (`engine`, `index`, `providers`) plus `types` and `core`. `sdk` wraps all internal crates. `cli` depends only on `sdk`. - -### Data Flow - -1. **Read**: `providers` discover and read raw log files -2. **Normalize**: Convert to `AgentEvent` (Schema-on-Read) -3. **Index**: `index` stores metadata pointers in SQLite -4. **Analyze**: `engine` reconstructs sessions, calculates tokens -5. **Present**: `cli` renders via TUI or JSON diff --git a/AGENTS.md b/AGENTS.md new file mode 120000 index 00000000..681311eb --- /dev/null +++ b/AGENTS.md @@ -0,0 +1 @@ +CLAUDE.md \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 120000 index 47dc3e3d..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -AGENTS.md \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..04fe62e8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,143 @@ +# CLAUDE.md + +This file provides guidance for Claude Code when working in this repository. + +## Required + +- **Always load `/git-workflow` first** regardless of the conversation topic (before any other task) +- Before starting work -> `mise tasks` to see available tasks +- All commands MUST be run via `mise run` (works from any directory) +- Prefer root-cause fixes over shortcuts (step back, reflect, take the senior engineer approach) +- **All changes go through PRs via `/git-workflow`** (never commit directly to main) +- Commit messages must be one-line, Conventional Commits format +- Write everything in English (OSS project) + +## Project Overview + +Rust-based local-first observability platform for AI agents. Normalizes diverse agent log formats (Claude Code, Codex, Gemini) into a unified `AgentEvent` timeline. + +``` +./ +├── crates/ +│ ├── agtrace-types/ # Type definitions (no deps) +│ ├── agtrace-core/ # File paths, env, workspace utils +│ ├── agtrace-providers/ # Log parsers (claude/, codex/, gemini/) +│ ├── agtrace-index/ # SQLite pointer index +│ ├── agtrace-engine/ # Session assembly, token calc +│ ├── agtrace-runtime/ # Orchestration layer +│ ├── agtrace-sdk/ # Public SDK +│ ├── agtrace-cli/ # CLI (depends on sdk only) +│ └── agtrace-testing/ # Shared test utilities +└── docs/ # Design documents +``` + +## Quick Reference + +```bash +mise run verify # fmt + clippy + test + build (full check) +mise run test # run all tests +mise run clippy # lint +mise run fmt # format code +mise run build:release # release build +mise run git:status # git workflow state + next action +mise tasks # list all tasks +``` + +## Skills + +Detailed knowledge is separated into `.claude/skills/`. Loaded automatically or manually via `/skill-name`. + +| Skill | Purpose | +|-------|---------| +| `/git-workflow` | Git workflow, branch management, PR creation | +| `/agtrace-provider-normalization` | Provider schema investigation and domain abstraction | +| `/execplan` | Execution plan creation for complex features | +| `/skill-creator` | Meta-skill for creating new skills | + +**Usage**: Type `/skill-name` in conversation, or auto-loaded when relevant. + +## Project Rules + +- Snapshot tests: `mise run snapshot:accept` to accept and review diff, then include in the same commit +- Bug fixes: write a test that fails before the fix and passes after +- Investigate event structures: `mise run lab:grep -- "pattern" --json --limit 5` + +## Architecture + +Layered architecture: CLI -> SDK -> Runtime -> (Engine + Index + Providers) -> (Core + Types). + +**Dependency rules**: `types` has no internal deps. `core`, `index`, `engine` depend on `types` only. `providers` depends on `types` + `core`. `runtime` orchestrates all data layer crates. `sdk` wraps all. `cli` depends on `sdk` only. + +**Data flow**: providers read raw logs -> normalize to `AgentEvent` -> index stores pointers in SQLite -> engine reconstructs sessions -> cli renders via TUI or JSON. + +# CLAUDE.md + +This file provides guidance for Claude Code when working in this repository. + +## Required + +- **Always load `/git-workflow` first** regardless of the conversation topic (before any other task) +- Before starting work -> `mise tasks` to see available tasks +- All commands MUST be run via `mise run` (works from any directory) +- Prefer root-cause fixes over shortcuts (step back, reflect, take the senior engineer approach) +- **All changes go through PRs via `/git-workflow`** (never commit directly to main) +- Commit messages must be one-line, Conventional Commits format +- Write everything in English (OSS project) + +## Project Overview + +Rust-based local-first observability platform for AI agents. Normalizes diverse agent log formats (Claude Code, Codex, Gemini) into a unified `AgentEvent` timeline. + +``` +./ +├── crates/ +│ ├── agtrace-types/ # Type definitions (no deps) +│ ├── agtrace-core/ # File paths, env, workspace utils +│ ├── agtrace-providers/ # Log parsers (claude/, codex/, gemini/) +│ ├── agtrace-index/ # SQLite pointer index +│ ├── agtrace-engine/ # Session assembly, token calc +│ ├── agtrace-runtime/ # Orchestration layer +│ ├── agtrace-sdk/ # Public SDK +│ ├── agtrace-cli/ # CLI (depends on sdk only) +│ └── agtrace-testing/ # Shared test utilities +└── docs/ # Design documents +``` + +## Quick Reference + +```bash +mise run verify # fmt + clippy + test + build (full check) +mise run test # run all tests +mise run clippy # lint +mise run fmt # format code +mise run build:release # release build +mise run git:status # git workflow state + next action +mise tasks # list all tasks +``` + +## Skills + +Detailed knowledge is separated into `.claude/skills/`. Loaded automatically or manually via `/skill-name`. + +| Skill | Purpose | +|-------|---------| +| `/git-workflow` | Git workflow, branch management, PR creation | +| `/agtrace-provider-normalization` | Provider schema investigation and domain abstraction | +| `/execplan` | Execution plan creation for complex features | +| `/skill-creator` | Meta-skill for creating new skills | + +**Usage**: Type `/skill-name` in conversation, or auto-loaded when relevant. + +## Project Rules + +- Snapshot tests: `mise run snapshot:accept` to accept and review diff, then include in the same commit +- Bug fixes: write a test that fails before the fix and passes after +- Investigate event structures: `mise run lab:grep -- "pattern" --json --limit 5` + +## Architecture + +Layered architecture: CLI -> SDK -> Runtime -> (Engine + Index + Providers) -> (Core + Types). + +**Dependency rules**: `types` has no internal deps. `core`, `index`, `engine` depend on `types` only. `providers` depends on `types` + `core`. `runtime` orchestrates all data layer crates. `sdk` wraps all. `cli` depends on `sdk` only. + +**Data flow**: providers read raw logs -> normalize to `AgentEvent` -> index stores pointers in SQLite -> engine reconstructs sessions -> cli renders via TUI or JSON. diff --git a/mise.toml b/mise.toml new file mode 100644 index 00000000..ae14fec2 --- /dev/null +++ b/mise.toml @@ -0,0 +1,2 @@ +[task_config] +includes = ["tasks.toml"] diff --git a/tasks.toml b/tasks.toml new file mode 100644 index 00000000..3b16efc4 --- /dev/null +++ b/tasks.toml @@ -0,0 +1,184 @@ +# tasks.toml +# Core project tasks - run with `mise run ` + +# --- Cargo --- + +[build] +description = "Build the project (debug)" +run = "cargo build" + +["build:release"] +description = "Build the project (release)" +run = "cargo build --release" + +[test] +description = "Run all tests" +run = "cargo test --workspace" + +[fmt] +description = "Format code" +run = "cargo fmt" + +["fmt:check"] +description = "Check formatting" +run = "cargo fmt --check" + +[clippy] +description = "Run clippy linter" +run = "cargo clippy --workspace -- -D warnings" + +[verify] +description = "Run all checks (fmt + clippy + test + build)" +run = "cargo fmt --check && cargo clippy --workspace -- -D warnings && cargo test --workspace && cargo build --release" + +["snapshot:accept"] +description = "Accept snapshot changes and show diff" +run = "cargo insta accept && git diff" + +# --- Lab --- + +["lab:grep"] +description = "Search real event data (mise run lab:grep -- 'pattern' --json --limit 5)" +run = "cargo run --release -- lab grep" + +# --- Release --- +# +# See `.claude/commands/release.md` for full release procedure. + +["release:dry-run"] +description = "Dry-run release (mise run release:dry-run -- patch|minor|major)" +run = "cargo release --workspace --no-verify" + +["release:execute"] +description = "Execute release (mise run release:execute -- patch|minor|major)" +run = "cargo release --workspace --execute" + +["release:changelog"] +description = "Generate CHANGELOG for next release (mise run release:changelog -- patch|minor|major)" +run = """ +#!/bin/bash +set -euo pipefail +RELEASE_LEVEL="${1:?Usage: mise run release:changelog -- patch|minor|major}" +LAST_TAG=$(git describe --tags --abbrev=0) +CURRENT_VERSION=${LAST_TAG#v} +IFS='.' read -r major minor patch <<< "$CURRENT_VERSION" +case "$RELEASE_LEVEL" in + major) NEXT_VERSION="$((major + 1)).0.0" ;; + minor) NEXT_VERSION="${major}.$((minor + 1)).0" ;; + patch) NEXT_VERSION="${major}.${minor}.$((patch + 1))" ;; + *) echo "Invalid release level: $RELEASE_LEVEL" >&2; exit 1 ;; +esac +echo "Current: $CURRENT_VERSION -> Next: $NEXT_VERSION" +git cliff ${LAST_TAG}..HEAD --unreleased --tag v${NEXT_VERSION} --prepend CHANGELOG.md +echo "CHANGELOG.md updated. Review and commit." +""" + +# --- Git Workflow (using gw CLI) --- +# +# Worktree-aware git workflow. +# Do not use `git checkout main` — use `mise run git:home` instead. +# +# gw: cargo install git-workflow +# https://crates.io/crates/git-workflow + +["git:home"] +description = "Switch to home branch and sync with origin/main" +run = "gw home" + +["git:new"] +description = "Create new branch from origin/main (mise run git:new -- feature/name)" +run = "gw new" + +["git:cleanup"] +description = "Delete merged branch and return to home (mise run git:cleanup -- [branch])" +run = "gw cleanup" + +["git:status"] +description = "Show current git workflow state" +run = "gw status" + +["git:pause"] +description = "Pause work: WIP commit + return to home (mise run git:pause -- [message])" +run = "gw pause" + +["git:abandon"] +description = "Abandon changes and return to home" +run = "gw abandon" + +["git:undo"] +description = "Undo last commit (soft reset HEAD~1)" +run = "gw undo" + +["git:sync"] +description = "Sync current branch after base PR merge (update base to main, rebase, push)" +run = "gw sync" + +["git:open-pr"] +description = "CI wait -> open in browser -> watch merge -> cleanup (mise run git:open-pr -- [--no-wait])" +run = """ +#!/bin/bash +set -euo pipefail +WAIT_CI=true +ARG="" +for arg in "$@"; do + case "$arg" in + --no-wait) WAIT_CI=false ;; + *) ARG="$arg" ;; + esac +done +if [[ -z "$ARG" ]]; then + echo "Usage: mise run git:open-pr -- [--no-wait]" >&2 + exit 1 +fi +if [[ "$ARG" =~ ^[0-9]+$ ]]; then + PR_NUMBER="$ARG" + URL=$(gh pr view "$PR_NUMBER" --json url --jq '.url') +else + URL="$ARG" + PR_NUMBER=$(echo "$URL" | grep -oE '[0-9]+$' || "") +fi + +# Phase 1: Wait for CI +if [[ "$WAIT_CI" == true && -n "$PR_NUMBER" ]]; then + echo "[git:open-pr] Phase 1/3: Waiting for CI checks on PR #${PR_NUMBER}..." + gh pr checks "$PR_NUMBER" --watch || echo "[git:open-pr] CI checks failed or timed out, opening anyway" +fi + +# Phase 2: Open in browser +echo "[git:open-pr] Phase 2/3: Opening PR in browser..." +gh pr view "$PR_NUMBER" --web + +# Phase 3: Watch for merge +if [[ -n "$PR_NUMBER" ]]; then + INTERVAL=30 + echo "[git:open-pr] Phase 3/3: Watching PR #${PR_NUMBER} for merge (interval: ${INTERVAL}s)..." + while true; do + STATE=$(gh pr view "$PR_NUMBER" --json state --jq '.state' 2>/dev/null || echo "ERROR") + case "$STATE" in + MERGED) + echo "" + echo "========================================" + echo "[git:open-pr] PR #${PR_NUMBER} MERGED!" + echo "========================================" + if command -v osascript &>/dev/null; then + osascript -e 'display notification "PR #'"${PR_NUMBER}"' merged. Running cleanup..." with title "Git Workflow" sound name "Glass"' + fi + echo "[git:open-pr] Running: mise run git:cleanup" + mise run git:cleanup + exit 0 + ;; + CLOSED) + echo "[git:open-pr] PR #${PR_NUMBER} was closed without merging" + exit 0 + ;; + OPEN) + sleep "$INTERVAL" + ;; + ERROR) + echo "[git:open-pr] Failed to fetch PR status, retrying..." + sleep "$INTERVAL" + ;; + esac + done +fi +"""