Repository navigation
Conversation
…#272) When PARSEC_AGENT=1 or PARSEC_AGENT=true, parsec automatically forces JSON output mode and blocks all interactive dialoguer prompts with helpful error messages guiding the user to non-interactive alternatives. Guarded prompts: config init, config shell, switch picker, inbox --pick. Closes #244 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Adds `parsec commit` command that analyzes staged changes and generates a commit message using OpenAI or Anthropic APIs. Auto-detects ticket from current worktree and supports --conventional for Conventional Commits format. New [ai] config section with provider, model, and api_key fields. Env vars: PARSEC_AI_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY. Closes #243 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add --ai-description flag and [ai].auto_pr_description config option to generate PR body content using OpenAI/Anthropic APIs during ship. Includes generate_pr_description() in ai.rs with PR-specific prompt, git::diff_against() helper, and integration in build_pr_body() flow. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…tures) # Conflicts: # src/cli/commands/mod.rs # src/cli/mod.rs # src/config/mod.rs
fix(sync): restore v1.0 features lost by -X theirs auto-resolution
Conflict in src/cli/mod.rs resolved manually: preserved both
v1.0 'Command::Commit' (AI commit message) match arm and develop's
updated 'Command::Smartlog { depth, no_overlay, worktree }' signature.
Build + test verified locally.
Co-Authored-By: Pochacco <noreply@anthropic.com>
chore: sync develop with main (preventive — avoid next-release BEHIND)
- docs/mcp/spec.md: full MCP tool catalogue with JSON schemas for
10 tools: worktree_list/start/status/ship, smartlog, ci_status,
pr_status, health_check, reviews, sync
- src/mcp/mod.rs: McpContext struct, ToolDef, TOOLS registry constant
- src/mcp/tools/{worktree,smartlog,ci,pr,health,reviews,sync}.rs:
Phase 1 stubs with #[allow(dead_code)] pending Phase 2 dispatcher
- 5 unit tests: registry non-empty, snake_case+unique names,
descriptions non-empty, McpContext construction
- #[allow(dead_code)] scoped to mcp module (Phase 1 intentional)
No new external dependencies. No CLI surface changes.
Phase 2 (#293): parsec mcp serve stdio JSON-RPC echo server.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(mcp): Phase 1 — tool spec + src/mcp skeleton (Refs #292)
Conflict on src/config/settings.rs — both branches added a new config struct at the same anchor (release/1.0: AiConfig for Refs #292 MCP / develop: TestConfig for Refs #247 parsec test). Both are unrelated features that must coexist. Resolution: keep both struct definitions sequentially and add both fields (ai + test) to ParsecConfig — no semantic conflict. Verified: - cargo build clean (0 warnings) - cargo test: 83 + 5 + 81 = 169 tests pass 🤖 Manual conflict resolution after auto-sync cron flagged develop → release/1.0 with conflict on src/config/settings.rs (cron policy: silently lost 회피 → 수동 개입 요청).
Refs #292 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
docs(mcp): Phase 2 — protocol contracts
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…stry feat(mcp): Phase 2 — tool registry schemas
## Summary
- translate the v0.5 changelog release notes to English
- translate remaining Korean Rust comments in env and doctor token fallback code
- verify the repository no longer contains Hangul text
## Verification
- rg -n --pcre2 '[\p{Hangul}]' .
- git diff --check
- cargo fmt --check
- cargo test
Refs #293 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Refs #294 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Refs #295 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Refs #293 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Refs #293 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Refs #294 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Refs #293 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Refs #293 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Refs #295 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Refs #295 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Refs #294 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…erlay · Refs #310 (#418) - Add `SmartlogCiOverlay` struct (overall/total/failed) replacing the `serde_json::Value` placeholder in `SmartlogNode.ci` - `attach_ci_overlay()` soft-fail async fn: calls `get_check_runs()` for each PR-linked node; maps passing/failing/pending/no-checks to the four canonical states (passed/failed/running/none) - `map_ci_overall()` helper for the state mapping - `format_ci_badge()` text renderer: [CI: ✓ passed (7/7)] / [CI: ✗ failed (2/7)] / [CI: ● running (0/5)] / [CI: none] - `render_text` emits ├─ CI badge line for nodes with ci overlay set - 9 new Phase 1 tests (badge variants, serde roundtrip, JSON omit/present, render_text integration, map_ci_overall mapping) - `SmartlogNode.ci` change is backward-compatible: None is skip-serialized, existing JSON consumers see no change Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…e fix Add `running: usize` field to `SmartlogCiOverlay` tracking how many check runs are still in-progress or queued. Previously `format_ci_badge` hardcoded `(0/N)` for the running state; now it renders the accurate `● running (R running/N)` count populated by `attach_ci_overlay`. ## Changes - `SmartlogCiOverlay`: new `running: usize` field with `#[serde(default)]` for backward-compatible JSON deserialization. - `attach_ci_overlay`: count `status == "in_progress" | "queued"` runs. - `format_ci_badge`: render `● running (R running/N)` instead of `(0/N)`. - Tests: +4 cases (running count badge, zero-running edge case, Phase-1-era JSON backward compat, render_text integration check). Refs #310 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously attach_ci_overlay skipped any SmartlogNode that had no PR overlay, leaving worktrees without an open PR with no CI information. This phase completes the original #310 acceptance criterion: > 각 worktree branch tip 에 대해 GitHub check runs aggregate Changes - src/github/mod.rs: add GitHubClient::get_check_runs_by_sha(sha) Fetches /commits/{sha}/check-runs directly, without a PR round-trip. Returns CiStatus with pr_number=0 as sentinel (callers use aggregate fields, not pr_number). Identical aggregation logic to get_check_runs. - src/cli/commands/smartlog.rs: - attach_ci_overlay: remove early-exit when all nodes lack a PR; instead branch per node — PR nodes use get_check_runs (existing), PR-less nodes resolve their branch-tip SHA via git rev-parse and call get_check_runs_by_sha (new). Skip gracefully on git failure. - resolve_branch_tip_sha(repo, branch) -> Option<String>: thin helper calling git rev-parse, returns None for orphan/unresolvable branches. - Phase 3 doc comment at module top. - 3 new unit tests: ci badge renders for PR-less node, none badge for PR-less node, resolve_branch_tip_sha returns None for invalid path. Backward-compat: behaviour for PR-linked nodes is unchanged; nodes that fail the git rev-parse (orphan/unborn) degrade to no CI badge, same as before. Refs #310 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
#309 Closes #308 ## 무엇 - `render_text` 에 `overlay_requested: bool` 파라미터 추가 - GitHub overlay 가 요청됐지만 열린 PR 이 없는 worktree 에 `├─ (no PR)` 라인 표시 (issue #309 마지막 미충족 acceptance criterion: "PR 없는 worktree는 (no PR) 표시") - PR 이 있는 노드는 기존 PR badge 만 표시 (동작 불변) - `--no-overlay` 모드에서는 (no PR) 표시 안 함 — 조회 자체를 안 했기 때문 - CI overlay 가 있고 PR 이 없는 노드: (no PR) 위에, CI badge 아래에 표시 (순서 보장) ## 테스트 - Phase 6 테스트 4개 추가: - `no_pr_line_shown_when_overlay_requested` — 핵심 경로 - `no_pr_line_suppressed_when_overlay_not_requested` — --no-overlay 격리 - `no_pr_line_plus_ci_badge_for_pr_less_node_with_ci` — Phase 3(#310) 공존 - `no_pr_line_absent_when_pr_overlay_is_set` — PR 있으면 (no PR) 없음 - issue #308 acceptance criterion ("snapshot test >=1") 충족: - `render_text_full_snapshot_single_node_with_pr_and_commit` — 전체 ASCII 골든 출력 - `render_text_full_snapshot_no_pr_no_commits` — (no PR) + 빈 커밋 골든 출력 - 기존 테스트 15개: `render_text(..., false)` → `render_text(..., false, false)` 시그니처 업데이트 ## 다음 Phase 힌트 - #308 / #309 / #310 모두 acceptance criteria 충족 → 이슈 close - v1.0 마일스톤 완료 → 마일스톤 close 검토 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
… (#423) Add `--no-cleanup` flag to `parsec ship` so users working incrementally (multiple commits / ships on the same ticket) can push + create/update the PR without losing their worktree. Also fix a latent gap: `ship_cleanup()` existed in WorktreeManager but was never called from the `ship` command handler. The combined `manager.ship()` (dead_code) already called it, but the refactored command path (ship_push → PR creation) forgot Phase 3. Now wired correctly with the escape hatch. ## Changes - `src/cli/mod.rs`: add `no_cleanup: bool` to `Command::Ship`, pass through to handler and dry-run message - `src/cli/commands/ship.rs`: add `no_cleanup` param; Phase 3 block calls `manager.ship_cleanup(ticket)` when `!no_cleanup` (still respects `config.ship.auto_cleanup`) - `src/cli/commands/stack.rs`: forward `no_cleanup = false` in stack-ship call to satisfy updated signature (stack always uses config default) - `tests/cli_tests.rs`: two new integration tests — `test_ship_no_cleanup_preserves_worktree` and `test_ship_auto_cleanup_removes_worktree` Refs #313 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ay integration tests (#421) Add PARSEC_GITHUB_API_BASE env var override so tests (and GitHub Enterprise users) can route GitHubClient calls to a custom API endpoint without changing the git remote URL. Also adds two CLI-level integration tests that close the 'mock 으로 통합 테스트' gap in issues #309 and #310. ## Changes ### src/env.rs - PARSEC_GITHUB_API_BASE constant + github_api_base() function (mirrors existing PARSEC_BITBUCKET_API_BASE pattern) ### src/github/mod.rs - GitHubClient::new() uses github_api_base() override when set (single-line additive change; falls back to remote.api_base() when unset) ### tests/cli_tests.rs - test_smartlog_no_overlay_skips_github: verifies --no-overlay exits 0 without any GitHub token and emits no PR/CI badges - test_smartlog_overlay_with_mock_github: spins up a mockito server, points PARSEC_GITHUB_API_BASE at it, runs parsec smartlog, and asserts that [PR #99] and [CI: ✓ passed] badges appear in ASCII output Refs #309 (통합 테스트 acceptance criterion) Refs #310 (mock 으로 통합 테스트 acceptance criterion) Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Add `substitute_template_vars()` helper that expands `{{ticket}}`,
`{{branch}}`, `{{title}}`, `{{ticket_url}}` placeholders in PR
template content before embedding it into the PR body.
Changes:
- src/cli/commands/ship.rs:
- New `substitute_template_vars()` with RustDoc explaining each var
- `build_pr_body()` gains `branch: &str` parameter; passes it + other
context to substitute_template_vars when template content is present
- Template section comment updated to reference #304 alongside #233
- 5 unit tests: all-vars, optional-vars-empty, unknown-var-intact,
multi-occurrence, build_pr_body end-to-end
Unknown `{{…}}` tokens are left intact so templates using other
tooling variables are not silently mangled.
Refs #304
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…efs #296 (#425) Add `parsec self-update` subcommand that queries the GitHub releases API, compares the running version against the latest published release, and prints a cargo-install upgrade command when a newer version is available. ## Changes - src/cli/commands/update.rs (new): async fetch + semver compare + output - src/cli/commands/mod.rs: wire update module - src/cli/mod.rs: SelfUpdate command variant + run dispatch ## Implementation detail - Uses reqwest (already a dep) with 8 s timeout and a parsec/VERSION User-Agent - Numeric semver comparison handles 0.10.0 > 0.9.0 correctly (7 unit tests) - Gracefully degrades on network error (prints current version + releases URL) - Respects global --offline flag: skips network call, prints version only - Phase 2 will add in-place binary replacement (see issue #296) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Refs #304 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…e · Refs #296 (#427) Adds a startup version-check that runs after every command (Human mode only) and prints a one-line stderr hint when a newer release is available. ## What - VersionCheckCache (serde JSON) persisted in dirs::cache_dir() - Throttled to one live GitHub API call per 24 h (STARTUP_CHECK_TIMEOUT_SECS = 2 s) - Uses cached result between checks — instant on subsequent runs - Hint written to stderr (never pollutes piped stdout / JSON mode) - Skipped for: --offline, --quiet, --json, parsec self-update command ## How it works 1. Load cache from ~/.cache/.parsec-version-check 2. If age < 24 h → show hint if cache.latest_tag is newer (instant, no network) 3. If age ≥ 24 h → quick reqwest call (2 s timeout), update cache, show hint if newer 4. Network failure → bump last_checked_secs, preserve existing latest_tag ## Tests 5 new unit tests: cache serde round-trip, default-cache-is-stale, hint logic (newer/older/equal/None) — all deterministic, no network Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…n · Refs #296 - Add `UpdateConfig` to `ParsecConfig` with `check_on_startup` (bool, default true) and `check_interval_hours` (u64, default 24) fields - `startup_version_hint()` now accepts config values; returns immediately when `check_on_startup = false`, honoring `[update] check_on_startup = false` in `.parsec.toml` - `check_interval_hours` replaces the hard-coded 24 h constant, allowing users to tune the poll cadence without code changes - Add `upgrade_command()`: detects Homebrew (/homebrew/ or /Cellar/ in exe path), Cargo (/.cargo/bin/), or prebuilt binary, and returns the appropriate upgrade command string shown in `parsec self-update` output - Remove stale note about Phase 2 from upgrade output now that it is shipped - Add 5 new tests: `upgrade_command_homebrew`, `upgrade_command_contains_repo`, `throttle_secs_from_hours` (pure arithmetic), and existing tests still pass - 108+83+5 tests, clippy-clean, fmt-pass Closes AC: 알림 opt-out config, 다양한 설치 경로 지원 (homebrew/cargo/prebuilt) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes #429 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Register a custom panic hook that prints a user-friendly crash banner
(always) and optionally saves a structured JSON report to
~/.cache/parsec/crash-<ts>.json (opt-in).
## What
- src/panic_handler.rs: new module
- setup(enabled): registers std::panic::set_hook
- Always: human-readable crash banner (version, location, message)
- Opt-in: JSON report (version, ts, os, shell, argv[1], location, msg)
- save_report(): writes ~/.cache/parsec/crash-<ts>.json
- unix_to_utc_fields(): stdlib-only UTC decomposition (no new deps)
- 6 unit tests: date decomposition, report fields, escape, setup idempotency
- src/config/settings.rs: CrashReportConfig { enabled: bool } (default false)
+ ParsecConfig::crash_report field
- src/main.rs: call panic_handler::setup(config.crash_report.enabled) early
- docs/crash-report.md: privacy policy (what is/isn't collected, opt-in, retention)
## What is NOT collected
No stack trace, no flags, no ticket IDs, no tokens. argv[1] only.
No automatic transmission; user must manually share.
## Tests
114 unit tests pass (6 new in panic_handler), 5 integration, 83 total.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ds · Refs #298 * feat(panic-handler): Phase 2 — crash-report list/show/clear subcommands · Refs #298 Add `parsec crash-report` with three sub-commands for managing the opt-in crash report cache written by the Phase 1 panic hook. ## Subcommands | Command | Description | |------------------------------|----------------------------------------------| | `parsec crash-report list` | Table of all reports + panic preview | | `parsec crash-report show ID`| Full JSON pretty-print for one report | | `parsec crash-report clear` | Remove all reports (--dry-run safe) | ## Changes | File | Change | |-----------------------------------------|-------------------------------------| | `src/cli/commands/crash_report.rs` | New: list/show/clear + 5 unit tests | | `src/cli/commands/mod.rs` | Re-export new module | | `src/cli/mod.rs` | CrashReport + CrashReportAction enum + dispatch | ## Behaviour - `list` respects `--json` (array of {id, timestamp, panic_message, panic_location}) - `show` accepts id with or without `.json` suffix; bail if not found - `clear` respects global `--dry-run`; all operations read-only except clear - Cache dir: `<OS cache>/parsec/crash-*.json` (same as Phase 1 writer) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(panic-handler): use epoch-second stems in test fixtures (Windows colon-in-filename) Windows forbids in filenames, so test fixtures using ISO-8601 stems like failed on the windows-latest CI runner. Switch to Unix epoch-second stems (e.g. ) to match the actual filename format written by the Phase 1 panic hook. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Add `parsec checkpoint` with two subcommands: - `parsec checkpoint create [name]` — stashes current worktree state (staged, unstaged, untracked) under a `parsec-checkpoint:<name>` label. Defaults to a UTC timestamp when no name is given. Exits cleanly when the working tree is clean. - `parsec checkpoint list` — filters `git stash list` to show only parsec-managed checkpoints; renders a STASH REF / NAME / BRANCH table (--json supported). Implementation details: - Purely stash-based — no new files written to disk. - Prefix convention (`parsec-checkpoint:`) isolates parsec stashes from ordinary WIP stashes without data loss risk. - `--dry-run` respected via the global flag (stash not created when dry). - 8 unit tests covering happy paths, WIP-prefix variant, filtering of non-parsec stashes, and malformed input. Phase 2 will add `restore <name>` and `drop <name>`. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
) Add `parsec checkpoint restore <name>` and `parsec checkpoint drop <name>` subcommands that perform name-based lookup of parsec-managed stash entries. ## Changes - `checkpoint_restore`: finds stash by name, runs `git stash pop` - `checkpoint_drop`: finds stash by name, runs `git stash drop` - `find_checkpoint` helper: exact-match lookup with helpful error listing available checkpoint names when the given name is not found - CLI: `CheckpointAction::{Restore,Drop}` variants wired through dispatcher - Tests: 6 new unit tests covering exact-match lookup, partial-name rejection, hyphenated names, timestamp names, missing name error path Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…Refs #435 Add 11 integration tests to tests/cli_tests.rs covering the checkpoint and crash-report commands (both shipped in Phase 1+2 with zero prior CLI-level test coverage). ## checkpoint (8 tests) - help shows all four subcommands - list empty repo → human 'No checkpoints found' - list empty repo --json → [] - create on clean tree → exit 0 + 'clean' message - create with uncommitted changes → checkpoint created, name in stdout - create then list → name appears in list - drop removes checkpoint → list returns empty again - name with ':' is rejected (colon collides with prefix delimiter) ## crash-report (3 tests) - help shows list/show/clear - list with no reports → human 'No crash reports found' - list --json with no reports → [] (uses XDG_CACHE_HOME isolation to avoid host crash reports) All tests: cargo test --quiet passes (94/94 cli_tests, 132/132 unit). cargo fmt + clippy -D warnings clean. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Closes #439 Co-authored-by: OpenAI Codex <noreply@openai.com>
Closes #441 Co-authored-by: OpenAI Codex <noreply@openai.com>
Closes #443 Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: OpenAI Codex <noreply@openai.com>
Closes #447 Co-authored-by: OpenAI Codex <noreply@openai.com>
Merge the final develop line into release/1.0, preserve both MCP and late v0.x features, and align version and release documentation. Co-Authored-By: OpenAI Codex <noreply@openai.com>
release: prepare v1.0.0
release: promote v1.0.0 to develop
## Summary - align the README Linux download URL with the v1.0 release artifact name - remove the inaccurate Homebrew label ## Verification - compared against `.github/workflows/release.yml` artifact naming
docs: fix v1.0 binary download URL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mainIntegration trail
developintorelease/1.0and prepare v1.0.0developVerification
cargo fmt --all -- --checkcargo clippy --all-targets -- -D warningscargo test --locked --all-targets(419 tests)cargo publish --dry-run --lockedMerging this PR triggers the v1.0.0 tag, crates.io publish, GitHub Release binaries, and versioned docs snapshot.