Skip to content

release: promote v1.0.0 to develop - #450

Merged
erishforG merged 85 commits into
developfrom
release/1.0
Sep 19, 2026
Merged

erishforG merged 85 commits into
developfrom
release/1.0

Conversation

@erishforG

Copy link
Copy Markdown
Owner

Summary

Promote the validated v1.0.0 release branch into develop so the repository returns to a single release lineage.

Evidence

PR #449 integrated the final develop line into release/1.0. Its Linux, macOS, Windows, Clippy, formatting, test, security audit, and VS2026 checks all passed.

Next

After this PR lands, develop will be promoted to main to trigger the v1.0.0 release workflow.

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>
- 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>
Refs #293

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
erishforG and others added 28 commits August 18, 2026 09:57
…395)

Implement the `health_check` MCP tool handler in `src/mcp/tools/health.rs`,
replacing the Phase 1 stub with real synchronous health diagnostics.

## What

- `check()` iterates active worktrees (all, or one if `ticket` supplied)
- Per-worktree: `has_lock` (index.lock detection, handles gitdir pointer
  format), `uncommitted` count via `git::get_uncommitted_files`,
  `stale_days` from last-commit timestamp
- `healthy` boolean = no lock + no uncommitted + not stale
- Respects caller-supplied `stale_days` threshold (default: 7 days)
- CI overlay deferred: `ci_overlay: false` until async bridge is wired (Phase 25)
- Updated `stdio_smoke.jsonl`: fixture promoted from stub/isError=true to
  real/isError=false asserting `"records"` + `"ci_overlay"` schema keys

## Tests (5 new unit tests)

- empty worktree list → count: 0
- worktree list → correct ticket, healthy/lock/uncommitted fields
- custom `stale_days` arg respected in threshold field
- no lock + no uncommitted → default healthy path
- invalid ticket format → returns error

Refs #293

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire the `smartlog` MCP tool from its Phase 1 stub to a real synchronous
implementation that collects the worktree commit DAG without requiring an
async GitHub client.

## What
- Replace the `not_implemented` stub in `src/mcp/tools/smartlog.rs` with
  a full handler that reads active worktrees via `WorktreeManager` and
  collects per-worktree commits using the same `git log` format
  (`%h\t%s\t%an\t%aI`) as the CLI `parsec smartlog` command.
- `ticket` argument provides case-insensitive substring filtering on ticket
  ID or branch name; `limit` caps commit depth per node (default 10).
- PR/CI overlays remain `false`/`null` — a later phase will wire the async
  GitHub client once the transport boundary is stable.
- Update `stdio_smoke.jsonl` fixture: replace the stub-error assertion with
  a live-success assertion (`isError: false`, `"nodes"` in text).
- Add 4 unit tests: empty-range robustness, envelope shape, filter subset,
  and limit argument.
- Update `src/mcp/mod.rs` phase log.

## Refs
Refs #293

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire the `pr_status` MCP tool stub to a real implementation using the
`gh` CLI. Phase 26 closes the stub and returns live PR state for any
registered worktree without requiring a new external dependency.

## What
- Replace the dead-code stub in `src/mcp/tools/pr.rs` with a working
  synchronous handler backed by `gh pr view --json`.
- GhPrView / GhReview: minimal Deserialize structs for the fields we
  need (number, url, state, isDraft, mergeable, reviewDecision, reviews).
- Delegated PAT forwarded as GH_TOKEN env var when McpContext carries a
  github_token (auth.md Phase 6 contract).
- parse_mergeable: maps the GitHub GraphQL MERGEABLE/CONFLICTING/UNKNOWN
  enum to a plain bool.
- ci_overall field reserved as null (async check-runs bridge deferred).

## Tests (3 new unit tests)
- parse_mergeable_handles_all_variants
- pr_status_rejects_missing_ticket
- pr_status_rejects_invalid_ticket
- pr_status_fails_for_nonexistent_worktree

Refs #293

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire the `reviews` stub to real GitHub PR data via synchronous `gh` CLI
calls. Read-only; no new external dependencies.

## What

- Replace 5-line stub in `src/mcp/tools/reviews.rs` with full implementation
- Support three modes: "authored" (PRs created by @me), "requested" (PRs
  where @me is a requested reviewer), "all" (default, both combined)
- Forward delegated PAT from `McpContext.github_token` via GH_TOKEN env var
- Structured JSON output: `mode`, `total_count`, `authored_count`,
  `requested_count`, `entries[]" with per-PR fields
- 7 unit tests: mode validation, count_reviews(), entry_json() field mapping,
  review_decision defaulting to "pending" when absent

## Pattern

Follows `pr.rs` (Phase 26): synchronous `Command::new("gh")`, no async,
no new Cargo deps, token forwarded via GH_TOKEN.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire the previously-stub `ci_status` tool to real GitHub Actions
check-run data via `gh pr view --json number,statusCheckRollup`.

## What

- Replace the 9-line stub in `src/mcp/tools/ci.rs` with a full
  synchronous implementation that follows the pr.rs / reviews.rs pattern.
- Look up the worktree branch from `WorktreeManager`, then call
  `gh pr view <branch> --json number,statusCheckRollup` to fetch check
  runs.
- Handle both GraphQL `CheckRun` (status/conclusion/detailsUrl) and
  `StatusContext` (state/targetUrl) objects uniformly.
- Derive `overall` as one of: `passing`, `failing`, `pending`,
  `no_checks`.
- Respect `limit` input (default 10, clamped to 1–100).
- Forward `McpContext.github_token` as `GH_TOKEN` for delegated auth.
- Update the Phase history comment in `src/mcp/mod.rs`.
- Add a Phase 28 smoke fixture for `ci_status` with `checks:read` scope
  in `tests/mcp/fixtures/stdio_smoke.jsonl`.

## Tests

- derive_overall: empty / all-passing / any-failure / in-progress / skipped
- status_context: failure/success mapped through state field
- normalise_check_status: all variants
- Handler: missing ticket / invalid ticket / non-existent worktree

All 241 tests pass.

Refs #293

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

Wires the `sync` MCP tool (#293) from a 9-line stub to a full
implementation that rebases or merges a parsec-managed worktree branch
against its base branch.

## Safety model

sync is a mutating tool (mutating: true). Two-key gate prevents
accidental rebases:
- dry_run defaults to true → analysis-only unless caller opts out
- confirm defaults to false → mutation requires dry_run=false AND confirm=true

## Changes

- src/mcp/tools/sync.rs: stub → 430-line implementation
  - ticket validation (alphanumeric-dash, max 128 chars, shell-safe)
  - parse_strategy(): rebase (default) or merge
  - commits_behind(): git rev-list --count HEAD..origin/<base>
  - dry_run path: staleness analysis + advisory message, no mutation
  - mutating path: git fetch_if_remote + git rebase/merge via subprocess
  - 11 inline unit tests covering validation, strategy parsing, and gates
- src/mcp/mod.rs: Phase 29 entry in phase log, update remaining stubs list
- tests/mcp/fixtures/stdio_smoke.jsonl: two Phase 29 fixtures
  (missing-ticket and unsafe-ticket validation paths)

Refs #293

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

Refs #293

Wire the previously-stubbed `worktree_start` MCP tool to
`WorktreeManager::create` using the same dry_run/confirm two-key gate
established by the `sync` tool (Phase 29).

## What changes

- `src/mcp/tools/worktree.rs`: Replace `not_implemented` stub with full
  handler.  When `dry_run=true` the handler returns a preview JSON object
  (branch name, effective base branch, title, parent_ticket) without touching
  git.  When `dry_run=false` AND `confirm=true` the handler calls
  `WorktreeManager::create` and returns the created `Workspace` as JSON.
  Base-branch resolution order: explicit arg → parent worktree branch → config
  default → "main".

- `src/mcp/mod.rs`: Annotate Phase 30 in the module-level phase log;
  update "remaining stubs" comment to `worktree_ship`.

- `tests/mcp/fixtures/stdio_smoke.jsonl`: Update two worktree_start
  fixtures that previously expected `tool_error` (stub era):
    • `tools-call-worktree-start-dry-run-passthrough` → now asserts
      `isError=false` and presence of preview fields.
    • `tools-call-worktree-start-confirmed-passthrough` → arguments
      changed to `{dry_run:true, confirm:true}` (verifies dry_run wins);
      asserts `isError=false` with preview fields (safe for CI, no git ops).

- 7 new unit tests covering: preview response shape, dry_run wins over
  confirm, explicit base, title + parent ticket resolution, empty-ticket
  and path-traversal rejection.

## Next Phase

Phase 31: wire `worktree_ship` — push branch, create/update GitHub PR via
`parsec ship` internals (requires ctx.dry_run gate for push + PR creation).

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

Wire the last remaining MCP stub tool: worktree_ship.

Follows the same dry_run/confirm two-key gate established by sync (Phase 29)
and worktree_start (Phase 30).

## Changes

### src/mcp/tools/worktree.rs
- Replace `worktree_ship` stub with a real handler implementing:
  - `dry_run=true` OR `!confirm` → preview response (branch/base/draft/no_cleanup echoed)
  - `dry_run=false + confirm=true` → push via `WorktreeManager::ship_push` +
    `gh pr create` + optional cleanup via `WorktreeManager::ship_cleanup`
  - Partial-success path when push succeeds but PR creation fails
- Add `create_gh_pr()` helper: calls `gh pr create --json url,number`; falls
  back to `gh pr view` when PR already exists
- Add `find_existing_gh_pr()` helper for the idempotent re-ship case
- 8 new unit tests covering: preview, no-confirm default, dry_run-wins-over-confirm,
  draft flag in message, no_cleanup flag, empty ticket, unsafe ticket, unknown ticket

### src/mcp/mod.rs
- Update Phase log comment: Phase 31 wired, all 10 tools now wired

### tests/mcp/fixtures/stdio_smoke.jsonl
- 3 new fixtures:
  - `tools-call-worktree-ship-confirmation-required`: CONFIRMATION_REQUIRED when no gate key
  - `tools-call-worktree-ship-dry-run-auth-required`: dry_run bypasses confirm gate → AUTH_REQUIRED
  - `tools-call-worktree-ship-confirm-auth-required`: confirm=true → AUTH_REQUIRED (requires_github)

Refs #293

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ocs (Refs #295)

Add 7 end-to-end scenario fixtures (scenario-e2e-*) to stdio_smoke.jsonl
covering the full AI agent workflow: initialize → discover tools →
health_check → worktree_list → worktree_start (dry_run preview) →
worktree_ship (no-auth gate) → worktree_ship (with auth, dry_run).

All fixtures are deterministic (dry_run=true) and machine-independent.
The ship step with auth correctly reaches the tool handler, passing
preflight, then fails on missing worktree (expected tool_error).

Also:
- docs/mcp/clients.md: add 'Typical AI Agent Workflow' table + updated
  Next Phases to reflect Phase 32 shipped.
- docs/mcp/spec.md: replace stale 'Next Phases' with full Phase Status
  table (Phases 1–31 ✅, Phase 32–34 🔲 planned).
- src/mcp/mod.rs: update stale Phase 1 skeleton comment.
- src/mcp/tools/mod.rs: update not_implemented() docstring to remove
  stale #293 phase reference.

Refs #295

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…er · Refs #293

Adds `parsec mcp install --client=<client>` CLI sub-command that
registers git-parsec in a desktop MCP client JSON config file without
disturbing unrelated keys.

## What

- New `src/mcp/install.rs` module:
  - `McpClientTarget` enum (claude-desktop | cursor) with Display + FromStr
  - `config_path()` — platform-specific config file resolution per
    `docs/mcp/clients.md` table (macOS/Windows Claude Desktop, .cursor/mcp.json)
  - `build_server_entry()` — produces {command, args:["mcp","serve"]} entry
  - `merge_server_entry()` — merges only mcpServers.git-parsec; preserves all
    other top-level keys and other mcpServers entries
  - `install()` — reads existing JSON (strict; rejects JSONC), creates
    timestamped .bak-<ts> backup, writes merged config; dry_run prints
    planned JSON to stdout without touching disk
  - 11 unit tests covering merge, build, FromStr, Display, and dry-run path

- `src/cli/mod.rs`: added `McpAction::Install { client, bin_path }` variant
  and dispatch arm; `--dry-run` flag inherited from root CLI

- `src/mcp/mod.rs`: `pub mod install` registered

- `docs/mcp/spec.md` + `docs/mcp/clients.md`: Phase 33 marked shipped

## Safety

No new external dependencies. Uses only serde_json (already in deps),
chrono (already in deps), dirs (already in deps), and std::fs.

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

Add tests/mcp_serve_e2e.rs: 5 integration tests that spawn the real
`parsec mcp serve` binary in a sandboxed temp git repository and
exchange JSON-RPC 2.0 over stdin/stdout.

## Coverage
- Protocol lifecycle: initialize → notifications/initialized (no resp)
  → ping → shutdown (3 JSON-RPC responses verified)
- tools/list: all 10 registered tools + inputSchema presence
- worktree_list + health_check: local-read tools return structured JSON
  (worktrees array, pr_overlay/ci_overlay flags, records array)
- GitHub-backed auth errors: pr_status → AUTH_REQUIRED + pull_request:read;
  ci_status → AUTH_REQUIRED + checks:read (error path, no network)
- Mutation gates: worktree_start without confirm → CONFIRMATION_REQUIRED;
  with dry_run=true → preview text contains ticket (no side effects)

## Why
Prior fixture tests (stdio_smoke.jsonl) test the in-process dispatcher
only. This phase exercises the actual subprocess boundary so transport
framing, BufRead EOF handling, and process exit can be verified in CI.

## Spec update
docs/mcp/spec.md Phase Status table: Phase 34 marked shipped.

## Next Phase hint
Phase 35: PAT delegation via env var injection through MCP session
context (env or config-file path for non-interactive hosts).

## Risk: low — new test file only, no production code change
## Rollback: delete tests/mcp_serve_e2e.rs

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…n-interactive hosts (#406)

Refs #294

## 무엇
serve_stdio가 PARSEC_GITHUB_TOKEN 환경변수를 읽어 McpContext.github_token을 채움.
Claude Desktop / Cursor / systemd 서비스처럼 PAT을 inline으로 전달하지 못하는
non-interactive 호스트에서 GitHub-backed 도구(pr_status, ci_status, reviews 등)를
토큰 없이 AUTH_REQUIRED 차단 없이 사용할 수 있게 됨.

## 변경
- src/mcp/mod.rs:
  - McpContext::from_env() 신규 — PARSEC_GITHUB_TOKEN 읽어 with_github_token 주입
  - McpContext::from_env_lookup() 내부 헬퍼 — 클로저 기반 env 조회 (병렬 테스트 안전)
  - serve() 내부: from_cwd() → from_env() 으로 변경
  - 유닛 테스트 3개: picks_up_token / ignores_missing_var / ignores_empty_var
- tests/mcp_serve_e2e.rs:
  - run_serve_session_with_env() 헬퍼 — 서브프로세스에 env 주입 지원
  - mcp_serve_env_token_bypasses_auth_required e2e 테스트:
    env 없음 → AUTH_REQUIRED, env 있음 → 토큰 게이트 통과(gh CLI 레벨 에러) 검증
- docs/mcp/auth.md: Phase 35 구현 표에 추가
- src/mcp/mod.rs 모듈 doc: Phase 35 기록

## 다음 Phase 힌트
Phase 36 (#294): config-file 경로 지원 (~/.config/parsec/mcp.toml 또는
PARSEC_MCP_CONFIG 환경변수로 지정) — 토큰 + 스코프를 파일로 선언.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…edence e2e · Refs #295 (#409)

Add two subprocess-level e2e tests to tests/mcp_serve_e2e.rs that validate
the Phase 36 mcp.toml config-file auth at the full binary boundary — a gap
left after Phase 37's in-process scope-enforcement pipeline tests.

## Tests added

### mcp_serve_config_file_token_bypasses_auth_required
- Writes a temp mcp.toml with a fake token and sets PARSEC_MCP_CONFIG.
- Verifies baseline (no config, no env var) → AUTH_REQUIRED.
- Verifies with PARSEC_MCP_CONFIG pointing to temp file → no AUTH_REQUIRED;
  server loads the config-file token and forwards it into McpContext.

### mcp_serve_env_var_wins_over_config_file_scope_restriction
- Config file grants only pull_request:read scopes; worktree_ship needs
  pull_request:write → config-only auth returns INSUFFICIENT_SCOPE (baseline).
- Adds PARSEC_GITHUB_TOKEN: env var wins, discarding config-file token AND
  its scope list → worktree_ship reaches CONFIRMATION_REQUIRED (mutation gate),
  not INSUFFICIENT_SCOPE — proving env var supersedes config-file scopes.

## Why
Phase 37 (#294) tested config-file auth in-process; no test verified the
full subprocess stdio boundary with PARSEC_MCP_CONFIG at the binary level.
Phase 38 closes that gap, making the auth source chain (env > config > none)
fully verifiable end-to-end without a real GitHub token.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…rt · Refs #293

Add docs/mcp-quickstart.md: the end-to-end user quickstart for the git-parsec
MCP server (one of the explicit ACs in issue #293).

## What
- docs/mcp-quickstart.md (new, 273 lines):
  - Prerequisites table (parsec, git, gh, PAT, desktop client)
  - One-command install: `parsec mcp install --client=claude-desktop|cursor`
  - Manual config JSON + platform config-file path table
  - Auth setup: mcp.toml config-file (recommended) vs PARSEC_GITHUB_TOKEN env
  - Verify connection prompt + expected response
  - Common AI agent workflows (health check, worktree start/ship, smartlog, CI)
  - Full tool catalogue with auth/mutating flags
  - Manual server invocation smoke-test one-liner
  - Troubleshooting table (7 common failure modes)
  - Pointers to spec.md / auth.md / clients.md
- docs/mcp/spec.md: Phase Status row for Phase 39 added
- src/mcp/mod.rs: Phase 38+39 doc-comment entries added to phase header

## Why
Issue #293 AC explicitly lists `docs/mcp-quickstart.md` as a deliverable.
The existing docs/mcp/{spec,auth,clients}.md are reference documents aimed at
implementers. The quickstart fills the user-facing gap: from zero to a working
Claude Desktop / Cursor conversation in under five minutes.

## Changes
- 3 files, +279 / -0
- Pure documentation + 5 lines of Rust doc-comment; no logic changes

## Next Phase hint
#293: remaining ACs include the MCP SDK integration smoke and potential
`parsec mcp status` diagnostic subcommand. #294 sandbox boundary enforcement
(worktree-path validation beyond the repo-argument check) is the next code Phase.

## Risk: low (documentation only)
## Rollback: revert the 3 files
## Test plan: cargo build / clippy / fmt / test all pass (no Rust logic changed)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Bump version from 0.1 (draft) to 1.0; update date to 2026-08-31
- Remove stale Phase 3 stub note (all 10 tools wired since Phase 31)
- Update tool_error example to reflect real runtime failure, not stub
- Add missing CONFIRMATION_REQUIRED to standard error codes table
- Fix tool_error code description (remove 'or is still a structured stub')
- Remove stale '(to be automated in Phase 2)' implementation note
- Add Phase 35–38 rows to Phase Status table (previously missing)
- Fix Phase 32 row from 'shipped (this PR)' to 'shipped'
- Add Phase 40 row to Phase Status table

The MCP tool spec is now final and reflects the full v1.0 implementation:
10 wired tools, auth (env var + config file), scope enforcement, e2e tests,
install helper, and user quickstart. Closes issue #292.

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

Add two subprocess-level integration tests that verify the MCP server's
repo-path sandbox guard through the full transport stack (spawn → stdin
JSON-RPC → stdout parse):

  mcp_serve_sandbox_boundary_violation_rejected
    - Sends worktree_list with a repo argument pointing outside the session
      boundary (a separate TempDir).
    - Asserts isError=true + SANDBOX_VIOLATION in the error text.
    - Also asserts the requested path is NOT echoed in the response
      (information-leak guard).

  mcp_serve_sandbox_descendant_path_allowed
    - Sends worktree_list with a repo argument that is a sub-directory
      inside the sandbox boundary.
    - Asserts SANDBOX_VIOLATION does NOT appear — the guard is
      boundary-inclusive and must not block legitimate descendant paths.

The unit test in src/mcp/mod.rs::repository_argument_cannot_escape_session_boundary
already covers the dispatch-function level. These tests close the gap at
the subprocess/transport boundary that CI's cargo-test run now exercises
automatically on every push.

Addresses #294 AC: sandbox 로컬 worktree 외부 접근 차단 (e2e coverage)
Addresses #295 AC: CI smoke test 통합 (runs via cargo test in CI)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…293 #294 #295 (#412)

All implementation phases (35–40) are complete. Remove draft/future-phase
language from both docs and promote to v1.0.

auth.md changes:
- Version 0.1 (draft) → 1.0, Date 2026-06-10 → 2026-08-31
- Merge 'Credential Sources' into its own section (env var + config file)
- Scope Matrix: add write-implies-read note for pull_request:write
- Threat Model: add audit-log injection row
- Remove draft wording ('design input for later phases', 'Future phases may…')
- Implementation Phase History: add Phase 37 + 38 rows

clients.md changes:
- Version 0.1 (draft) → 1.0, Date 2026-06-13 → 2026-08-31
- Goal: reference mcp-quickstart.md, remove 'while transport continues to evolve'
- Add 'Automated Installer (Recommended)' section (parsec mcp install)
- Environment table: add PARSEC_GITHUB_TOKEN + PARSEC_MCP_CONFIG rows
- Smoke Test: note that cargo test covers fixture-driven checks
- Troubleshooting: update GitHub auth row to reference PARSEC_GITHUB_TOKEN
- Implementation Phase History: mark all phases shipped, add Phase 41

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

- Add summary header line: 'smartlog  N worktrees · M stacked' giving a
  quick count before the tree output
- Replace alphabetical BTreeMap iteration with topological group ordering
  via topo_sort_groups(): stacked groups now appear directly below their
  parent group instead of jumping alphabetically
- Multi-level stacks (grandparent → parent → child) are rendered in correct
  depth order thanks to recursive DFS from root bases
- Cycle-safe: a placed HashSet prevents infinite loops in unusual reference
  loops between worktree branches
- Stack group header updated to '○ <branch> ⤷ stacked on <ticket>' for
  cleaner visual connection to parent
- Add 4 new Phase 4 tests covering: summary counts, singular form, topo
  ordering across lexicographic gap, and multi-level three-deep stacks

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Add `SmartlogPrOverlay::merge_ready: Option<bool>` that surfaces GitHub's
merge-ability verdict in the smartlog one-line badge.

Changes:
- `SmartlogPrOverlay`: new `merge_ready: Option<bool>` field
  (skip_serializing_if=None for backward-compat)
- `fetch_overlay()`: populate from `PrStatus::mergeable` (open PRs only)
- `format_pr_badge()`: append '⬆ ready' (green) / '⚡ conflicts' (red)
  for open PRs when readiness is known; no segment when None or non-open
- 7 Phase 5 unit tests: ready/conflict badge, None omit, merged/draft skip,
  serde round-trip (absent + present)
- `mk_overlay_with_readiness()` test helper for targeted badge tests

Co-authored-by: Claude Sonnet 4.6 <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>
…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>
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>
@erishforG
erishforG merged commit 23847f4 into develop Sep 19, 2026
24 checks passed
@erishforG erishforG mentioned this pull request Sep 19, 2026
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