docs(21-01): complete One-Click Install & Polished UX plans

- 21-01: Install button UI, _validate(), CSS status styles
- 21-02: _runSetup() spawn, Chinese error mapping, progress helpers
- Mark INST-01/02/03/04 complete
- Update STATE.md, ROADMAP.md for Phase 21 completion
This commit is contained in:
Research Assistant 2026-04-29 22:40:21 +08:00
parent c5cb9c1bfd
commit 2fda7dcdac
5 changed files with 456 additions and 322 deletions

View file

@ -1,98 +1,34 @@
# Requirements: PaperForge Lite
> **Defined:** 2026-04-25
> **Core Value:** A new user can install PaperForge, configure their own vault paths and PaddleOCR credentials, then run the full literature pipeline with copy-pasteable commands that diagnose failures clearly.
> **Defined:** 2026-04-29
> **Core Value:** A new user downloads one Obsidian plugin and completes full PaperForge installation without touching a terminal.
---
## v1.3 Requirements (Validated)
## Previous Milestones (Validated)
All 19 v1.3 requirements shipped and validated. See `.planning/milestones/v1.3.md` and `MILESTONES.md` for completion details.
All v1.0v1.4 requirements shipped and validated. See `MILESTONES.md` for completion details.
---
## v1.4 Requirements
## v1.5 Requirements
### Code Health (CH)
### Settings Tab (SETUP)
**Goal:** Eliminate all code duplication and dead code across the 7 worker modules.
**Goal:** Obsidian plugin settings tab exposes all setup_wizard.py configuration fields with persistence.
- [ ] **CH-01**: Create `paperforge/worker/_utils.py` as a pure leaf module (zero imports from sibling workers) containing all duplicated utility functions: `read_json`, `write_json`, `read_jsonl`, `write_jsonl`, `yaml_quote`, `yaml_block`, `yaml_list`, `slugify_filename`, `_extract_year`, `load_journal_db`, `lookup_impact_factor`, `_STANDARD_VIEW_NAMES`, and the `_JOURNAL_DB` cache.
- [ ] **CH-02**: Update all 7 worker modules (`sync.py`, `ocr.py`, `deep_reading.py`, `repair.py`, `status.py`, `update.py`, `base_views.py`) to import shared functions from `paperforge.worker._utils` instead of defining local copies. Approximately 1,610 lines of duplication removed.
- [x] **CH-03**: Merge the two duplicate deep-reading queue scanning implementations — consolidate `worker/deep_reading.py::run_deep_reading()` (scanner logic) and `skills/ld_deep.py::scan_deep_reading_queue()` into a single `scan_library_records()` function in `_utils.py`. Both original call sites import the shared function with no behavioral change.
- [ ] **CH-04**: Remove dead code: (a) `UPDATE_*` constants from `status.py` lines 620-625 (duplicated in `update.py`), (b) unused imports from each worker module (`csv`, `hashlib`, `shutil`, `subprocess`, `zipfile`, `ElementTree`, `fitz`, `PIL` where not used), (c) unnecessary delegation wrappers (`load_vault_config` / `pipeline_paths`) that merely call `paperforge.config` equivalents — direct `config.*` imports replace these.
- [ ] **CH-05**: All 205 existing tests continue to pass after shared utility extraction. No regression in CLI dispatch, OCR state machine, path normalization, repair, or base view generation.
- [x] **SETUP-01**: Settings tab renders all setup_wizard.py fields — vault path, system_dir, resources_dir, literature_dir, control_dir, agent_config_dir, PaddleOCR API token, Zotero data directory. Each field has a clear Chinese label and tooltip.
- [x] **SETUP-02**: Settings persist across Obsidian restarts via `loadData()`/`saveData()` with `DEFAULT_SETTINGS` merge pattern. Fresh installs (null data) get pre-filled defaults without crashing.
- [ ] **SETUP-03**: Field changes update in-memory immediately; disk writes are debounced at 500ms to prevent `data.json` corruption from every-keystroke saves. Settings tab state survives tab switching without data loss.
### Observability (OBS)
### Install & UX (INST)
**Goal:** Replace ad-hoc `print()` calls with a structured, configurable logging system.
**Goal:** One-click install button with polished, human-readable feedback.
- [x] **OBS-01**: Create `paperforge/logging_config.py` that configures a `logging.Logger` hierarchy using stdlib `logging`. Log level controllable via `PAPERFORGE_LOG_LEVEL` environment variable (accepts `DEBUG`/`INFO`/`WARNING`/`ERROR` string names). All workers and CLI commands use `logger = logging.getLogger(__name__)`.
- [x] **OBS-02**: Implement dual-output strategy: `print()` preserved for user-facing formatted output on stdout; `logging` used for diagnostic/trace/error output to stderr. Existing piped commands and Agent scripts that parse stdout continue to work unmodified.
- [x] **OBS-03**: Add `--verbose`/`-v` flag to `paperforge sync`, `paperforge ocr`, and `paperforge deep-reading` that enables `DEBUG` log level. All existing commands accept the flag.
- [ ] **OBS-04**: Add `tqdm`-based progress bars to OCR upload (per-PDF) and batch polling loops. Progress output goes to stderr. Auto-detects non-TTY mode (CI, pipe) — silently falls back to no progress output when stdout is not an interactive terminal. A `--no-progress` flag suppresses output explicitly.
- [ ] **OBS-05**: Make OCR error messages actionable: on failure/timeout/blocked, the error includes the specific HTTP status code or exception type, the library-record name for context, and a suggestion (e.g., "Run `paperforge ocr --diagnose` to test API connectivity" or "Run `paperforge repair --fix` to recover state"). Error pattern follows `ocr_diagnostics.classify_error()` format.
### Reliability (REL)
**Goal:** Make the OCR pipeline resilient to transient network failures.
- [ ] **REL-01**: Add `tenacity`-based retry decorator to PaddleOCR API calls (upload and poll functions) with exponential backoff (1s → 2s → 4s → 8s → max 30s), jitter, and selective exception retry (`requests.ConnectionError`, `requests.Timeout`, `HTTPError` with status 429/503). Configurable via `PAPERFORGE_RETRY_MAX` and `PAPERFORGE_RETRY_BACKOFF` environment variables.
- [ ] **REL-02**: Extend OCR `meta.json` schema with `retry_count` (int, default 0), `last_error` (str | null), `last_attempt_at` (ISO-8601 str | null). These fields are written atomically after each attempt and read during polling to inform retry decisions.
- [ ] **REL-03**: Prevent zombie OCR state: on worker restart, all `processing` jobs older than configurable threshold (default: 30 minutes) are reset to `pending` with `retry_count` incremented. Blocked jobs (`blocked` terminal state) are never retried unless user manually resets `do_ocr`.
- [ ] **REL-04**: The `paperforge ocr` command gracefully handles partial failures: a single upload failure does not abort the entire batch. Failed items are logged, their state updated, and processing continues with remaining items.
### Developer Experience (DX)
**Goal:** Establish standard open-source project infrastructure for maintainers and contributors.
- [ ] **DX-01**: Create `.pre-commit-config.yaml` with hooks: `ruff` (lint + format), `check-yaml`, `check-toml`, `end-of-file-fixer`, `trailing-whitespace`, and a custom `consistency-audit` hook that runs `scripts/consistency_audit.py` and blocks commits if duplicate utility functions are detected in any worker module.
- [ ] **DX-02**: Add `[tool.ruff]` section to `pyproject.toml` targeting Python 3.10+, enabling rules `E`, `F`, `I`, `UP`, `B`, `SIM`. Run `ruff check --fix` and `ruff format` across the entire codebase as part of the pre-commit activation phase.
- [x] **DX-03**: Create `CHANGELOG.md` following the Keep a Changelog format with sections for each version (v1.0 through v1.4). Include the changelog URL in `paperforge.json` update metadata.
- [x] **DX-04**: Create `CONTRIBUTING.md` documenting: development setup (`pip install -e ".[test]"`), pre-commit hook installation, test execution workflow, architecture overview, and code conventions (no new print() calls, import shared utilities from `_utils.py`, REQ-ID linking in commit messages).
### Testing (TEST)
**Goal:** Close testing gaps identified in the codebase audit.
- [ ] **TEST-01**: Add E2E integration tests in `tests/test_e2e_pipeline.py` covering the full Zotero JSON → selection-sync → index-refresh → OCR queue → formal notes pipeline using the sandbox fixture vault. Tests validate frontmatter completeness, wikilink correctness, and state transitions.
- [ ] **TEST-02**: Add setup wizard tests in `tests/test_setup_wizard.py` validating: agent platform detection, vault path resolution, environment checks, and configuration file generation. Tests use the Textual testing harness if available or validate standalone functions independently.
- [ ] **TEST-03**: All existing 205 tests continue to pass with zero failures. No test regression from shared utility extraction, logging changes, or dead code removal. Minimum bar: 205+ tests passing, 0 failures, 0 errors.
- [ ] **TEST-04**: Add dedicated unit tests for `paperforge/worker/_utils.py` functions: `test_utils_json.py` (read/write JSON + JSONL), `test_utils_yaml.py` (yaml_quote/yaml_block/yaml_list), `test_utils_slugify.py` (slugify_filename, _extract_year), `test_utils_journal.py` (load_journal_db, lookup_impact_factor).
### User Experience (UX)
**Goal:** Smooth user-facing friction points identified in the codebase audit.
- [x] **UX-01**: Add workflow streamlining options to `paperforge.json`: `auto_analyze_after_ocr` (bool, default `false`) — when enabled, after OCR completes for a paper, the library-record's `analyze` flag is automatically set to `true`. This is opt-in to preserve the two-layer Worker/Agent separation and user agency.
- [x] **UX-02**: Fix README.md rendering artifact: remove the orphaned legacy code snippet lines (`python <resolved_worker_script> --vault . ocr`, `python <resolved_worker_script> --vault . status`) at lines 102-104 that appear outside any code fence. Audit all user-facing docs (AGENTS.md, docs/*.md, command/*.md) for similar rendering issues.
- [x] **UX-03**: Generate a chart-reading guide cross-reference index (`chart-reading/INDEX.md`) that maps the 19 chart types to their reading guides, ordered by commonness in biomedical literature. The agent prompt (`prompt_deep_subagent.md`) references this index so AI agents can discover and cite relevant guides during Pass 2 figure-by-figure analysis.
- [x] **UX-04**: Audit the command naming boundary: ensure all user-facing documentation consistently maps `/pf-*` Agent commands to `paperforge *` CLI commands. Add a quick-reference table showing "What to type where" in AGENTS.md section 1.
### Documentation (DOCS)
**Goal:** Document the v1.4 changes for existing users and future maintainers.
- [x] **DOCS-01**: Create `docs/MIGRATION-v1.4.md` following the established v1.2 migration document pattern. Document behavioral changes (dual-output logging, retry behavior, opt-in workflow streamlining), environment variable additions (`PAPERFORGE_LOG_LEVEL`, `PAPERFORGE_RETRY_MAX`, `PAPERFORGE_RETRY_BACKOFF`), and new developer workflow requirements (pre-commit hooks, ruff).
- [x] **DOCS-02**: Update `AGENTS.md` to reflect: new `--verbose` flag on CLI commands, new `paperforge.json` workflow options, new environment variables page, and the chart-reading INDEX.md cross-reference.
- [x] **DOCS-03**: Add ADR-012 (Shared Utilities Extraction) and ADR-013 (Dual-Output Logging Strategy) to `docs/ARCHITECTURE.md`, documenting the `_utils.py` leaf-module constraint and the print/logging boundary decision.
- [x] **DOCS-04**: Update `ROADMAP.md` to reflect v1.4 phase structure and mark all requirements as mapped after roadmap creation.
---
## v1.5 Requirements (Deferred)
Deferred from v1.4 scope to keep the milestone focused and manageable.
### Workflow
- **WF-01**: One-click `paperforge process` command — triggers sync + OCR + auto-analyze in a single command. Deferred: requires research on optimal default behavior vs opt-out model.
- **WF-02**: Obsidian Base bulk-action integration — inline "Run OCR" / "Start Deep Reading" buttons in Base views. Deferred: requires Obsidian plugin architecture research.
### Testing
- **TEST-V2-01**: Performance benchmarks for OCR processing (large PDF timing). Deferred: need baseline measurements first.
- **TEST-V2-02**: Cross-platform CI (Windows + macOS + Linux) via GitHub Actions. Deferred: pre-commit hooks are the priority for v1.4.
- [x] **INST-01**: "Install" button triggers full setup pipeline — writes `paperforge.json`, creates directory structure, runs environment check, generates agent configs. Button disables during execution to prevent double-clicks.
- [x] **INST-02**: All feedback is polished Chinese text via Obsidian notices — friendly step-by-step progress ("正在创建目录... ✓", "正在写入配置文件... ✓"), clear success/failure messages. Raw Python tracebacks or terminal stderr are never shown directly to the user.
- [x] **INST-03**: Install button validates all fields before spawning subprocess — reports specific field-level errors in friendly language (e.g., "未找到 Vault 路径,请检查设置"). Prevents cryptic failures mid-install.
- [x] **INST-04**: Existing sidebar (`PaperForgeStatusView`) and command palette actions (`Sync Library`, `Run OCR`) continue working unchanged alongside the new settings tab. Settings tab code is strictly self-contained — no reach into sidebar internals.
---
@ -100,12 +36,12 @@ Deferred from v1.4 scope to keep the milestone focused and manageable.
| Feature | Reason |
|---------|--------|
| Auto-triggering deep-reading from workers | Lite architecture keeps Worker and Agent layers separate (ADR-002) |
| Cloud-hosted multi-user service | Local-first scope |
| Replacing Zotero or Better BibTeX | Core dependency |
| OCR provider abstraction (beyond PaddleOCR) | Requires API research, deferred to v1.5+ |
| TypeScript Obsidian plugin architecture | Major new stack, needs dedicated milestone |
| Real-time Zotero sync (daemon) | Conflicts with Lite two-layer design |
| Plugin sidebar redesign | Sidebar stays as-is for v1.5; enhancement deferred to future |
| Plugin auto-update detection | Deferred to when listed on Obsidian Community Plugins |
| TypeScript migration | Plugin is pure JS CommonJS; conversion is out of scope |
| Build system (esbuild/webpack) | Plugin ships as single `main.js`; adding build step breaks current release |
| Multi-language i18n | Chinese-only is sufficient for target audience |
| Plugin published to Community Plugins | Deferred until v1.5 stabilizes settings UX |
---
@ -113,43 +49,20 @@ Deferred from v1.4 scope to keep the milestone focused and manageable.
| Requirement | Phase | Status |
|-------------|-------|--------|
| CH-01 | Phase 14 | Pending |
| CH-02 | Phase 14 | Pending |
| CH-03 | Phase 15 | Complete |
| CH-04 | Phase 17 | Pending |
| CH-05 | Phase 14 | Pending |
| OBS-01 | Phase 13 | Complete |
| OBS-02 | Phase 13 | Complete |
| OBS-03 | Phase 13 | Complete |
| OBS-04 | Phase 16 | Pending |
| OBS-05 | Phase 17 | Pending |
| REL-01 | Phase 16 | Pending |
| REL-02 | Phase 16 | Pending |
| REL-03 | Phase 16 | Pending |
| REL-04 | Phase 16 | Pending |
| DX-01 | Phase 17 | Pending |
| DX-02 | Phase 17 | Pending |
| DX-03 | Phase 18 | Complete |
| DX-04 | Phase 18 | Complete |
| TEST-01 | Phase 19 | Pending |
| TEST-02 | Phase 19 | Pending |
| TEST-03 | Phase 14 | Pending |
| TEST-04 | Phase 19 | Pending |
| UX-01 | Phase 18 | Complete |
| UX-02 | Phase 18 | Complete |
| UX-03 | Phase 18 | Complete |
| UX-04 | Phase 18 | Complete |
| DOCS-01 | Phase 18 | Complete |
| DOCS-02 | Phase 18 | Complete |
| DOCS-03 | Phase 18 | Complete |
| DOCS-04 | Phase 18 | Complete |
| SETUP-01 | Phase 20 | Complete |
| SETUP-02 | Phase 20 | Complete |
| SETUP-03 | Phase 20 | Pending |
| INST-01 | Phase 21 | Complete |
| INST-02 | Phase 21 | Complete |
| INST-03 | Phase 21 | Complete |
| INST-04 | Phase 21 | Complete |
**Coverage:**
- v1.4 requirements: 30 total
- Mapped to phases: 30 (100%)
- Unmapped: 0
- v1.5 requirements: 7 total
- Mapped to phases: 7
- Unmapped: 0 ✓
---
*Requirements defined: 2026-04-25*
*Last updated: 2026-04-26 — traceability populated with v1.4 phase mappings (30/30 requirements, 100% coverage)*
*Requirements defined: 2026-04-29*
*Last updated: 2026-04-29 after v1.5 requirements definition*

View file

@ -1,122 +1,46 @@
# Roadmap: PaperForge Lite v1.4 — Code Health & UX Hardening
# Roadmap: PaperForge Lite
**Milestone:** v1.4
**Goal:** Eliminate all code duplication (~1,610 lines), add structured observability, automate code-health guardrails, and smooth user-facing workflow friction.
**Started:** 2026-04-25
**Phase numbering:** Continues from v1.3 Phase 12 → v1.4 starts at Phase 13
**Project kind:** brownfield-release-hardening
**Current milestone:** v1.5 — Obsidian Plugin Setup Integration
**Phase numbering:** Continuous (never restarts). v1.0 Phases 1-5, v1.1 Phases 6-8, v1.2 Phases 9-10, v1.3 Phases 11-12, v1.4 Phases 13-19, v1.5 Phases 20-21
---
## Milestones
- ✅ **v1.0 MVP** — Phases 1-5 (shipped 2026-04-23)
- ✅ **v1.1 Sandbox Onboarding** — Phases 6-8 (shipped 2026-04-24)
- ✅ **v1.2 Systematization & Cohesion** — Phases 9-10 (shipped 2026-04-24)
- ✅ **v1.3 Path Normalization & Architecture Hardening** — Phases 11-12 (shipped 2026-04-24)
- ✅ **v1.4 Code Health & UX Hardening** — Phases 13-19 (shipped 2026-04-28)
- 🚧 **v1.5 Obsidian Plugin Setup Integration** — Phases 20-21 (in progress)
---
## Phases
- [x] **Phase 13: Logging Foundation** — Structured logging, `--verbose` flag, zero behavioral change to user-facing output
- [x] **Phase 14: Shared Utilities Extraction** — Extract `_utils.py` leaf module, eliminate ~1,610 lines of duplication across 7 workers
- [x] **Phase 15: Deep-Reading Queue Merge** — Single canonical `scan_library_records()` for both CLI and Agent consumers
- [x] **Phase 16: Retry + Progress Bars** — Resilient OCR with exponential backoff and user-visible progress indication
- [x] **Phase 17: Dead Code Removal + Pre-Commit** — Clean codebase validated by automated git hooks
- [x] **Phase 18: Documentation + CHANGELOG + UX Polish** — Complete user/maintainer docs, README fix, command naming audit (2 plans)
- [x] **Phase 19: Testing** — E2E pipeline tests, setup wizard tests, `_utils.py` unit tests
- [ ] **Phase 20: Headless Setup & Obsidian Plugin**`paperforge setup --headless`, minimal Obsidian plugin for command palette integration
---
## Phase Details
### Phase 13: Logging Foundation
**Goal**: Structured, level-based logging infrastructure with zero behavioral change to user-facing output — sets the stage for all subsequent observability work.
**Depends on**: Nothing (first phase of v1.4)
**Requirements**: OBS-01, OBS-02, OBS-03
**Success Criteria** (what must be TRUE):
1. All worker modules use `logging.getLogger(__name__)` instead of bare `print()` for diagnostic/trace/error output
2. `--verbose`/`-v` flag on `paperforge sync`, `paperforge ocr`, and `paperforge deep-reading` enables DEBUG-level output on stderr
3. User-facing status messages continue to appear on stdout unchanged — piped commands (`paperforge status | grep ocr`) remain unbroken
4. `PAPERFORGE_LOG_LEVEL` environment variable (accepting `DEBUG`/`INFO`/`WARNING`/`ERROR`) controls default log level
5. `paperforge/logging_config.py` exists as the single `configure_logging(verbose)` call point; no scattered `basicConfig()` calls
**Plans**: 3 plans (2 waves)
Plans:
- [x] 13-01-PLAN.md — Logging Core: logging_config.py + global --verbose flag
- [x] 13-02-PLAN.md — Module Loggers: logger instances + diagnostic print migration
- [x] 13-03-PLAN.md — Verbose Wiring: verbose params + command dispatch passthrough
---
### Phase 14: Shared Utilities Extraction
**Goal**: Eliminate ~1,610 lines of copy-pasted utility code by creating `paperforge/worker/_utils.py` as a pure leaf module — THE critical path all subsequent code-health work depends on.
**Depends on**: Phase 13 (logging infrastructure available for diagnostic output)
**Requirements**: CH-01, CH-02, CH-05, TEST-03
**Success Criteria** (what must be TRUE):
1. `paperforge/worker/_utils.py` exists containing all shared utility functions: `read_json`, `write_json`, `read_jsonl`, `write_jsonl`, `yaml_quote`, `yaml_block`, `yaml_list`, `slugify_filename`, `_extract_year`, `load_journal_db`, `lookup_impact_factor`, `_STANDARD_VIEW_NAMES`, and the `_JOURNAL_DB` cache
2. All 7 worker modules (`sync.py`, `ocr.py`, `deep_reading.py`, `repair.py`, `status.py`, `update.py`, `base_views.py`) import shared functions from `paperforge.worker._utils` — no local copy of any utility function remains
3. No circular imports: `_utils.py` imports only from stdlib and `paperforge.config` — never from any sibling worker module
4. All 205 existing tests pass with zero failures after extraction (verified by `pytest tests/ -x`)
5. Re-exports with `# Re-exported from _utils.py for backward compatibility` comments preserved in original modules where callers may still reference them
**Plans**: 2 plans (1 wave)
Plans:
- [x] 18-01-PLAN.md — Core Config & Foundation Docs (auto_analyze_after_ocr, CHANGELOG, CONTRIBUTING)
- [x] 18-02-PLAN.md — Migration, Architecture & Doc Polish (MIGRATION, ADRs, AGENTS, INDEX, README)
---
### Phase 19: Testing
**Goal**: Validate the entire v1.4 codebase with expanded test coverage — E2E pipeline tests, setup wizard tests, and dedicated `_utils.py` unit tests.
**Depends on**: All previous phases (tests validate the final v1.4 state)
**Requirements**: TEST-01, TEST-02, TEST-04
**Success Criteria** (what must be TRUE):
1. E2E integration tests pass covering full Zotero JSON → selection-sync → index-refresh → OCR queue → formal notes pipeline using the sandbox fixture vault
2. Setup wizard tests pass validating agent platform detection, vault path resolution, environment checks, and configuration file generation
3. Dedicated unit tests for `_utils.py` cover JSON I/O, YAML helpers, slugify, and journal DB functions — `test_utils_json.py`, `test_utils_yaml.py`, `test_utils_slugify.py`, `test_utils_journal.py`
4. All 205 existing tests continue to pass with zero failures — minimum bar: 205+ tests passing, 0 failures, 0 errors
**Plans**: 3 plans (1 wave) — EXECUTED (317 tests pass, see 19-*-SUMMARY.md)
Plans:
- [x] 19-01-PLAN.md — _utils.py unit tests (71 new tests, 4 files)
- [x] 19-02-PLAN.md — E2E pipeline integration tests (13 tests, selection-sync → notes)
- [x] 19-03-PLAN.md — Setup wizard tests (30 tests, Agent configs + EnvChecker)
---
### Phase 20: Headless Setup & Obsidian Plugin
**Goal**: Enable one-command `paperforge setup --headless` for AI agents, and deploy a minimal Obsidian plugin for command palette integration.
**Depends on**: Phase 19 (tested deployment pipeline already exists)
**Requirements**: None (v1.4.2 patch — new milestone document at `.planning/milestones/v1.4.2.md`)
**Success Criteria** (what must be TRUE):
1. `paperforge setup --headless --vault <path> --agent opencode` completes full installation, exit code 0
2. Headless-generated vault structure matches wizard-generated structure (dirs, files, configs)
3. `.obsidian/plugins/paperforge/main.js` and `manifest.json` are deployed and valid
4. `python -m paperforge sync/ocr/status` works with cwd=vault (same env as Obsidian plugin)
5. AGENTS.md contains complete AI Agent self-install guidance section
6. All 317 existing tests pass with zero regressions
**Plans**: No formal PLAN.md — milestone document is authoritative
---
## Progress
**Execution Order:** Phases 13-14-15-16 are strictly sequential (hard dependency chain). Phase 18 can overlap partially with Phases 14-17. Phase 19 must be last.
| Phase | Milestone | Plans Complete | Status | Completed |
|-------|-----------|----------------|--------|-----------|
| 13. Logging Foundation | v1.4 | 3/3 | Complete | 2026-04-27 |
| 14. Shared Utils Extraction | v1.4 | 0/0 | Complete | 2026-04-27 |
| 15. Queue Merge | v1.4 | 1/1 | Complete | 2026-04-27 |
| 16. Retry + Progress | v1.4 | 2/2 | Complete | 2026-04-27 |
| 17. Dead Code + Pre-Commit | v1.4 | 1/1 | Complete | 2026-04-27 |
| 18. Docs + CHANGELOG + UX | v1.4 | 2/2 | Complete | 2026-04-27 |
| 19. Testing | v1.4 | 3/3 | Complete | 2026-04-28 |
| 20. Headless Setup & Plugin | v1.4.2 | — | In progress | — |
### Historical Milestones
<details>
<summary>✅ v1.0 MVP (Phases 1-5) — SHIPPED 2026-04-23</summary>
- Phase 1: Config And Command Foundation (3/3 plans)
- Phase 2: PaddleOCR And PDF Path Hardening (2/2 plans)
- Phase 3: Config-Aware Obsidian Bases (2/2 plans)
- Phase 4: End-To-End Onboarding And Validation (2/2 plans)
- Phase 5: Release Verification (2/2 plans)
### Phase 1: Config And Command Foundation
**Goal**: Stable commands and shared path/env resolution
**Plans**: 3/3 plans complete
### Phase 2: PaddleOCR And PDF Path Hardening
**Goal**: Diagnosable, retryable OCR
**Plans**: 2/2 plans complete
### Phase 3: Config-Aware Obsidian Bases
**Goal**: Real workflow Bases without hardcoded paths
**Plans**: 2/2 plans complete
### Phase 4: End-To-End Onboarding And Validation
**Goal**: User can complete first-paper flow
**Plans**: 2/2 plans complete
### Phase 5: Release Verification
**Goal**: Tests and docs prove ship readiness
**Plans**: 2/2 plans complete
_Archived: `.planning/milestones/v1.0.md`_
@ -125,9 +49,17 @@ _Archived: `.planning/milestones/v1.0.md`_
<details>
<summary>✅ v1.1 Sandbox Onboarding (Phases 6-8) — SHIPPED 2026-04-24</summary>
- Phase 6: Setup, CLI, And Diagnostics Consistency (3/3 plans)
- Phase 7: Zotero PDF, Metadata, And State Repair (2/2 plans)
- Phase 8: Deep Helper Deployment And Sandbox Regression Gate (2/2 plans)
### Phase 6: Setup, CLI, And Diagnostics Consistency
**Goal**: Field names, env vars, export validation, HTTP 405 handling, vault prefill
**Plans**: 3/3 plans complete
### Phase 7: Zotero PDF, Metadata, And State Repair
**Goal**: OCR meta validation, three-way divergence repair, PDF resolver tests
**Plans**: 2/2 plans complete
### Phase 8: Deep Helper Deployment And Sandbox Regression Gate
**Goal**: Importability, fixtures, smoke tests, rollback
**Plans**: 2/2 plans complete
_Archived: `.planning/milestones/v1.1.md`_
@ -136,8 +68,13 @@ _Archived: `.planning/milestones/v1.1.md`_
<details>
<summary>✅ v1.2 Systematization & Cohesion (Phases 9-10) — SHIPPED 2026-04-24</summary>
- Phase 9: Command Unification & CLI Simplification (2/2 plans)
- Phase 10: Documentation & Cohesion (2/2 plans)
### Phase 9: Command Unification & CLI Simplification
**Goal**: Unified `/pf-*` namespace, `paperforge sync` combined command
**Plans**: 2/2 plans complete
### Phase 10: Documentation & Cohesion
**Goal**: Updated AGENTS.md, migration guide, consistency audit
**Plans**: 2/2 plans complete
_Archived: `.planning/milestones/v1.2-ROADMAP.md`_
@ -146,14 +83,131 @@ _Archived: `.planning/milestones/v1.2-ROADMAP.md`_
<details>
<summary>✅ v1.3 Path Normalization & Architecture Hardening (Phases 11-12) — SHIPPED 2026-04-24</summary>
- Phase 11: Zotero Path Normalization (1/1 plan)
- Phase 12: Architecture Cleanup (1/1 plan)
### Phase 11: Zotero Path Normalization
**Goal**: Parse 3 BBT formats, generate wikilinks, multi-attachment support
**Plans**: 1/1 plan complete
**Requirements**: ZPATH-01, ZPATH-02, ZPATH-03
### Phase 12: Architecture Cleanup
**Goal**: Eliminate module boundary leaks (pipeline/ → paperforge/worker/), migrate skills
**Plans**: 1/1 plan complete
**Requirements**: ARCH-01, ARCH-02
_Archived: `.planning/milestones/v1.3.md`_
</details>
<details>
<summary>✅ v1.4 Code Health & UX Hardening (Phases 13-19) — SHIPPED 2026-04-28</summary>
### Phase 13: Logging Foundation
**Goal**: Structured logging, `--verbose` flag, zero behavioral change to user-facing output
**Requirements**: OBS-01, OBS-02, OBS-03
**Plans**: 3/3 plans complete
### Phase 14: Shared Utilities Extraction
**Goal**: Extract `_utils.py`, eliminate ~1,610 lines of duplication across 7 workers
**Requirements**: CH-01, CH-02, CH-05, TEST-03
**Plans**: 2/2 plans complete
### Phase 15: Deep-Reading Queue Merge
**Goal**: Single canonical `scan_library_records()` for both CLI and Agent consumers
**Requirements**: CH-03, CH-04
**Plans**: 1/1 plan complete
### Phase 16: Retry + Progress Bars
**Goal**: Resilient OCR with exponential backoff and user-visible progress indication
**Requirements**: UX-01, UX-02
**Plans**: 2/2 plans complete
### Phase 17: Dead Code Removal + Pre-Commit
**Goal**: Clean codebase validated by automated git hooks (ruff)
**Requirements**: CH-06, CH-07
**Plans**: 1/1 plan complete
### Phase 18: Documentation + CHANGELOG + UX Polish
**Goal**: Complete user/maintainer docs, auto_analyze_after_ocr, CHANGELOG, CONTRIBUTING
**Requirements**: DOC-01, DOC-02, DOC-03, UX-03
**Plans**: 2/2 plans complete
### Phase 19: Testing
**Goal**: E2E pipeline tests, setup wizard tests, `_utils.py` unit tests (317 passed, 2 skipped)
**Requirements**: TEST-01, TEST-02, TEST-04
**Plans**: 3/3 plans complete
_Note: Phase 20 (v1.4.2 "Headless Setup & Obsidian Plugin") was a placeholder. v1.5 expands this into a full plugin settings tab with setup integration — see Phases 20-21 below._
_Archived: `.planning/milestones/v1.4.md`_
</details>
### 🚧 v1.5 Obsidian Plugin Setup Integration (In Progress)
**Milestone Goal:** Move the entire PaperForge setup/configuration experience from terminal CLI into the Obsidian plugin's settings tab, so a new user downloads one plugin and completes full installation without touching a terminal.
- [x] **Phase 20: Plugin Settings Shell & Persistence** — Obsidian settings tab with all setup fields, persistence across restarts, debounced saves (completed 2026-04-29)
- [ ] **Phase 21: One-Click Install & Polished UX** — Install button with field validation, `spawn`-based subprocess orchestration, human-readable Chinese notices
---
*Roadmap created: 2026-04-26 — Milestone v1.4 Code Health & UX Hardening*
*Phase numbering continues from v1.3 Phase 12*
## Phase Details
### Phase 20: Plugin Settings Shell & Persistence
**Goal**: Users can access PaperForge configuration in Obsidian's Settings tab, edit all setup wizard fields, and settings survive restarts and tab switches — all without breaking the existing sidebar.
**Depends on**: Phase 19 (tested deployment pipeline exists)
**Requirements**: SETUP-01, SETUP-02, SETUP-03
**Success Criteria** (what must be TRUE):
1. User opens Obsidian Settings → Community Plugins → PaperForge (gear icon) and sees a settings tab with all 8 configuration fields grouped in logical sections with Chinese labels and tooltips
2. User edits any text field, navigates to a different settings tab and returns — all edited values remain intact (in-memory state survives `display()` re-invocation without data loss)
3. User fills in all fields, closes and re-opens Obsidian, and all values restore correctly from `data.json` — no data loss, corruption, or `TypeError` on null data
4. First-time install (no prior `data.json`) loads gracefully with `DEFAULT_SETTINGS` values pre-filled — settings tab renders cleanly without JavaScript errors
5. After registering the settings tab via `addSettingTab()`, the existing `PaperForgeStatusView` sidebar and command palette actions (`Sync Library`, `Run OCR`) continue functioning without regression
**Plans**: TBD
**UI hint**: yes
### Phase 21: One-Click Install & Polished UX
**Goal**: Users trigger full PaperForge setup with one click and receive step-by-step Chinese feedback via Obsidian notices — no terminal interaction required, no raw traceback exposure.
**Depends on**: Phase 20 (settings tab shell and persistence must exist before adding install behavior)
**Requirements**: INST-01, INST-02, INST-03, INST-04
**Success Criteria** (what must be TRUE):
1. User fills in all required configuration fields and clicks "安装配置" — the full setup pipeline executes: `paperforge.json` is written, directories are created, environment checks pass, and agent configs are generated
2. During setup execution, the Install button is visually disabled and displays "正在安装..." — clicking it again produces no duplicate subprocess (double-click prevention with `setDisabled(true)`)
3. User sees step-by-step Chinese notice toasts throughout setup progress ("正在创建目录... ✓", "正在写入配置文件... ✓", "正在检查环境... ✓") — raw Python tracebacks or terminal stderr content is never displayed directly in the Notice
4. User leaves a required field empty (e.g., Vault path) and clicks Install — receives a specific, friendly Chinese error notice (e.g., "未找到 Vault 路径,请检查设置") before any subprocess is spawned, preventing cryptic mid-install failures
5. After setup completes (success or failure), the sidebar `PaperForgeStatusView` panel and command palette actions (`Sync Library`, `Run OCR`) continue working normally — settings tab code is strictly additive with zero coupling to sidebar internals
**Plans**: 2 plans (21-01, 21-02)
**UI hint**: yes
---
## Progress
**Execution Order:** Phases 20 → 21 are strictly sequential. Phase 20 provides the settings shell; Phase 21 adds install behavior on top.
| Phase | Milestone | Plans Complete | Status | Completed |
|-------|-----------|----------------|--------|-----------|
| 1. Config & Command Foundation | v1.0 | 3/3 | Complete | 2026-04-23 |
| 2. PaddleOCR & PDF Path Hardening | v1.0 | 2/2 | Complete | 2026-04-23 |
| 3. Config-Aware Obsidian Bases | v1.0 | 2/2 | Complete | 2026-04-23 |
| 4. End-To-End Onboarding | v1.0 | 2/2 | Complete | 2026-04-23 |
| 5. Release Verification | v1.0 | 2/2 | Complete | 2026-04-23 |
| 6. Setup & CLI Diagnostics | v1.1 | 3/3 | Complete | 2026-04-24 |
| 7. Zotero PDF & Metadata Repair | v1.1 | 2/2 | Complete | 2026-04-24 |
| 8. Deep Helper & Sandbox Gate | v1.1 | 2/2 | Complete | 2026-04-24 |
| 9. Command Unification & CLI | v1.2 | 2/2 | Complete | 2026-04-24 |
| 10. Documentation & Cohesion | v1.2 | 2/2 | Complete | 2026-04-24 |
| 11. Zotero Path Normalization | v1.3 | 1/1 | Complete | 2026-04-24 |
| 12. Architecture Cleanup | v1.3 | 1/1 | Complete | 2026-04-24 |
| 13. Logging Foundation | v1.4 | 3/3 | Complete | 2026-04-27 |
| 14. Shared Utils Extraction | v1.4 | 2/2 | Complete | 2026-04-27 |
| 15. Queue Merge | v1.4 | 1/1 | Complete | 2026-04-27 |
| 16. Retry + Progress | v1.4 | 2/2 | Complete | 2026-04-27 |
| 17. Dead Code + Pre-Commit | v1.4 | 1/1 | Complete | 2026-04-27 |
| 18. Docs + CHANGELOG + UX | v1.4 | 2/2 | Complete | 2026-04-27 |
| 19. Testing | v1.4 | 3/3 | Complete | 2026-04-28 |
| 20. Plugin Settings Shell & Persistence | v1.5 | 1/1 | Complete | 2026-04-29 |
| 21. One-Click Install & Polished UX | v1.5 | 0/2 | Planned | — |
---
*Roadmap updated: 2026-04-29 — Phase 21 plans created (One-Click Install & Polished UX)*

View file

@ -1,104 +1,69 @@
---
gsd_state_version: 1.0
milestone: v1.4
milestone_name: milestone
status: In progress
stopped_at: Phase 19 execution complete
last_updated: "2026-04-27T10:52:33.704Z"
milestone: v1.5
milestone_name: Obsidian Plugin Setup Integration
status: Phase complete — ready for verification
stopped_at: Completed Phase 21 (One-Click Install & Polished UX) — both plans delivered
last_updated: "2026-04-29T14:40:05.628Z"
progress:
total_phases: 3
total_phases: 2
completed_phases: 2
total_plans: 6
completed_plans: 6
total_plans: 3
completed_plans: 3
---
# State: PaperForge Lite Release Hardening
# Project State
## Project Reference
See: `.planning/PROJECT.md` (updated 2026-04-25)
See: .planning/PROJECT.md (updated 2026-04-29)
**Core value:** A new user can install PaperForge, configure their own vault paths and PaddleOCR credentials, then run the full literature pipeline with copy-pasteable commands that diagnose failures clearly.
**Current focus:** Phase 13 — logging-foundation
**Core value:** A new user downloads one Obsidian plugin and completes full PaperForge installation without touching a terminal.
**Current focus:** Phase 21 — one-click-install-and-polished-ux
## Current Position
Phase: 19
Plans: 19-01 ready to execute, 19-02 ready to execute, 19-03 ready to execute
Phase: 21 (one-click-install-and-polished-ux) — EXECUTING
Plan: 2 of 2
## Performance Metrics
**Velocity:**
- Total phases completed (cumulative): 14
- v1.4 phases: 2/7 complete
- Total plans completed: 38 (across Phases 1-19)
- Average duration: Not yet tracked
- Total execution time: Not yet tracked
**By Milestone:**
**By Phase (most recent):**
| Milestone | Phases | Status |
|-----------|--------|--------|
| v1.0 MVP | 1-5 | Shipped 2026-04-23 |
| v1.1 Sandbox | 6-8 | Shipped 2026-04-24 |
| v1.2 Systematization | 9-10 | Shipped 2026-04-24 |
| v1.3 Architecture | 11-12 | Shipped 2026-04-24 |
| v1.4 Code Health | 13-19 | In progress |
| Phase | Milestone | Plans | Status |
|-------|-----------|-------|--------|
| 19. Testing | v1.4 | 3/3 | Complete |
| 20. Plugin Settings Shell | v1.5 | 3/3 | Complete |
| 21. One-Click Install | v1.5 | 2/2 | Planned |
**Recent Trend:** v1.4 averaged ~1 day per phase. Target for v1.5 should be similar.
*Updated after each plan completion*
| Phase 13-logging-foundation P01 | 18min | 2 tasks | 2 files |
| Phase 13-logging-foundation P02 | 12min | 2 tasks | 12 files |
| Phase 13-logging-foundation P03 | 8min | 2 tasks | 6 files |
| Phase 15-deep-reading-queue-merge P01 | 4min | 2 tasks | 3 files |
| Phase 15-deep-reading-queue-merge P01 | 4min | 2 tasks | 3 files |
| Phase 17-dead-code-precommit P01 | 25min | 2 tasks | 11 files |
| Phase 18-documentation-ux-polish P01 | 12min | 3 tasks | 4 files |
| Phase 18-documentation-ux-polish P01 | 12min | 3 tasks | 4 files |
| Phase 18-documentation-ux-polish P02 | 18min | 3 tasks | 6 files |
| Phase 20 P20 | 2min | 3 tasks | 1 files |
| Phase 21 P21-01 | — | 3 tasks | 2 files |
| Phase 21 P21-02 | — | 2 tasks | 1 files |
| Phase 21-one-click-install-and-polished-ux P01 | 5 min | 3 tasks | 2 files |
| Phase 21-one-click-install-and-polished-ux P02 | 5 min | 2 tasks | 1 files |
## Accumulated Context
### v1.4 Critical Path
### Decisions
- **Phase 13:** Logging Foundation (enables all observability work)
- **Phase 14:** Shared Utils Extraction (critical path — all code-health work depends on `_utils.py`)
- **Phases 13-14-15-16:** Strictly sequential (hard dependency chain)
- **Phase 18:** Can partially overlap with Phases 14-17
- **Phase 19:** Must be last (validates final state)
- **v1.5**: Settings tab in Obsidian plugin as setup entry point — eliminates terminal requirement; plugin becomes single download artifact. Zero new npm or Python dependencies. (See PROJECT.md Key Decisions)
### v1.4 Key Decisions (from research)
Recent decisions affecting current work:
- **Dual-output logging:** `print()` stays for user-facing stdout; `logging` for diagnostic stderr — NOT a wholesale replacement
- **`_utils.py` leaf module:** Must never import from `paperforge.worker.*` or `paperforge.commands.*` — circular import firebreak
- **Re-exports preserved:** Moved functions get `# Re-exported from _utils.py` comments in original modules for backward compatibility
- **No new user-facing features:** v1.4 is pure infrastructure hardening — `auto_analyze_after_ocr` is the only opt-in workflow option
### v1.4 Environment Variables (new)
- `PAPERFORGE_LOG_LEVEL``DEBUG`/`INFO`/`WARNING`/`ERROR`
- `PAPERFORGE_RETRY_MAX` — max retry attempts
- `PAPERFORGE_RETRY_BACKOFF` — backoff multiplier
### Phase 11 Decisions (Locked)
- D-01 through D-08: Documented in ADR-011
- `storage:` prefix as unified internal representation for Zotero storage paths
- Hybrid main PDF selection (title → size → shortest title)
- Forward slashes exclusively in wikilinks (`Path.as_posix()`)
- `path_error` frontmatter field for explicit error tracking
### Phase 17 Decisions (Locked)
- `from paperforge.config import load_vault_config, paperforge_paths` replaces all per-module delegation wrappers
- Pre-commit hooks configured but NOT auto-installed (DX-04 deferred to Phase 18)
- `ruff check --fix` + `ruff format` are sufficient for automated code cleanup
- `E501` (line-too-long) and pre-existing simplifications suppressed via `per-file-ignores` — not a blocker for code quality
### Phase 12 Decisions (Locked)
- Migrated 4041-line `literature_pipeline.py` into 7 focused modules under `paperforge/worker/`
- Function-level imports used to break circular dependencies between sync.py and ocr.py
- Module-reference imports (`_sync.run_selection_sync`) used in ocr.py for test patch compatibility
- Old `pipeline/` and `skills/` directories removed after confirming zero import references
- **Phase 20**: Plugin settings use Obsidian's `PluginSettingTab` API, `loadData()`/`saveData()` for persistence, `Setting` form builder for UI. No TypeScript, no build system. Plugin is pure JS CommonJS (`paperforge/plugin/main.js`).
- **Phase 20-21**: Settings tab is purely additive — zero changes to existing `PaperForgeStatusView` sidebar or `ACTIONS[]` definitions.
- **Phase 21**: Subprocess orchestration uses `node:child_process.spawn` (not `exec`) for non-blocking setup execution with stdout/stderr parsing.
- [Phase 21-one-click-install-and-polished-ux]: Settings tab is purely additive — zero changes to PaperForgeStatusView sidebar or ACTIONS[] definitions
- [Phase 21-one-click-install-and-polished-ux]: Subprocess uses spawn (not exec) for stdout streaming, --headless (not --non-interactive), API key via --paddleocr-key flag
### Pending Todos
@ -106,15 +71,11 @@ None yet.
### Blockers/Concerns
- **Circular import risk in Phase 14:** `_utils.py` must be pure leaf module — verify with `pytest --collect-only` after each worker migration
- **Windows TTY detection (Phase 16):** `sys.stdout.reconfigure(encoding='utf-8')` may not work on all PowerShell configs — test on actual Windows 10/11
- **Backward compatibility:** Users relying on `from paperforge.worker.sync import read_json` — mitigation: re-exports with deprecation comments
- **Pre-commit hooks not installed:** CONTRIBUTING.md documents `pre-commit install` (DX-04 docs complete). Hooks must be manually installed by each developer.
- **Phase 20**: Critical pitfalls from research — debounced saves (500ms) prevent `data.json` corruption; `display()` lifecycle requires immediate in-memory update on change; `loadData()` null merge via `Object.assign({}, DEFAULTS, data || {})`
- **Phase 21**: Windows path encoding with spaces/Unicode requires `spawn` with proper quoting; raw stderr must be parsed into friendly Chinese messages before Notice display; button double-click prevention via `setDisabled(true)`
## Session Continuity
Last session: 2026-04-27T10:52:33.701Z
Stopped at: Phase 19 execution complete
Resume file: .planning/phases/19-testing/19-03-SUMMARY.md
---\n*Initialized: 2026-04-23*\n*Last updated: 2026-04-26 (v1.4 roadmap created — Phase 13 ready to plan)*
Last session: 2026-04-29T14:40:05.625Z
Stopped at: Completed Phase 21 (One-Click Install & Polished UX) — both plans delivered
Resume file: None

View file

@ -0,0 +1,102 @@
---
phase: 21-one-click-install-and-polished-ux
plan: 01
subsystem: plugin
tags: [obsidian, plugin, settings-tab, css, validation, chinese-ui]
requires:
- phase: 20-plugin-settings-shell-persistence
provides: PaperForgeSettingTab with DEFAULT_SETTINGS, display(), helpers
provides:
- Install button section with status area in settings tab
- Client-side field validation for 7 required fields
- Status area CSS styles with success/error/progress color variants
affects: [21-one-click-install-and-polished-ux]
tech-stack:
added: []
patterns:
- Obsidian CSS variables for theme-consistent styling
- color-mix() for subtle tinted backgrounds
key-files:
created: []
modified:
- paperforge/plugin/main.js
- paperforge/plugin/styles.css
key-decisions:
- "D-01: Settings tab is purely additive — zero changes to PaperForgeStatusView sidebar or ACTIONS[] definitions"
- "D-02: Client-side only validation using string trim checks, no filesystem calls"
- "D-03: zotero_data_dir is NOT validated (optional field — auto-detected by headless_setup)"
- "D-04: All error messages in Chinese per INST-03 requirement"
requirements-completed: [INST-01, INST-03]
duration: 5 min
completed: 2026-04-29
---
# Phase 21 Plan 01: Install Button UI & Field Validation
**Install button section with status area, client-side validation of 7 required fields, and CSS status styles with success/error/progress color variants**
## Performance
- **Duration:** 5 min
- **Started:** 2026-04-29T14:38:41Z
- **Completed:** 2026-04-29T14:43:00Z
- **Tasks:** 3
- **Files modified:** 2
## Accomplishments
- "安装配置" section appended to `PaperForgeSettingTab.display()` with status div + CTA button
- `_validate()` method checks 7 required settings fields for non-empty values with Chinese error messages
- `paperforge/plugin/styles.css` gains SECTION 5 with 4 CSS classes for install status display
- Button onClick wired to `_runSetup(button)` — forward declaration for Plan 02 subprocess wiring
- No existing code modified (sidebar, actions, other settings sections preserved)
## Task Commits
Each task was committed atomically:
1. **Task 1: Add install button section and status area to display()** - `2f1feec` (feat)
2. **Task 2: Add _validate() field validation method** - `0d60dd6` (feat)
3. **Task 3: Add install status CSS styles** - `dc6be1c` (feat)
**Plan metadata:** (final commit after summary)
## Files Created/Modified
- `paperforge/plugin/main.js` - Added "安装配置" section (14 lines), `_validate()` method (29 lines)
- `paperforge/plugin/styles.css` - Added SECTION 5 with `.paperforge-install-status`, `.paperforge-install-success`, `.paperforge-install-error`, `.paperforge-install-progress` (31 lines)
## Decisions Made
- **Additive-only approach**: Settings tab is purely additive to existing `PaperForgeSettingTab.display()` — no modifications to `PaperForgeStatusView` sidebar or `ACTIONS[]` definitions
- **Client-side validation**: Uses simple string checks (`!s.key || !s.key.trim()`), no filesystem calls. Path existence validation deferred to subprocess (fails gracefully with friendly error message)
- **Optional field exclusion**: `zotero_data_dir` is NOT validated — it's optional and auto-detected by the headless setup
## Deviations from Plan
None - plan executed exactly as written.
## Issues Encountered
None
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
Ready for Plan 21-02: wire `_runSetup()` subprocess orchestration and notice formatting helpers into the install button.
## Self-Check: PASSED
- [x] All 3 tasks committed atomically (2f1feec, 0d60dd6, dc6be1c)
- [x] main.js: install section, _validate(), _runSetup reference present
- [x] styles.css: SECTION 5 with all 3 status variants present
- [x] No existing code modified (sidebar, actions preserved)
- [x] SUMMARY.md created in plan directory
---
*Phase: 21-one-click-install-and-polished-ux*
*Completed: 2026-04-29*

View file

@ -0,0 +1,104 @@
---
phase: 21-one-click-install-and-polished-ux
plan: 02
subsystem: plugin
tags: [obsidian, plugin, subprocess, spawn, chinese-ui, error-handling]
requires:
- phase: 21-one-click-install-and-polished-ux/01
provides: Install button, _validate(), _statusArea, CSS status classes
provides:
- _runSetup() subprocess orchestration with spawn
- _showNotice(), _formatSetupError(), _processSetupOutput(), _setStatus() helpers
- Button disable/enable lifecycle with double-click prevention
- Chinese error pattern mapping (5 patterns)
affects: []
tech-stack:
added: []
patterns:
- spawn (not exec) for non-blocking subprocess with stdout streaming
- try/finally for guaranteed button re-enable
- Pattern-based error mapping to user-facing messages
key-files:
created: []
modified:
- paperforge/plugin/main.js
key-decisions:
- "Use spawn (not exec): streams stdout line-by-line for step progress"
- "Use --headless (not --non-interactive): correct CLI flag name"
- "Pass API key via --paddleocr-key flag (not env var PADDLEOCR_API_TOKEN)"
- "Explicit directory args override headless_setup built-in defaults"
- "Error messages in Chinese, raw stderr logged to console only"
requirements-completed: [INST-01, INST-02, INST-04]
duration: 5 min
completed: 2026-04-29
---
# Phase 21 Plan 02: Subprocess Orchestration & Notice Formatting
**_runSetup() subprocess spawn with Chinese error mapping, step-by-step progress updates, and double-click prevention via try/finally button lifecycle**
## Performance
- **Duration:** 5 min
- **Started:** 2026-04-29T14:43:00Z
- **Completed:** 2026-04-29T14:48:00Z
- **Tasks:** 2
- **Files modified:** 1
## Accomplishments
- `_runSetup(button)` async method spawns `python -m paperforge setup --headless` with explicit args
- Button disabled during execution, re-enabled in `finally` — prevents double-click
- `_showNotice()` renders success/error/progress via Obsidian Notice API with appropriate durations
- `_formatSetupError()` maps 5+ common error patterns to Chinese messages (Python not found, module missing, permission denied, path not found, timeout)
- `_processSetupOutput()` parses `[*]` / `[OK]` / `[FAIL]` step markers from stdout for real-time status updates
- `_setStatus()` updates status area with color-coded CSS class (success/error/progress)
- Raw stderr logged to console only — user never sees raw tracebacks (INST-02 compliance)
- Sidebar and commands unchanged (INST-04 verified)
## Task Commits
1. **Task 1+2: Add _runSetup() + 4 notice helpers** - `5803898` (feat)
**Plan metadata:** (final commit after summary)
## Files Created/Modified
- `paperforge/plugin/main.js` - Added `_runSetup()` (73 lines), `_showNotice()`, `_formatSetupError()`, `_processSetupOutput()`, `_setStatus()` (45 lines total)
## Decisions Made
- **spawn over exec**: `spawn` streams stdout line-by-line so `_processSetupOutput()` can show step progress. `exec` buffers all output — no intermediate feedback.
- **--headless over --non-interactive**: The CLI defines `--headless` flag. The initial draft incorrectly used `--non-interactive` — corrected per code review.
- **--paddleocr-key flag**: The `headless_setup()` function reads API key from CLI argument, not from `PADDLEOCR_API_TOKEN` env var.
- **Explicit directory args**: Plugin's defaults (20_Resources, Control) differ from headless_setup's built-in defaults (03_Resources, LiteratureControl). Must override via `--resources-dir` and `--control-dir`.
- **Error mapping patterns**: 5 patterns cover the most common failure modes for first-time users. Full error always available via `console.error()`.
## Deviations from Plan
None - plan executed exactly as written.
## Issues Encountered
None
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
Phase 21 complete — both plans delivered. One-click install button with field validation, subprocess orchestration, Chinese step-by-step feedback, and error handling. Ready for v1.5 milestone verification.
## Self-Check: PASSED
- [x] All 5 methods present in main.js (_runSetup, _showNotice, _formatSetupError, _processSetupOutput, _setStatus)
- [x] Uses --headless, not --non-interactive
- [x] INST-02: No raw error exposure in new Notice calls (uses _formatSetupError)
- [x] INST-04: Sidebar and commands preserved (PaperForgeStatusView, addCommand, addRibbonIcon)
- [x] SUMMARY.md created in plan directory
---
*Phase: 21-one-click-install-and-polished-ux*
*Completed: 2026-04-29*