Skip to content

release: v1.0.0 - #452

Merged
erishforG merged 109 commits into
mainfrom
develop
Sep 19, 2026
Merged

erishforG merged 109 commits into
mainfrom
develop

Conversation

@erishforG

Copy link
Copy Markdown
Owner

Summary

  • promote the integrated v1.0.0 release to main
  • ship MCP server support and the completed v1 roadmap
  • align README, changelog, CLI help, and release metadata
  • mark v1.0 as the final planned feature release

Integration trail

Verification

  • cargo fmt --all -- --check
  • cargo clippy --all-targets -- -D warnings
  • cargo test --locked --all-targets (419 tests)
  • cargo publish --dry-run --locked
  • GitHub CI passed on Linux, macOS, Windows, security audit, and VS2026 pre-validation

Merging this PR triggers the v1.0.0 tag, crates.io publish, GitHub Release binaries, and versioned docs snapshot.

erishforG and others added 30 commits April 29, 2026 23:24
…#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>
erishforG and others added 29 commits September 2, 2026 09:44
…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>
…efs #302 (#437)

Auto-merged by parsec-daily-improvement cron. All CI checks passed. Gates: CI CLEAN · diff matches #302 · no breaking changes · 10 unit tests.
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: 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
@erishforG
erishforG merged commit c56c884 into main Sep 19, 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