Skip to content

release-followup: docs snapshot v0.5.0 + release.yml fix#344

Merged
erishforG merged 27 commits into
mainfrom
develop
Jun 3, 2026
Merged

release-followup: docs snapshot v0.5.0 + release.yml fix#344
erishforG merged 27 commits into
mainfrom
develop

Conversation

@erishforG

Copy link
Copy Markdown
Owner

What

v0.5.0 release follow-up — main에 반영해야 라이브:

  1. PR docs: snapshot versioned docs for v0.5.0 (manual replay of failed release job) #342 — `docs/v/0.5.0/` 수동 스냅샷 (release.yml의 실패한 job 재현)
  2. PR fix(release): snapshot-docs via PR instead of direct push to protected main #343 — release.yml을 PR 기반 (peter-evans) + Branch Policy 예외 (다음 릴리스부터 자동)

이미 develop에 머지된 두 PR을 main으로 전달.

Trigger 영향

이 PR이 main에 머지되면 `release.yml`이 다시 실행되지만:

  • Cargo.toml version 0.5.0 그대로 → tag check exists == 'false' 가 false → 모든 job skip (no-op)
  • 즉 새 tag/publish 없음, 안전

효과

🤖 Generated with Claude Code

erishforG and others added 27 commits May 6, 2026 21:59
* fix(ship): fall back to gh auth token (parity with parsec doctor) (#281)

parsec ship 이 PARSEC_GITHUB_TOKEN / GITHUB_TOKEN / GH_TOKEN env var 모두 비어있을 때
PR 생성을 거부했지만 parsec doctor 와 tracker 레이어는 이미 `gh auth token` fallback
적용. parity 깨져 사용자가 수동 `gh pr create` 로 추가 작업 필요.

해결:
- src/env.rs: github_token() 의 4번째 우선순위로 gh_auth_token() 추가. 신규
  gh_auth_token() helper 는 `gh auth token` shell out — 실패 시 None (binary 없음 /
  exit code != 0 / non-UTF8 / 빈 출력 모두 graceful).
- src/github/mod.rs: resolve_github_token 의 env-var/gh fallback 을 GitHub host
  (github.com / *.ghe.com / *.github.* GHE) 에만 적용. 신규 is_github_host() helper.
  Bitbucket / GitLab remote 가 `gh auth login` 한 환경에서 GitHub 토큰을 잘못 픽업하지
  않도록 가드.
- src/cli/commands/doctor.rs: 중복 `gh auth token` shell-out 코드 제거 → env::gh_auth_token()
  공통 helper 호출. parity at the helper level.

신규 테스트 (src/env.rs): github_token_priority_order — PARSEC > GITHUB > GH 우선순위
+ 빈값 fallback 4 시나리오 sequential 검사. EnvGuard 로 process-wide env 보존+복원.
gh_auth_token_returns_option_string_or_none — gh binary 가용성에 무관하게 trim 보장.
github_token_returns_none_when_all_missing_and_gh_fails — env 모두 미설정 시 None
또는 valid Some 모두 허용 (CI 와 dev 환경 양립).

검증:
- cargo test: 79 tests PASS (env tests 6 + integration 73)
- cargo clippy --all-targets -- -D warnings: clean
- cargo fmt --check: clean
- bitbucket integration tests: 5/5 PASS (이전 발견된 host-gated 이슈 해결)

회귀 위험: 매우 낮음
- 환경에 gh CLI 미로그인 / 미설치 → 기존과 동일 (None 반환)
- 환경에 gh 로그인됨 + GitHub remote → 신규 fallback 활용 (issue #281 의도)
- 환경에 gh 로그인됨 + Bitbucket/GitLab remote → is_github_host 로 차단, 기존과 동일

Closes #281

* docs(v0.5): open roadmap milestone — visualization release vision

v0.5 마일스톤 공식 출발 마커. README 와 CHANGELOG 양쪽에 향후 비전 명시.

README.md (## Roadmap 섹션 신설, ## Why use it 과 ## Install 사이):
- vision tagline: "parsec = AI agents + human devs both — worktree-native git CLI"
- 4단계 milestone:
  · v0.4.0 ✅ Released (2026-05-04): Multi-forge + multi-tracker foundation
  · v0.5 🚧 Next — _The visualization release_:
    smartlog · TUI dashboard · speculative merge · parsec test · AI PR descriptions
  · v1.0 🔜 — _AI-Native Standard_:
    MCP server signature, Claude/Cursor/Copilot 가 parsec 을 first-class tool 로 invoke
  · v2.0+ 🔮 — _Ecosystem Hub_: plugins · VS Code extension · Linear tracker
- v0.5 milestone link (github.com/erishforG/git-parsec/milestone/3)

CHANGELOG.md (## [Unreleased] 확장):
- ### Added: v0.5 milestone opened, README Roadmap 참조
- ### Fixed: #281 ship gh auth token fallback 노트 (별 commit ae1a2d3 와 동일 entry)

회귀 위험: 0 (문서 변경만)

* fix(env): serialize env-touching tests via process-wide mutex (Windows CI)

PR #289 Windows CI 1건 fail. macOS / Ubuntu Test 통과, Windows Test 만 실패.

원인:
- env::tests 의 github_token_priority_order 와 github_token_returns_none_when_all_
  missing_and_gh_fails 가 cargo test 병렬 실행 시 process-wide env vars 를 race.
- priority_order 가 PARSEC=p / GITHUB=g / GH=h 셋업 후 assert 사이에 sibling 테스트의
  EnvGuard::new() 가 모든 env 를 clear → assert 가 PARSEC 못 보고 GH=h 반환.
- macOS/Ubuntu 는 timing 우연히 안전, Windows 는 다른 thread scheduling 으로 race
  발현 (Some("h") vs Some("p") at src/env.rs:205).

수정:
- std::sync::OnceLock<Mutex<()>> 의 env_lock() 신규 — env 만지는 테스트들 직렬화.
  std 만 사용 (외부 deps 추가 X 제약 준수).
- github_token_priority_order 와 github_token_returns_none_when_all_missing_and_gh_fails
  를 단일 함수 github_token_priority_order_and_fallback 로 통합 + env_lock() 의
  Mutex guard 획득. 5 시나리오 (PARSEC 우선 / GITHUB / GH / 빈값 / 모두 미설정) 직렬 실행.
- gh_auth_token_returns_option_string_or_none 은 env 미터치라 lock 불필요 — 그대로 유지.
- production 로직 (env::github_token / env::gh_auth_token) 변경 0.

검증:
- 로컬 cargo test 78 PASS (env tests 5 + integration 73), clippy clean, fmt clean.
- Windows CI 검증은 force-push 후 PR #289 워크플로우에서 확인.
…utput (#305)

Phase 1 of #245. Establishes the command surface and rendering path
without any forge-side enrichment.

Adds `parsec smartlog` (alias `sl`):
- `SmartlogNode` per active worktree: ticket, branch, base, commits,
  plus `pr` / `ci` placeholder fields gated on `skip_serializing_if`
  so the JSON output stays clean until follow-up PRs populate them.
- `collect_commits` shells out to `git log <base>..<branch>` (no
  `git2` dependency — matches the rest of `git/`). Soft-fails per
  worktree so a corrupt worktree can't take the whole command down.
- `render_text` groups nodes by base branch and draws ASCII tree
  glyphs (○ │ ├─● └─). Returns the rendered string for testability.
- `--json` emits the same structure for tooling.
- `--depth N` caps commits per worktree (default 10).

Out of scope for this PR (follow-ups on the same epic):
- PR overlay (open/draft/merged)
- CI overlay (passed/failed/running)
- Review state (approved / changes requested)
- Stack relationship visualization
- Color / smarter wrapping

Tests (9 new in `cli::commands::smartlog::tests`):
- `parse_commit_line` happy path + tab-in-subject + garbage + empty SHA
- `render_text` empty / single / no-commits / multi-base grouping
- JSON serialization omits placeholder overlay fields

Smoke run on parsec's own worktrees produces:
  ○ develop (base)
  ├─● 207 #207 [feature/207]
  │  └─ (no commits since develop)
  └─● 279 #279 [feature/279]
     └─ (no commits since develop)
…lp) (#306)

* [303] refactor(errors): adopt 3-line standard (error / caused by / help)

Issue #303. Add the infrastructure for the standard error format and
wire main.rs to render it. Existing call sites keep rendering as a
single line — migration is gradual (see docs/error-format.md).

Changes:
- `ParsecError` gains `caused_by: Option<String>` and `help: Option<String>`
  fields plus builder-style setters (`with_caused_by`, `with_help`).
  `Display` now writes one to three lines depending on which fields are
  populated.
- `JsonError` gains the same two fields with `skip_serializing_if =
  "Option::is_none"` so existing `--json` consumers see no schema change.
- `extract_full(&anyhow::Error) -> Option<&ParsecError>` helper for new
  callers; the legacy `extract_code` is kept untouched.
- `main.rs` prefers the typed error: when the error is a `ParsecError`,
  print it directly (its `Display` already includes the `error:` prefix
  + code); otherwise fall back to the legacy single-line `error: {err:#}`.
- `bail_code!` macro unchanged (for the "summary only" case).
- `docs/error-format.md` documents the format, builder API, JSON shape,
  recipes, and what NOT to do.

Tests: +9 in `errors::tests` covering 1/2/3-line display, help-only,
extract_full happy/None, backward-compat extract_code, JSON skip-if-none,
JSON with-fields, bail_code macro round-trip. Full suite 53 + 5 + 40 =
98 pass, fmt clean.

Migration: any existing `ParsecError::new(...)` site can opt in by
chaining `.with_caused_by(...)` and/or `.with_help(...)`. Prioritize
cli/commands/ and worktree/ first (highest user contact).

* [303] chore(errors): allow dead_code on Phase 1 builder + legacy extract_code

Clippy `-D warnings` flagged `with_caused_by`, `with_help`, and
`extract_code` as never-used. Phase 1 of #303 is the infra-only PR —
call sites land in follow-up PRs. Annotation matches the existing
`#[allow(dead_code)]` on `ErrorCode` for the same forward-looking reason.
Adds an informational windows-2025-vs2026 job that runs cargo build/test
on the new Visual Studio 2026 default image ahead of the GitHub Actions
runner migration window (2026-06-08 ~ 06-15).

continue-on-error: true keeps it advisory only — main matrix stays gated
on existing windows-latest. After the migration window closes we either
delete this job (if main matrix passes) or pin windows-2022 here (if it
fails).

Refs: #307
Adds `parsec __complete <worktrees|branches>` — a hidden subcommand that
shell completion scripts can call to enumerate candidates dynamically.
Failure paths (no repo / no config) silently emit nothing so completion
never errors at the prompt.

Also adds `git::list_local_branches`, a helper for enumerating local
branch names via `git for-each-ref refs/heads/`.

This is the **foundation only**. The follow-up work — post-processing
clap-generated completion scripts (zsh/bash/fish) so that ticket-shaped
arguments call `parsec __complete worktrees` and branch-shaped arguments
call `parsec __complete branches` — lands in a separate PR.

Refs: #291
* test(cli): add integration tests for compress, config schema, log --export

Cover three commands added in v0.4.0 that had zero test coverage:
- test_compress_nothing_to_do: single-commit worktree exits cleanly
- test_compress_squashes_commits: 2-commit branch is reduced to 1
- test_config_schema_outputs_json: output is valid JSON Schema
- test_history_log_export_empty: empty log exits 0 with no stdout

Closes #314

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* ci: re-trigger Branch Policy (base now develop)

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…317)

develop에 머지됐지만 CHANGELOG.md [Unreleased]에 누락된
항목 4개를 추가한다:

- parsec smartlog (alias sl): commit DAG 시각화 (#245, #305)
- parsec __complete: 동적 shell completion 헬퍼 (#291, #312)
- 에러 메시지 3줄 표준화 (error/caused by/help) (#303, #306)
- Windows VS2026 pre-validation CI job (#307, #311)

Closes #316

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
parsec smartlog (#305)과 sl 별칭이 develop에 머지됐지만
CLI 통합 테스트가 전혀 없었음. 5개 시나리오 추가:

- test_smartlog_empty_repo: 빈 repo → 'No active worktrees' 확인
- test_sl_alias_works_like_smartlog: sl == smartlog 동일 출력 확인
- test_smartlog_json_empty_is_array: --json 빈 repo → [] JSON 배열
- test_smartlog_shows_worktree: worktree 1개 → 티켓·(base) 마커 표시
- test_smartlog_json_one_worktree: --json 1 worktree → 필드 검증
  (ticket, branch, base_branch, commits, pr/ci 미노출)

Closes #318

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
diff.rs, history.rs에 module-level(//!) 및 function-level(///) RustDoc을
추가. 인접한 smartlog.rs·complete.rs와 일관성 맞춤.

- diff.rs: //! 모듈 헤더(diff/conflicts/sync 역할·관련 이슈), pub async fn
  diff/conflicts/sync에 파라미터·출력모드·동작 설명 추가
- history.rs: //! 모듈 헤더(OpLog·ExecLog 구조 설명), pub async fn
  log/log_export/undo에 동작·edge-case 설명 추가

프로덕션 코드 변경 없음 (주석 전용).

Closes #320

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
stack.rs: //! 모듈 헤더 + stack/stack_sync/stack_submit 함수 doc
ci.rs: //! 모듈 헤더 + ci/fetch_bitbucket_ci 함수 doc

프로덕션 코드 변경 없음 — 주석 73줄 추가만.

Closes #322

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…eleton (#324) (#325)

Add `parsec health` command that scans all active worktrees for three
lightweight health indicators:

- has_lock     — .git/index.lock exists (interrupted git process)
- uncommitted  — count of staged + unstaged files
- stale        — last commit older than 7 days

Output (human mode): colored table with ✓/⚠/✗ per worktree and a
summary line. JSON mode emits a structured array with `all_healthy` flag.

Files changed:
- src/cli/commands/health.rs       (new, ~99 lines)
- src/cli/commands/mod.rs          (+2 lines, re-export)
- src/cli/mod.rs                   (+11 lines, Health variant + dispatch)
- src/output/mod.rs                (+15 lines, HealthRecord + dispatch_output!)
- src/output/human.rs              (+66 lines, colored table renderer)
- src/output/json.rs               (+34 lines, JSON renderer)

CI-status overlay deferred to Phase 2 (depends on #309/#310).
All checks are read-only; no worktree state is modified.

Closes #324
Refs #299

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Phase 1 구현(#325)을 커버하는 통합 테스트:

- test_health_empty_repo: 빈 repo → 'No active worktrees.' 확인
- test_health_empty_repo_json: 빈 repo → --json 시 '[]' 출력 확인
- test_health_shows_worktree: 워크트리 1개 → 티켓명 포함 출력 확인
- test_health_json_one_worktree: --json 구조 검증
  (worktrees 배열, all_healthy 불리언, ticket/has_lock/uncommitted/stale_days/stale 필드)
- test_health_exit_zero_with_issues: lock 파일 존재해도 exit 0 (정보성 only)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(health): parsec health CLI 통합 테스트 5개 추가 (#324)

Phase 1 구현(#325)을 커버하는 통합 테스트:

- test_health_empty_repo: 빈 repo → 'No active worktrees.' 확인
- test_health_empty_repo_json: 빈 repo → --json 시 '[]' 출력 확인
- test_health_shows_worktree: 워크트리 1개 → 티켓명 포함 출력 확인
- test_health_json_one_worktree: --json 구조 검증
  (worktrees 배열, all_healthy 불리언, ticket/has_lock/uncommitted/stale_days/stale 필드)
- test_health_exit_zero_with_issues: lock 파일 존재해도 exit 0 (정보성 only)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(smartlog): Phase 2 — PR/CI status overlay (Refs #245)

Phase 1 (#305) skeleton에서 `SmartlogNode.pr` 가 placeholder로 남아있던 걸
실제 GitHub PR/CI 데이터로 채움. Issue #245 의 예시 (`[PR #42 ✓ CI passed,
✓ approved]`) 가 이제 ASCII 트리에 그대로 렌더링됨.

## 변경
- `SmartlogPrOverlay` struct 신설 (number/state/ci_status/review_status/url)
- `smartlog()` 가 GitHubClient 통해 brach → PR 매칭 + PrStatus 조회 후
  node.pr 채움. 토큰 없거나 비-GitHub remote거나 HTTP 실패 = 그냥 overlay
  생략 (best-effort, 명령 실패 안 함)
- `--no-overlay` 플래그 추가 (강제 offline 모드)
- ASCII 렌더러: ticket 라인 아래 `├─ [PR #N ● open ✓ CI ✓ approved]` 한 줄
- 글리프 규칙: 기존 `parsec pr status` / `parsec ci` 와 동일 (✓/✗/●/○)

## CI 필드는?
`SmartlogNode.ci` 는 일단 None 유지. Phase 2 는 CI 요약을 overlay 안에
포함시켜 한 줄로 표시 (스마트로그 본질은 한눈 — per-check 디테일은
`parsec ci` 가 이미 담당).

## 드라이브-바이
tests/cli_tests.rs:1725 에 `assert_eq!(bool, false)` clippy 경고 (#326
회귀) → `assert!(!...)` 로 수정. develop 의 clippy strict 빌드 회복.

## 테스트
- 신규 unit 5개 (format_pr_badge × 3 + render_text overlay + JSON 직렬화)
- 기존 9개 smartlog unit + 5개 통합 테스트 모두 통과
- cargo build / clippy -D warnings / fmt --check / test 전체 clean

## 다음 Phase 힌트
- Phase 3: per-worktree filtering (`--ticket CL-2283` 등)
- Phase 4: stack 관계 시각화 (PR base = 다른 PR head)
- Phase 5: review state 색상 강조 (terminal color)

Refs #245

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…291) (#328)

Phase 1 (#312) 가 `parsec __complete <kind>` 내부 명령을 만들어 shell completion
스크립트가 동적으로 worktree/branch 후보를 가져올 수 있게 했음. 이번에는 그 위에
실제 zsh/bash/fish 스크립트 3개를 추가해서 사용자가 sourcing 만 하면
`parsec switch <Tab>` 처럼 live ticket 자동완성을 받을 수 있게 함.

## 변경
- `completions/_parsec` (zsh, #compdef) — `_parsec_worktrees` / `_parsec_branches`
  helper + 모든 주요 subcommand 의 positional/option 자동완성
- `completions/parsec.bash` — `complete -F _parsec parsec`. bash-completion
  의존 (`_init_completion`). prev word 기반 dispatch + `compgen -W`
- `completions/parsec.fish` — `__fish_seen_subcommand_from` 기반.
  per-subcommand 옵션 (`--base`, `--on`, `--branch`) 도 동적 branch/worktree
  후보 연결
- README "Install > Shell completion" 섹션 추가 (3개 shell install 명령)

## 커버 범위 (Tier 1 + 2)
- ticket 받는 subcommand: start, switch, ship, open, clean, status, ticket,
  pr-status, ci, merge, diff, sync, log, compress, adopt, rename
- branch 받는 옵션: `start --base|--on|--branch`, `ship --base`, `adopt --branch`
- smartlog: `--depth`, `--no-overlay` (PR #327 와 호환)

## __complete kind 추가
없음. Phase 1 의 `worktrees` / `branches` 두 개로 충분 — future Phase 3 에서
필요하면 추가 (예: `tickets` 트래커, `reviewers` GitHub 사용자).

## 드라이브-바이
PR #327 에서 같이 잡았던 `tests/cli_tests.rs:1725` clippy 회귀 (#326)
develop 머지 전이라 또 한 번 적용. PR #327 머지되면 충돌 안 남.

## 테스트
- 신규 4개 통합 테스트:
  - `completion_zsh_present_and_dynamic` — `#compdef parsec` + `__complete` 호출 + 핵심 sub 7개
  - `completion_bash_present_and_dynamic` — `complete -F _parsec parsec` + 동일
  - `completion_fish_present_and_dynamic` — `__parsec_worktrees` 함수 + 동일
  - `completion_scripts_reference_phase1_subcommand_signature` — 스크립트가
    Phase 1 가 지원하지 않는 kind 부르지 않는지 (silent fail 방지)
- 전체 62 통합 테스트 + smartlog 14 단위 + health 5 통과
- cargo build / clippy -D warnings / fmt --check 전부 clean

## 다음 Phase 힌트
- Phase 3: `__complete tickets` (트래커 미해결 티켓), `__complete reviewers`
  (GitHub mention)
- Phase 4: shell auto-install hook (parsec init 에서 자동 설치 옵션)

Refs #291

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…old (Refs #299)

## 무엇
parsec health Phase 2: GitHub CI 상태 오버레이 + 설정 가능한 stale 임계값.

## 변경
- health.rs: --stale-days <N> 플래그로 stale 임계값 설정 (기본 7일)
- health.rs: --no-overlay 플래그로 오프라인 모드 지원
- health.rs: fetch_ci_overlay() — 브랜치 → PR 번호 → CI 상태 (best-effort)
- output/mod.rs: HealthRecord에 ci_status: Option<String>, pr_number: Option<u64> 추가
- output/human.rs: CI 상태를 색상 아이콘으로 표시 (✓/✗/● CI)
- output/json.rs: ci_status, pr_number, ci_failing 필드를 JSON 출력에 포함
- cli/mod.rs: Health 명령을 struct variant로 변경 (--stale-days, --no-overlay)
- tests/cli_tests.rs: Phase 2 플래그 검증 테스트 3개 추가 (8/8 통과)

## 다음 Phase 힌트
Phase 3: threshold config (parsec.toml [health] stale_days), 경고 exit code 옵션

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(health): Phase 2 — CI status overlay + configurable stale threshold
#301) (#331)

Adds `parsec reviews` (alias `rv`) — a new command that scans every
active worktree, resolves its open GitHub PR by branch name, and prints
a unified review table with per-PR review decisions and CI status.

## What
- New `src/cli/commands/reviews.rs` with `reviews()` async function
- `ReviewEntry` struct added to `src/output/mod.rs`
- Human table renderer in `src/output/human.rs` (color-coded review/CI badges)
- JSON array renderer in `src/output/json.rs`
- `Reviews` CLI variant wired in `src/cli/mod.rs` (alias `rv`)
- 3 unit tests for ReviewEntry construction

## Phase 2 hint
Add `--requested` flag: use GitHub Search API
(`/search/issues?q=review-requested:{login}`) to show PRs from *others*
where the current user is a requested reviewer.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…nt (#290)

* feat(sync): stale-threshold filter, dry-run behind-count, conflict hint (#290)

- Add --min-behind N flag (default: 1) to skip worktrees fewer than N
  commits behind origin/<base_branch>; skipped entries shown in output
- dry-run now fetches behind-count and reports per-worktree before exit
- Conflict detection: append "(conflict detected — resolve manually)"
  hint to failed sync reason when git output contains "conflict"
- Extend print_sync signature with skipped: &[(String, u32)] across
  human/json/mod output layers; stack_sync passes &[] (no change)
- Add 3 CLI integration tests: up-to-date skip, dry-run output, rebase

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* style: cargo fmt

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
#333)

Refs #245

## What
- Add `--worktree <pattern>` flag (-w) to `parsec smartlog` / `sl`: case-
  insensitive substring match on ticket or branch name so users can focus on
  a subset of worktrees without noise from unrelated ones.
- ANSI color in the PR/CI badge: green for success/approved/merged, red for
  failure/changes-requested, yellow for pending, blue for open PR, dim for
  draft/closed.  Automatically disabled when `NO_COLOR` is set or stdout is
  not a TTY; force-enable via `PARSEC_COLOR=always`.
- Stack indicator: when a worktree's base branch matches another active
  worktree's branch name, the base-group header now reads
  `○ <branch> (stacked on <ticket>)` instead of `(base)`, making stacked-PR
  flows immediately visible without extra commands.

## Tests added (5 new)
- `worktree_filter_matches_ticket_substring`
- `worktree_filter_branch_fallback`
- `stack_indicator_appears_when_base_is_sibling_branch`
- `color_badge_contains_ansi_codes_when_enabled`
- `color_badge_failure_ci_is_red`

All 138 tests pass (cargo build / clippy / fmt / test ✓).

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…301) (#334)

Add `--requested` flag to `parsec reviews` (alias `rv -r`) that shows
open PRs *from others* in this repo where the authenticated user is
a requested reviewer.

## What changed
- `src/github/mod.rs`: add `get_authenticated_user()` (GET /user) and
  `search_review_requested_prs(login)` (GET /search/issues with
  review-requested query). Reqwest .query() handles URL encoding —
  no new dependencies.
- `src/cli/commands/reviews.rs`: split into `collect_authored_reviews`
  (Phase 1 logic) and `collect_requested_reviews` (Phase 2). Each
  returns Vec<ReviewEntry>; the caller merges and dispatches.
- `src/cli/mod.rs`: add `requested: bool` field to `Reviews` variant,
  pass through to command handler.
- 4 unit tests: existing 3 preserved + 1 new for reviewer-mode ticket placeholder.

## Phase 3 hint
- Add `--all` flag to include closed/merged PRs.
- Add author filter (`--author`) to narrow results.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…oses #246) (#335)

`parsec conflicts --simulate`로 실제 in-memory three-way 머지를 수행해 라인-레벨
충돌을 사전 탐지. 기존 filename overlap 휴리스틱 (`parsec conflicts`)을 보완.

## 추가 모듈
- `src/conflict/simulator.rs` (240줄)
  - `MergeSimulation { vs_base, cross, skipped }` 결과 구조
  - `simulate(repo, &workspaces)` 진입점
  - Pass 1: 각 워크트리 HEAD vs origin/<base> (`merge-base` → fallback to local base)
  - Pass 2: 워크트리 페어 cross-simulate
  - 도구: `git merge-tree --write-tree --name-only --merge-base=<mb>` (git 2.38+)
  - read-only — 워킹디렉터리/index 무수정, merge tree 객체는 DB에 남되 참조 없음

## CLI
- `Command::Conflicts` variant에 `--simulate` bool 플래그 추가
- 디스패치 시 simulate true이면 `conflict::simulate(...)`, false면 기존 `conflict::detect(...)`

## Output
- Human: 'Worktree → base conflicts' + 'Cross-worktree conflicts' 섹션, 파일 목록 ●로 표시
- JSON: `{ vs_base: [...], cross: [...], skipped: [...] }` 머신 readable

## 가드레일
- WorkspaceStatus::Active 만 처리
- merge-base 계산 실패시 skipped로 다운그레이드 (전체 리포트 중단 방지)
- `merge-tree` 비-0 exit + 빈 출력은 transient로 간주

## 검증
- cargo build clean
- cargo clippy -D warnings clean
- cargo fmt clean
- cargo test: 66 lib + 5 simulator + 71 cli = 142 통과 (이전 138 + 신규 4 simulate)

## 신규 테스트 (tests/cli_tests.rs)
- test_conflicts_simulate_empty_repo
- test_conflicts_simulate_json_empty_is_object
- test_conflicts_simulate_single_clean_worktree
- test_conflicts_simulate_detects_cross_worktree_line_conflict (실제 충돌 시드)

v0.5 마일스톤.

Co-authored-by: Pochacco <noreply@anthropic.com>
…Closes #247) (#336)

* feat(test): parsec test — parallel test runner with tree-hash caching

Implements `parsec test` (issue #247): runs a configurable shell command
inside one or every parsec-managed worktree, with optional parallelism
(`--jobs N`) and tree-hash result caching (`--cache`).

- New `[test]` section in ParsecConfig (command / jobs / cache defaults).
- New `Command::Test` variant with --all / --jobs / --cache / --command
  flags plus auto-detect of the current worktree from CWD.
- Cache files live under `<repo>/.parsec/test-cache/<tree-hash>.json`;
  only successful runs are persisted.
- Output dispatched through `print_test_results` (human table + JSON
  array with from_cache / exit_code / duration_ms / stdout_tail).
- Tail of stdout/stderr (40 lines) surfaced on failure for fast triage.
- Six new CLI integration tests covering help, single-worktree, --all,
  cache hit replay, non-zero propagation, and parallel completion.

Closes #247

* fix(test): cross-platform shell + Windows test gating

Windows CI fail 원인: bash가 WSL로 해석되는데 distro 미설치 → exec 실패.

- 러너: `bash -c` → 플랫폼별로 `sh -c` (Unix) / `cmd /C` (Windows)
- 테스트 명령: `true` → `exit 0` (cmd.exe + sh 양쪽 동작)
- `test_test_jobs_parallel_completes`는 sleep 의존 → `#[cfg(unix)]` 게이트

cargo test 73 cli + 5 bitbucket + 69 unit = 147 통과.

Co-Authored-By: Pochacco <noreply@anthropic.com>

---------

Co-authored-by: Pochacco <noreply@anthropic.com>
…#337)

Introduce `parsec dashboard` (alias `dash`), a `ratatui` + `crossterm`
based terminal UI that aggregates worktree, CI, and GitHub PR status into
a single live view.

Layout (three panes + status bar):
  - Worktrees pane (top-left): list of every active worktree with a
    color-coded CI dot, ticket ID, title/branch, and status.
  - CI pane (top-right): per-worktree `PR #N · ✓/✗/●` summary.
  - PRs pane (bottom): table — PR · title · state · review · CI.
  - Status bar: key hints + last-update timestamp + last-error badge.

Concurrency: a single background `tokio::task` refreshes the shared
`Arc<Mutex<DashboardSnapshot>>` every `--refresh` seconds (default 10).
The UI loop never blocks on network — it redraws the latest snapshot
on each tick or key event via `tokio::select!`.

Keys: `q` / Esc quit · `r` force refresh · `?` / F1 help overlay ·
`↑/↓` (or `j/k`) move selection · Ctrl-C quit.

Robustness:
  - Terminal state (alternate screen + raw mode) is restored by a
    `Drop` guard that runs on every exit path, including panic.
  - `--no-overlay` (or missing GitHub token) renders `–` placeholders
    instead of erroring.
  - `--json` / `--quiet` are rejected early with an actionable message
    pointing to `parsec list --json` / `parsec reviews --json`.

Tests: four new integration tests for help text (both `dashboard` and
`dash`), `--json` rejection, and `--quiet` rejection, plus five new
unit tests for the rendering helpers.

Deps: ratatui 0.28, crossterm 0.28.

Closes #248

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* chore(release): v0.5.0 — visualization release

- Cargo.toml: 0.4.0 → 0.5.0 (release.yml이 main push 시 자동 tag/publish 트리거)
- CHANGELOG: Unreleased → [0.5.0] 정리 (v0.5 마일스톤 16개 항목 반영)
- README: Roadmap v0.5.0 ✅ Released 마킹, v1.0 'Next'. 신규
  'Visualization & power-user tools' 섹션 (8개 신규 명령). command count 33+
- docs/llms.txt: 버전 0.5.0, v0.5 명령 quick reference

cargo build/clippy/fmt clean · test 142/142.

Co-Authored-By: Pochacco <noreply@anthropic.com>

* ci: RUST_MIN_STACK=8MB to fix Windows stack overflow after TUI deps landed

#248 (TUI dashboard) added ratatui + crossterm. Windows 기본 main-thread
stack 1MB가 tokio + reqwest + ratatui + crossterm 결합 후 overflow → bitbucket
integration test 5개 panic.

워크플로우 env에 RUST_MIN_STACK=8388608 (8MB) 추가. 모든 test/build job에
적용. macOS/Linux는 변경 영향 없음.

Co-Authored-By: Pochacco <noreply@anthropic.com>

* build: Windows linker /STACK:16MB — fix bitbucket integration test overflow

RUST_MIN_STACK은 Rust 스레드만 영향. Windows main-thread stack(기본 1MB)은
linker 옵션이 결정. v0.5 TUI dashboard 진입 후 ratatui + crossterm +
tokio + reqwest 결합으로 1MB 초과 → parsec.exe subprocess가 overflow →
bitbucket integration 테스트 5개 panic.

.cargo/config.toml에 Windows 타겟 한정 `/STACK:16777216` 추가.
macOS/Linux 기본은 이미 8MB라 변경 영향 없음.

Co-Authored-By: Pochacco <noreply@anthropic.com>

---------

Co-authored-by: Pochacco <noreply@anthropic.com>
…ease job) (#342)

* release: v0.5.0 — The visualization release (#340)

* chore(v0.5): roadmap section + ship gh auth token fallback (#281) (#289)

* fix(ship): fall back to gh auth token (parity with parsec doctor) (#281)

parsec ship 이 PARSEC_GITHUB_TOKEN / GITHUB_TOKEN / GH_TOKEN env var 모두 비어있을 때
PR 생성을 거부했지만 parsec doctor 와 tracker 레이어는 이미 `gh auth token` fallback
적용. parity 깨져 사용자가 수동 `gh pr create` 로 추가 작업 필요.

해결:
- src/env.rs: github_token() 의 4번째 우선순위로 gh_auth_token() 추가. 신규
  gh_auth_token() helper 는 `gh auth token` shell out — 실패 시 None (binary 없음 /
  exit code != 0 / non-UTF8 / 빈 출력 모두 graceful).
- src/github/mod.rs: resolve_github_token 의 env-var/gh fallback 을 GitHub host
  (github.com / *.ghe.com / *.github.* GHE) 에만 적용. 신규 is_github_host() helper.
  Bitbucket / GitLab remote 가 `gh auth login` 한 환경에서 GitHub 토큰을 잘못 픽업하지
  않도록 가드.
- src/cli/commands/doctor.rs: 중복 `gh auth token` shell-out 코드 제거 → env::gh_auth_token()
  공통 helper 호출. parity at the helper level.

신규 테스트 (src/env.rs): github_token_priority_order — PARSEC > GITHUB > GH 우선순위
+ 빈값 fallback 4 시나리오 sequential 검사. EnvGuard 로 process-wide env 보존+복원.
gh_auth_token_returns_option_string_or_none — gh binary 가용성에 무관하게 trim 보장.
github_token_returns_none_when_all_missing_and_gh_fails — env 모두 미설정 시 None
또는 valid Some 모두 허용 (CI 와 dev 환경 양립).

검증:
- cargo test: 79 tests PASS (env tests 6 + integration 73)
- cargo clippy --all-targets -- -D warnings: clean
- cargo fmt --check: clean
- bitbucket integration tests: 5/5 PASS (이전 발견된 host-gated 이슈 해결)

회귀 위험: 매우 낮음
- 환경에 gh CLI 미로그인 / 미설치 → 기존과 동일 (None 반환)
- 환경에 gh 로그인됨 + GitHub remote → 신규 fallback 활용 (issue #281 의도)
- 환경에 gh 로그인됨 + Bitbucket/GitLab remote → is_github_host 로 차단, 기존과 동일

Closes #281

* docs(v0.5): open roadmap milestone — visualization release vision

v0.5 마일스톤 공식 출발 마커. README 와 CHANGELOG 양쪽에 향후 비전 명시.

README.md (## Roadmap 섹션 신설, ## Why use it 과 ## Install 사이):
- vision tagline: "parsec = AI agents + human devs both — worktree-native git CLI"
- 4단계 milestone:
  · v0.4.0 ✅ Released (2026-05-04): Multi-forge + multi-tracker foundation
  · v0.5 🚧 Next — _The visualization release_:
    smartlog · TUI dashboard · speculative merge · parsec test · AI PR descriptions
  · v1.0 🔜 — _AI-Native Standard_:
    MCP server signature, Claude/Cursor/Copilot 가 parsec 을 first-class tool 로 invoke
  · v2.0+ 🔮 — _Ecosystem Hub_: plugins · VS Code extension · Linear tracker
- v0.5 milestone link (github.com/erishforG/git-parsec/milestone/3)

CHANGELOG.md (## [Unreleased] 확장):
- ### Added: v0.5 milestone opened, README Roadmap 참조
- ### Fixed: #281 ship gh auth token fallback 노트 (별 commit ae1a2d3 와 동일 entry)

회귀 위험: 0 (문서 변경만)

* fix(env): serialize env-touching tests via process-wide mutex (Windows CI)

PR #289 Windows CI 1건 fail. macOS / Ubuntu Test 통과, Windows Test 만 실패.

원인:
- env::tests 의 github_token_priority_order 와 github_token_returns_none_when_all_
  missing_and_gh_fails 가 cargo test 병렬 실행 시 process-wide env vars 를 race.
- priority_order 가 PARSEC=p / GITHUB=g / GH=h 셋업 후 assert 사이에 sibling 테스트의
  EnvGuard::new() 가 모든 env 를 clear → assert 가 PARSEC 못 보고 GH=h 반환.
- macOS/Ubuntu 는 timing 우연히 안전, Windows 는 다른 thread scheduling 으로 race
  발현 (Some("h") vs Some("p") at src/env.rs:205).

수정:
- std::sync::OnceLock<Mutex<()>> 의 env_lock() 신규 — env 만지는 테스트들 직렬화.
  std 만 사용 (외부 deps 추가 X 제약 준수).
- github_token_priority_order 와 github_token_returns_none_when_all_missing_and_gh_fails
  를 단일 함수 github_token_priority_order_and_fallback 로 통합 + env_lock() 의
  Mutex guard 획득. 5 시나리오 (PARSEC 우선 / GITHUB / GH / 빈값 / 모두 미설정) 직렬 실행.
- gh_auth_token_returns_option_string_or_none 은 env 미터치라 lock 불필요 — 그대로 유지.
- production 로직 (env::github_token / env::gh_auth_token) 변경 0.

검증:
- 로컬 cargo test 78 PASS (env tests 5 + integration 73), clippy clean, fmt clean.
- Windows CI 검증은 force-push 후 PR #289 워크플로우에서 확인.

* [245] feat(smartlog): skeleton — DAG data model + ASCII tree + JSON output (#305)

Phase 1 of #245. Establishes the command surface and rendering path
without any forge-side enrichment.

Adds `parsec smartlog` (alias `sl`):
- `SmartlogNode` per active worktree: ticket, branch, base, commits,
  plus `pr` / `ci` placeholder fields gated on `skip_serializing_if`
  so the JSON output stays clean until follow-up PRs populate them.
- `collect_commits` shells out to `git log <base>..<branch>` (no
  `git2` dependency — matches the rest of `git/`). Soft-fails per
  worktree so a corrupt worktree can't take the whole command down.
- `render_text` groups nodes by base branch and draws ASCII tree
  glyphs (○ │ ├─● └─). Returns the rendered string for testability.
- `--json` emits the same structure for tooling.
- `--depth N` caps commits per worktree (default 10).

Out of scope for this PR (follow-ups on the same epic):
- PR overlay (open/draft/merged)
- CI overlay (passed/failed/running)
- Review state (approved / changes requested)
- Stack relationship visualization
- Color / smarter wrapping

Tests (9 new in `cli::commands::smartlog::tests`):
- `parse_commit_line` happy path + tab-in-subject + garbage + empty SHA
- `render_text` empty / single / no-commits / multi-base grouping
- JSON serialization omits placeholder overlay fields

Smoke run on parsec's own worktrees produces:
  ○ develop (base)
  ├─● 207 #207 [feature/207]
  │  └─ (no commits since develop)
  └─● 279 #279 [feature/279]
     └─ (no commits since develop)

* [303] refactor(errors): adopt 3-line standard (error / caused by / help) (#306)

* [303] refactor(errors): adopt 3-line standard (error / caused by / help)

Issue #303. Add the infrastructure for the standard error format and
wire main.rs to render it. Existing call sites keep rendering as a
single line — migration is gradual (see docs/error-format.md).

Changes:
- `ParsecError` gains `caused_by: Option<String>` and `help: Option<String>`
  fields plus builder-style setters (`with_caused_by`, `with_help`).
  `Display` now writes one to three lines depending on which fields are
  populated.
- `JsonError` gains the same two fields with `skip_serializing_if =
  "Option::is_none"` so existing `--json` consumers see no schema change.
- `extract_full(&anyhow::Error) -> Option<&ParsecError>` helper for new
  callers; the legacy `extract_code` is kept untouched.
- `main.rs` prefers the typed error: when the error is a `ParsecError`,
  print it directly (its `Display` already includes the `error:` prefix
  + code); otherwise fall back to the legacy single-line `error: {err:#}`.
- `bail_code!` macro unchanged (for the "summary only" case).
- `docs/error-format.md` documents the format, builder API, JSON shape,
  recipes, and what NOT to do.

Tests: +9 in `errors::tests` covering 1/2/3-line display, help-only,
extract_full happy/None, backward-compat extract_code, JSON skip-if-none,
JSON with-fields, bail_code macro round-trip. Full suite 53 + 5 + 40 =
98 pass, fmt clean.

Migration: any existing `ParsecError::new(...)` site can opt in by
chaining `.with_caused_by(...)` and/or `.with_help(...)`. Prioritize
cli/commands/ and worktree/ first (highest user contact).

* [303] chore(errors): allow dead_code on Phase 1 builder + legacy extract_code

Clippy `-D warnings` flagged `with_caused_by`, `with_help`, and
`extract_code` as never-used. Phase 1 of #303 is the infra-only PR —
call sites land in follow-up PRs. Annotation matches the existing
`#[allow(dead_code)]` on `ErrorCode` for the same forward-looking reason.

* ci(windows): add VS2026 pre-validation job (#307) (#311)

Adds an informational windows-2025-vs2026 job that runs cargo build/test
on the new Visual Studio 2026 default image ahead of the GitHub Actions
runner migration window (2026-06-08 ~ 06-15).

continue-on-error: true keeps it advisory only — main matrix stays gated
on existing windows-latest. After the migration window closes we either
delete this job (if main matrix passes) or pin windows-2022 here (if it
fails).

Refs: #307

* feat(completion): hidden __complete subcommand foundation (#291) (#312)

Adds `parsec __complete <worktrees|branches>` — a hidden subcommand that
shell completion scripts can call to enumerate candidates dynamically.
Failure paths (no repo / no config) silently emit nothing so completion
never errors at the prompt.

Also adds `git::list_local_branches`, a helper for enumerating local
branch names via `git for-each-ref refs/heads/`.

This is the **foundation only**. The follow-up work — post-processing
clap-generated completion scripts (zsh/bash/fish) so that ticket-shaped
arguments call `parsec __complete worktrees` and branch-shaped arguments
call `parsec __complete branches` — lands in a separate PR.

Refs: #291

* test(cli): compress / config schema / log --export 통합 테스트 추가 (#315)

* test(cli): add integration tests for compress, config schema, log --export

Cover three commands added in v0.4.0 that had zero test coverage:
- test_compress_nothing_to_do: single-commit worktree exits cleanly
- test_compress_squashes_commits: 2-commit branch is reduced to 1
- test_config_schema_outputs_json: output is valid JSON Schema
- test_history_log_export_empty: empty log exits 0 with no stdout

Closes #314

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* ci: re-trigger Branch Policy (base now develop)

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>

* docs(changelog): [Unreleased]에 smartlog·complete·errors·win-ci 항목 추가 (#317)

develop에 머지됐지만 CHANGELOG.md [Unreleased]에 누락된
항목 4개를 추가한다:

- parsec smartlog (alias sl): commit DAG 시각화 (#245, #305)
- parsec __complete: 동적 shell completion 헬퍼 (#291, #312)
- 에러 메시지 3줄 표준화 (error/caused by/help) (#303, #306)
- Windows VS2026 pre-validation CI job (#307, #311)

Closes #316

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(cli): parsec smartlog / sl 통합 테스트 추가 (#318) (#319)

parsec smartlog (#305)과 sl 별칭이 develop에 머지됐지만
CLI 통합 테스트가 전혀 없었음. 5개 시나리오 추가:

- test_smartlog_empty_repo: 빈 repo → 'No active worktrees' 확인
- test_sl_alias_works_like_smartlog: sl == smartlog 동일 출력 확인
- test_smartlog_json_empty_is_array: --json 빈 repo → [] JSON 배열
- test_smartlog_shows_worktree: worktree 1개 → 티켓·(base) 마커 표시
- test_smartlog_json_one_worktree: --json 1 worktree → 필드 검증
  (ticket, branch, base_branch, commits, pr/ci 미노출)

Closes #318

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(commands): diff·history 모듈 RustDoc 추가 (#321)

diff.rs, history.rs에 module-level(//!) 및 function-level(///) RustDoc을
추가. 인접한 smartlog.rs·complete.rs와 일관성 맞춤.

- diff.rs: //! 모듈 헤더(diff/conflicts/sync 역할·관련 이슈), pub async fn
  diff/conflicts/sync에 파라미터·출력모드·동작 설명 추가
- history.rs: //! 모듈 헤더(OpLog·ExecLog 구조 설명), pub async fn
  log/log_export/undo에 동작·edge-case 설명 추가

프로덕션 코드 변경 없음 (주석 전용).

Closes #320

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(commands): stack·ci 모듈 RustDoc 추가 (#323)

stack.rs: //! 모듈 헤더 + stack/stack_sync/stack_submit 함수 doc
ci.rs: //! 모듈 헤더 + ci/fetch_bitbucket_ci 함수 doc

프로덕션 코드 변경 없음 — 주석 73줄 추가만.

Closes #322

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(health): parsec health Phase 1 — lock/uncommitted/stale check skeleton (#324) (#325)

Add `parsec health` command that scans all active worktrees for three
lightweight health indicators:

- has_lock     — .git/index.lock exists (interrupted git process)
- uncommitted  — count of staged + unstaged files
- stale        — last commit older than 7 days

Output (human mode): colored table with ✓/⚠/✗ per worktree and a
summary line. JSON mode emits a structured array with `all_healthy` flag.

Files changed:
- src/cli/commands/health.rs       (new, ~99 lines)
- src/cli/commands/mod.rs          (+2 lines, re-export)
- src/cli/mod.rs                   (+11 lines, Health variant + dispatch)
- src/output/mod.rs                (+15 lines, HealthRecord + dispatch_output!)
- src/output/human.rs              (+66 lines, colored table renderer)
- src/output/json.rs               (+34 lines, JSON renderer)

CI-status overlay deferred to Phase 2 (depends on #309/#310).
All checks are read-only; no worktree state is modified.

Closes #324
Refs #299

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>

* test(health): parsec health CLI 통합 테스트 5개 추가 (#324) (#326)

Phase 1 구현(#325)을 커버하는 통합 테스트:

- test_health_empty_repo: 빈 repo → 'No active worktrees.' 확인
- test_health_empty_repo_json: 빈 repo → --json 시 '[]' 출력 확인
- test_health_shows_worktree: 워크트리 1개 → 티켓명 포함 출력 확인
- test_health_json_one_worktree: --json 구조 검증
  (worktrees 배열, all_healthy 불리언, ticket/has_lock/uncommitted/stale_days/stale 필드)
- test_health_exit_zero_with_issues: lock 파일 존재해도 exit 0 (정보성 only)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(smartlog): Phase 2 — PR/CI status overlay (#327)

* test(health): parsec health CLI 통합 테스트 5개 추가 (#324)

Phase 1 구현(#325)을 커버하는 통합 테스트:

- test_health_empty_repo: 빈 repo → 'No active worktrees.' 확인
- test_health_empty_repo_json: 빈 repo → --json 시 '[]' 출력 확인
- test_health_shows_worktree: 워크트리 1개 → 티켓명 포함 출력 확인
- test_health_json_one_worktree: --json 구조 검증
  (worktrees 배열, all_healthy 불리언, ticket/has_lock/uncommitted/stale_days/stale 필드)
- test_health_exit_zero_with_issues: lock 파일 존재해도 exit 0 (정보성 only)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(smartlog): Phase 2 — PR/CI status overlay (Refs #245)

Phase 1 (#305) skeleton에서 `SmartlogNode.pr` 가 placeholder로 남아있던 걸
실제 GitHub PR/CI 데이터로 채움. Issue #245 의 예시 (`[PR #42 ✓ CI passed,
✓ approved]`) 가 이제 ASCII 트리에 그대로 렌더링됨.

## 변경
- `SmartlogPrOverlay` struct 신설 (number/state/ci_status/review_status/url)
- `smartlog()` 가 GitHubClient 통해 brach → PR 매칭 + PrStatus 조회 후
  node.pr 채움. 토큰 없거나 비-GitHub remote거나 HTTP 실패 = 그냥 overlay
  생략 (best-effort, 명령 실패 안 함)
- `--no-overlay` 플래그 추가 (강제 offline 모드)
- ASCII 렌더러: ticket 라인 아래 `├─ [PR #N ● open ✓ CI ✓ approved]` 한 줄
- 글리프 규칙: 기존 `parsec pr status` / `parsec ci` 와 동일 (✓/✗/●/○)

## CI 필드는?
`SmartlogNode.ci` 는 일단 None 유지. Phase 2 는 CI 요약을 overlay 안에
포함시켜 한 줄로 표시 (스마트로그 본질은 한눈 — per-check 디테일은
`parsec ci` 가 이미 담당).

## 드라이브-바이
tests/cli_tests.rs:1725 에 `assert_eq!(bool, false)` clippy 경고 (#326
회귀) → `assert!(!...)` 로 수정. develop 의 clippy strict 빌드 회복.

## 테스트
- 신규 unit 5개 (format_pr_badge × 3 + render_text overlay + JSON 직렬화)
- 기존 9개 smartlog unit + 5개 통합 테스트 모두 통과
- cargo build / clippy -D warnings / fmt --check / test 전체 clean

## 다음 Phase 힌트
- Phase 3: per-worktree filtering (`--ticket CL-2283` 등)
- Phase 4: stack 관계 시각화 (PR base = 다른 PR head)
- Phase 5: review state 색상 강조 (terminal color)

Refs #245

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(completion): Phase 2 — dynamic zsh/bash/fish shell scripts (Refs #291) (#328)

Phase 1 (#312) 가 `parsec __complete <kind>` 내부 명령을 만들어 shell completion
스크립트가 동적으로 worktree/branch 후보를 가져올 수 있게 했음. 이번에는 그 위에
실제 zsh/bash/fish 스크립트 3개를 추가해서 사용자가 sourcing 만 하면
`parsec switch <Tab>` 처럼 live ticket 자동완성을 받을 수 있게 함.

## 변경
- `completions/_parsec` (zsh, #compdef) — `_parsec_worktrees` / `_parsec_branches`
  helper + 모든 주요 subcommand 의 positional/option 자동완성
- `completions/parsec.bash` — `complete -F _parsec parsec`. bash-completion
  의존 (`_init_completion`). prev word 기반 dispatch + `compgen -W`
- `completions/parsec.fish` — `__fish_seen_subcommand_from` 기반.
  per-subcommand 옵션 (`--base`, `--on`, `--branch`) 도 동적 branch/worktree
  후보 연결
- README "Install > Shell completion" 섹션 추가 (3개 shell install 명령)

## 커버 범위 (Tier 1 + 2)
- ticket 받는 subcommand: start, switch, ship, open, clean, status, ticket,
  pr-status, ci, merge, diff, sync, log, compress, adopt, rename
- branch 받는 옵션: `start --base|--on|--branch`, `ship --base`, `adopt --branch`
- smartlog: `--depth`, `--no-overlay` (PR #327 와 호환)

## __complete kind 추가
없음. Phase 1 의 `worktrees` / `branches` 두 개로 충분 — future Phase 3 에서
필요하면 추가 (예: `tickets` 트래커, `reviewers` GitHub 사용자).

## 드라이브-바이
PR #327 에서 같이 잡았던 `tests/cli_tests.rs:1725` clippy 회귀 (#326)
develop 머지 전이라 또 한 번 적용. PR #327 머지되면 충돌 안 남.

## 테스트
- 신규 4개 통합 테스트:
  - `completion_zsh_present_and_dynamic` — `#compdef parsec` + `__complete` 호출 + 핵심 sub 7개
  - `completion_bash_present_and_dynamic` — `complete -F _parsec parsec` + 동일
  - `completion_fish_present_and_dynamic` — `__parsec_worktrees` 함수 + 동일
  - `completion_scripts_reference_phase1_subcommand_signature` — 스크립트가
    Phase 1 가 지원하지 않는 kind 부르지 않는지 (silent fail 방지)
- 전체 62 통합 테스트 + smartlog 14 단위 + health 5 통과
- cargo build / clippy -D warnings / fmt --check 전부 clean

## 다음 Phase 힌트
- Phase 3: `__complete tickets` (트래커 미해결 티켓), `__complete reviewers`
  (GitHub mention)
- Phase 4: shell auto-install hook (parsec init 에서 자동 설치 옵션)

Refs #291

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>

* feat(health): Phase 2 — CI status overlay + configurable stale threshold (Refs #299)

## 무엇
parsec health Phase 2: GitHub CI 상태 오버레이 + 설정 가능한 stale 임계값.

## 변경
- health.rs: --stale-days <N> 플래그로 stale 임계값 설정 (기본 7일)
- health.rs: --no-overlay 플래그로 오프라인 모드 지원
- health.rs: fetch_ci_overlay() — 브랜치 → PR 번호 → CI 상태 (best-effort)
- output/mod.rs: HealthRecord에 ci_status: Option<String>, pr_number: Option<u64> 추가
- output/human.rs: CI 상태를 색상 아이콘으로 표시 (✓/✗/● CI)
- output/json.rs: ci_status, pr_number, ci_failing 필드를 JSON 출력에 포함
- cli/mod.rs: Health 명령을 struct variant로 변경 (--stale-days, --no-overlay)
- tests/cli_tests.rs: Phase 2 플래그 검증 테스트 3개 추가 (8/8 통과)

## 다음 Phase 힌트
Phase 3: threshold config (parsec.toml [health] stale_days), 경고 exit code 옵션

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(reviews): Phase 1 — unified PR review table across worktrees (Refs #301) (#331)

Adds `parsec reviews` (alias `rv`) — a new command that scans every
active worktree, resolves its open GitHub PR by branch name, and prints
a unified review table with per-PR review decisions and CI status.

## What
- New `src/cli/commands/reviews.rs` with `reviews()` async function
- `ReviewEntry` struct added to `src/output/mod.rs`
- Human table renderer in `src/output/human.rs` (color-coded review/CI badges)
- JSON array renderer in `src/output/json.rs`
- `Reviews` CLI variant wired in `src/cli/mod.rs` (alias `rv`)
- 3 unit tests for ReviewEntry construction

## Phase 2 hint
Add `--requested` flag: use GitHub Search API
(`/search/issues?q=review-requested:{login}`) to show PRs from *others*
where the current user is a requested reviewer.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(sync): stale-threshold filter, dry-run behind-count, conflict hint (#290)

* feat(sync): stale-threshold filter, dry-run behind-count, conflict hint (#290)

- Add --min-behind N flag (default: 1) to skip worktrees fewer than N
  commits behind origin/<base_branch>; skipped entries shown in output
- dry-run now fetches behind-count and reports per-worktree before exit
- Conflict detection: append "(conflict detected — resolve manually)"
  hint to failed sync reason when git output contains "conflict"
- Extend print_sync signature with skipped: &[(String, u32)] across
  human/json/mod output layers; stack_sync passes &[] (no change)
- Add 3 CLI integration tests: up-to-date skip, dry-run output, rebase

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* style: cargo fmt

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* feat(smartlog): Phase 3 — worktree filter, ANSI color, stack indicator (#333)

Refs #245

## What
- Add `--worktree <pattern>` flag (-w) to `parsec smartlog` / `sl`: case-
  insensitive substring match on ticket or branch name so users can focus on
  a subset of worktrees without noise from unrelated ones.
- ANSI color in the PR/CI badge: green for success/approved/merged, red for
  failure/changes-requested, yellow for pending, blue for open PR, dim for
  draft/closed.  Automatically disabled when `NO_COLOR` is set or stdout is
  not a TTY; force-enable via `PARSEC_COLOR=always`.
- Stack indicator: when a worktree's base branch matches another active
  worktree's branch name, the base-group header now reads
  `○ <branch> (stacked on <ticket>)` instead of `(base)`, making stacked-PR
  flows immediately visible without extra commands.

## Tests added (5 new)
- `worktree_filter_matches_ticket_substring`
- `worktree_filter_branch_fallback`
- `stack_indicator_appears_when_base_is_sibling_branch`
- `color_badge_contains_ansi_codes_when_enabled`
- `color_badge_failure_ci_is_red`

All 138 tests pass (cargo build / clippy / fmt / test ✓).

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(reviews): Phase 2 — --requested flag via GitHub Search API (Refs #301) (#334)

Add `--requested` flag to `parsec reviews` (alias `rv -r`) that shows
open PRs *from others* in this repo where the authenticated user is
a requested reviewer.

## What changed
- `src/github/mod.rs`: add `get_authenticated_user()` (GET /user) and
  `search_review_requested_prs(login)` (GET /search/issues with
  review-requested query). Reqwest .query() handles URL encoding —
  no new dependencies.
- `src/cli/commands/reviews.rs`: split into `collect_authored_reviews`
  (Phase 1 logic) and `collect_requested_reviews` (Phase 2). Each
  returns Vec<ReviewEntry>; the caller merges and dispatches.
- `src/cli/mod.rs`: add `requested: bool` field to `Reviews` variant,
  pass through to command handler.
- 4 unit tests: existing 3 preserved + 1 new for reviewer-mode ticket placeholder.

## Phase 3 hint
- Add `--all` flag to include closed/merged PRs.
- Add author filter (`--author`) to narrow results.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(conflicts): --simulate flag for line-level speculative merge (Closes #246) (#335)

`parsec conflicts --simulate`로 실제 in-memory three-way 머지를 수행해 라인-레벨
충돌을 사전 탐지. 기존 filename overlap 휴리스틱 (`parsec conflicts`)을 보완.

## 추가 모듈
- `src/conflict/simulator.rs` (240줄)
  - `MergeSimulation { vs_base, cross, skipped }` 결과 구조
  - `simulate(repo, &workspaces)` 진입점
  - Pass 1: 각 워크트리 HEAD vs origin/<base> (`merge-base` → fallback to local base)
  - Pass 2: 워크트리 페어 cross-simulate
  - 도구: `git merge-tree --write-tree --name-only --merge-base=<mb>` (git 2.38+)
  - read-only — 워킹디렉터리/index 무수정, merge tree 객체는 DB에 남되 참조 없음

## CLI
- `Command::Conflicts` variant에 `--simulate` bool 플래그 추가
- 디스패치 시 simulate true이면 `conflict::simulate(...)`, false면 기존 `conflict::detect(...)`

## Output
- Human: 'Worktree → base conflicts' + 'Cross-worktree conflicts' 섹션, 파일 목록 ●로 표시
- JSON: `{ vs_base: [...], cross: [...], skipped: [...] }` 머신 readable

## 가드레일
- WorkspaceStatus::Active 만 처리
- merge-base 계산 실패시 skipped로 다운그레이드 (전체 리포트 중단 방지)
- `merge-tree` 비-0 exit + 빈 출력은 transient로 간주

## 검증
- cargo build clean
- cargo clippy -D warnings clean
- cargo fmt clean
- cargo test: 66 lib + 5 simulator + 71 cli = 142 통과 (이전 138 + 신규 4 simulate)

## 신규 테스트 (tests/cli_tests.rs)
- test_conflicts_simulate_empty_repo
- test_conflicts_simulate_json_empty_is_object
- test_conflicts_simulate_single_clean_worktree
- test_conflicts_simulate_detects_cross_worktree_line_conflict (실제 충돌 시드)

v0.5 마일스톤.

Co-authored-by: Pochacco <noreply@anthropic.com>

* feat(test): parsec test — parallel test runner with tree-hash caching (Closes #247) (#336)

* feat(test): parsec test — parallel test runner with tree-hash caching

Implements `parsec test` (issue #247): runs a configurable shell command
inside one or every parsec-managed worktree, with optional parallelism
(`--jobs N`) and tree-hash result caching (`--cache`).

- New `[test]` section in ParsecConfig (command / jobs / cache defaults).
- New `Command::Test` variant with --all / --jobs / --cache / --command
  flags plus auto-detect of the current worktree from CWD.
- Cache files live under `<repo>/.parsec/test-cache/<tree-hash>.json`;
  only successful runs are persisted.
- Output dispatched through `print_test_results` (human table + JSON
  array with from_cache / exit_code / duration_ms / stdout_tail).
- Tail of stdout/stderr (40 lines) surfaced on failure for fast triage.
- Six new CLI integration tests covering help, single-worktree, --all,
  cache hit replay, non-zero propagation, and parallel completion.

Closes #247

* fix(test): cross-platform shell + Windows test gating

Windows CI fail 원인: bash가 WSL로 해석되는데 distro 미설치 → exec 실패.

- 러너: `bash -c` → 플랫폼별로 `sh -c` (Unix) / `cmd /C` (Windows)
- 테스트 명령: `true` → `exit 0` (cmd.exe + sh 양쪽 동작)
- `test_test_jobs_parallel_completes`는 sleep 의존 → `#[cfg(unix)]` 게이트

cargo test 73 cli + 5 bitbucket + 69 unit = 147 통과.

Co-Authored-By: Pochacco <noreply@anthropic.com>

---------

Co-authored-by: Pochacco <noreply@anthropic.com>

* feat(dashboard): interactive TUI dashboard for worktrees, CI, and PRs (#337)

Introduce `parsec dashboard` (alias `dash`), a `ratatui` + `crossterm`
based terminal UI that aggregates worktree, CI, and GitHub PR status into
a single live view.

Layout (three panes + status bar):
  - Worktrees pane (top-left): list of every active worktree with a
    color-coded CI dot, ticket ID, title/branch, and status.
  - CI pane (top-right): per-worktree `PR #N · ✓/✗/●` summary.
  - PRs pane (bottom): table — PR · title · state · review · CI.
  - Status bar: key hints + last-update timestamp + last-error badge.

Concurrency: a single background `tokio::task` refreshes the shared
`Arc<Mutex<DashboardSnapshot>>` every `--refresh` seconds (default 10).
The UI loop never blocks on network — it redraws the latest snapshot
on each tick or key event via `tokio::select!`.

Keys: `q` / Esc quit · `r` force refresh · `?` / F1 help overlay ·
`↑/↓` (or `j/k`) move selection · Ctrl-C quit.

Robustness:
  - Terminal state (alternate screen + raw mode) is restored by a
    `Drop` guard that runs on every exit path, including panic.
  - `--no-overlay` (or missing GitHub token) renders `–` placeholders
    instead of erroring.
  - `--json` / `--quiet` are rejected early with an actionable message
    pointing to `parsec list --json` / `parsec reviews --json`.

Tests: four new integration tests for help text (both `dashboard` and
`dash`), `--json` rejection, and `--quiet` rejection, plus five new
unit tests for the rendering helpers.

Deps: ratatui 0.28, crossterm 0.28.

Closes #248

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>

* release-prep: bump version + CHANGELOG + README for v0.5.0 (#339)

* chore(release): v0.5.0 — visualization release

- Cargo.toml: 0.4.0 → 0.5.0 (release.yml이 main push 시 자동 tag/publish 트리거)
- CHANGELOG: Unreleased → [0.5.0] 정리 (v0.5 마일스톤 16개 항목 반영)
- README: Roadmap v0.5.0 ✅ Released 마킹, v1.0 'Next'. 신규
  'Visualization & power-user tools' 섹션 (8개 신규 명령). command count 33+
- docs/llms.txt: 버전 0.5.0, v0.5 명령 quick reference

cargo build/clippy/fmt clean · test 142/142.

Co-Authored-By: Pochacco <noreply@anthropic.com>

* ci: RUST_MIN_STACK=8MB to fix Windows stack overflow after TUI deps landed

#248 (TUI dashboard) added ratatui + crossterm. Windows 기본 main-thread
stack 1MB가 tokio + reqwest + ratatui + crossterm 결합 후 overflow → bitbucket
integration test 5개 panic.

워크플로우 env에 RUST_MIN_STACK=8388608 (8MB) 추가. 모든 test/build job에
적용. macOS/Linux는 변경 영향 없음.

Co-Authored-By: Pochacco <noreply@anthropic.com>

* build: Windows linker /STACK:16MB — fix bitbucket integration test overflow

RUST_MIN_STACK은 Rust 스레드만 영향. Windows main-thread stack(기본 1MB)은
linker 옵션이 결정. v0.5 TUI dashboard 진입 후 ratatui + crossterm +
tokio + reqwest 결합으로 1MB 초과 → parsec.exe subprocess가 overflow →
bitbucket integration 테스트 5개 panic.

.cargo/config.toml에 Windows 타겟 한정 `/STACK:16777216` 추가.
macOS/Linux 기본은 이미 8MB라 변경 영향 없음.

Co-Authored-By: Pochacco <noreply@anthropic.com>

---------

Co-authored-by: Pochacco <noreply@anthropic.com>

* chore: back-merge main into develop (sync for release PR #340) (#341)

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>

* docs: snapshot versioned docs for v0.5.0

Manual replay of release.yml `Snapshot Versioned Docs` job that failed on
v0.5.0 release run (couldn't direct-push to protected main branch).

- docs/v/0.5.0/{index.html, guide/index.html, reference/index.html} 신규 — latest docs를 sed transform (data-doc-version, noindex, /v/0.5.0/ prefix)
- docs/versions.json: latest 0.4.0 → 0.5.0, versions list 맨 앞 추가
- docs/sitemap.xml: v0.5.0 3개 URL entry 추가

이후 부터는 release.yml 패치로 자동화될 예정 (별도 PR).

Co-Authored-By: Pochacco <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…sh (#343)

v0.5.0 release run의 `Snapshot Versioned Docs` job이 main 브랜치 protection
(`Changes must be made through a pull request`) 때문에 직접 push 실패.

## 변경
- `.github/workflows/release.yml`: `git push origin main` → `peter-evans/create-pull-request`로 `docs/snapshot-v<ver>` 브랜치 자동 생성 + PR 오픈. `pull-requests: write` 권한 추가.
- `.github/workflows/ci.yml`: Branch Policy가 `docs/snapshot-v*` 브랜치도 main에 머지 허용 (data-only 변경이므로 develop 우회 안전).

## 효과
다음 릴리스부터 자동으로 `docs/snapshot-vX.Y.Z` 브랜치 + auto-snapshot 라벨이 붙은 PR이 생성됨. Eric이 머지하면 versioned docs가 main에 반영. push 실패 0.

Co-authored-by: Pochacco <noreply@anthropic.com>
@erishforG erishforG merged commit eee6754 into main Jun 3, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant