- Replace this.plugin with this.app.plugins.plugins['paperforge']
- PaperForgeStatusView does not have a plugin property
- Remove debug console.log lines
- Merge status strip + file buttons into one row (left pills, right buttons)
- Move OCR/Analyze toggles into technical details disclosure body
- Replace All Set card with compact complete state row
- Save/restore technical details expanded state to prevent toggle flash
- Delete unused _renderPaperStatusStrip and _renderPaperFilesRow methods
- UI text: use Chinese labels (打开 PDF, 打开全文, 加入 OCR, 标记精读)
- Remove all box-shadows and ::before elevation pseudo-elements
- Typography constrained to 4 sizes (16/14/13/12) and 3 weights (600/500/400)
- Cards only for primary content modules (overview, discussion, OCR pipe, issues)
- Status pills: 999px radius, text-only status colors (no colored backgrounds)
- Technical details: inline disclosure row, not a bordered box
- Workflow toggles: not a card (simple flex row)
- Contextual buttons: Obsidian interactive-normal variables
- Section labels: no accent border, simple uppercase 12px muted
- Dark theme: no shadows, only background tweaks
- processFrontMatter triggers modify event which auto-refreshes the view
- Double refresh was resetting technical details toggle state (flash on first click)
- Discussion card only shows for papers with ai/discussion.json (currently 2Y9M3ILK only)
- Section labels: accent left-border matching metric card pattern
- Cards: ::before pseudo-element for smooth elevation on hover
- Per-paper header: larger title (16px), author (13px)/year (12px faint) hierarchy
- Body text: bumped from 11px to 13.5px for overview/discussion
- Status pills: rgba() translucent backgrounds with colored text
- Dark theme: deeper shadow on card hover (0 2px 12px rgba(0,0,0,0.3))
- Refined spacing, font weights, and transition timing for premium feel
- Discussion card: use lastIndexOf('/') instead of path.dirname to avoid
Windows backslash separator breaking Obsidian vault path resolution
- OCR token: also check .env PADDLEOCR_API_TOKEN as fallback when plugin
settings paddleocr_api_key is empty
- Status strip pills matching existing badge design (color-green/text-error)
- Paper overview card with card-style hover border + accent left border via ::before
- Discussion card with session-based Q&A styling + expand/truncate
- Workflow overview funnel with centered stage pills and arrows
- Issue summary with subtle error border + dot indicators
- Library snapshot pills and system status grid for global view
- Contextual button base style shared across all views
- All new components use Obsidian CSS variables for dark/light theme support
- Remove OCR pipeline and metric cards from global mode (moved to base)
- Add library snapshot: papers, PDFs ready, OCR done, deep-read done
- Add system status grid: runtime, index, Zotero export, OCR token
- Add issues panel with contextual Run Doctor / Repair Issues (only when issues exist)
- Add contextual Start Working actions: Open Literature Hub + Sync Library
- Add null guards to _renderStats and _renderOcr for safe backwards compat
- Replace metric cards + bar chart + health grid with workflow funnel overview
- Move OCR pipeline from global to base (same progress bar logic, new container)
- Replace health matrix with compact issue summary (only visible when issues exist)
- Add contextual action buttons: Sync Library + Run OCR
- Remove _renderCollectionHealth (replaced by inline issue summary)
- Add _extractZoteroKeyFromPath: extract key from dirname pattern '{KEY} - {title}'
- Modify _resolveModeForFile: fallback to workspace detection for any file type
- Fixes fulltext.md and other workspace files dropping to global mode
- New services/skill_deploy.py: single source of truth for agent skill deployment
- AGENT_CONFIGS with 9 platforms, all vault-local
- deploy_skills() with install/update mode (overwrite flag)
- Used by both setup wizard and update worker
- update.py: _deploy_all_skills() after pip/git/zip update
- setup_wizard.py: delegates skill deploy to shared service
- config.py: add agent_platform default
- main.js: Copy Context + Copy Collection Context now pure JS
- Uses in-memory _cachedItems / _currentPaperEntry
- No subprocess spawn, no timeout, no JSON parse errors
- testable.js: remove needsKey/needsFilter from context actions
- commands.test.mjs: update assertions for removed flags
- Move resolvePythonExecutable, getPluginVersion, classifyError, ACTIONS, etc. to src/testable.js
- main.js now requires from ./src/testable.js instead of inline duplication
- Tests import from ../src/testable.js (no obsidian dependency)
- Remove vitest obsidian mock setup (no longer needed)
- Fixes L3 Plugin Tests that failed because main.js requires 'obsidian'
- Add named exports for testable functions (resolvePythonExecutable, getPluginVersion, etc.)
- Update test imports from ../src/*.js to ../main.js
- Fix repair action test: disabled flag was removed when ACTIONS was inlined
- Add paperforgeEnrichedEnv() to enrich PATH for GUI Obsidian on macOS/Linux
- Add getPaperforgePythonCmd() preferring Homebrew/pyenv over Apple CLT Python
- Add tryExecPythonVersion() with multi-candidate fallback for pre-check
- Add scanBbtUnderProfiles() using real Zotero Profiles/extensions/ layout
- Add scanBbtDirectChildren() for safe shallow BBT folder detection
- Add macOS /Applications/Zotero.app and Linux Zotero install detection
- Use paperforgeEnrichedEnv() in setup wizard spawn calls
- Add --user flag to pip install on non-Windows
- Pass PaddleOCR key as --paddleocr-key CLI arg instead of env var
- Add Apple CLT stub Python specific error message in _formatSetupError()
Based on PR #1 by Chartreuse310
Original commit: 156f653 (improve setup modal i18n and update directory defaults)
Co-authored-by: CTZ <yoyflying@163.com>
test_ocr_preflight: mock fitz.open (not builtins.open) + set needs_sanitize=True
- Code uses fitz.open(), not builtins.open() — mock was targeting wrong function
- fitz.open() only called when meta.needs_sanitize is true — mock returned {} which skipped it
- These tests were always broken but CI never ran before v2.1
test_e2e_cli: guard against None stdout in doctor_verdict test on Windows CI
L3 runtime.test.mjs: use platform-agnostic path matching
- path.join produces / on Linux but \\\\ on Windows — test used \\\\ only
L2: removed -m cli marker filter (no test had the marker → exit code 5)
L3: committed package-lock.json (npm ci failed without it)
gitignore: added paperforge/plugin/node_modules/
These are CI config issues, not code regressions from v2.1.
- Add Runtime Health section in settings showing Plugin vX vs Python vY
- Add match/mismatch badge (green/red) with version comparison
- Add 'Sync Runtime' button that runs pip install --upgrade
- Add Dashboard yellow drift warning banner on version mismatch
- Extend _formatSetupError to 10 categories (pip/network/SSL/disk/Python/etc)
- Add 'Copy diagnostic' button on setup failure with env info
- Add all i18n keys in both en and zh
- Add CSS for badge states, drift banner, and diagnostic button
- Add clarifying comment in bump.py about canonical version source
- Update root and plugin manifest.json minAppVersion from 1.0.0 to 1.9.0
- Update versions.json compatibility mapping to 1.9.0
- Add pyyaml>=6.0 to pyproject.toml dependencies
Part A: All 8 subprocess call sites now use resolvePythonExecutable with
settings and extraArgs propagation for py -3 support:
- _fetchVersion, _fetchStats, _runAction, _preCheck, _runInstall, _stepComplete,
_autoUpdate, command palette
- Zero bare 'python' spawn/exec calls remain
- Spaces-in-path safe via execFile instead of shell-string exec
Part B: zotero_data_dir required with validation:
- field_zotero_placeholder i18n updated to 'Required'/'必填'
- Wizard placeholder uses t() call instead of hardcoded string
- _validateStep3 checks: non-empty -> exists -> isDirectory -> has storage/
- _validate() rejects missing zotero_data_dir with validate_zotero i18n key
- zotero_data_dir always passed to --zotero-data flag (no conditional)
- Add python_path to DEFAULT_SETTINGS for storing manual override path
- Refactor resolvePythonExecutable(vaultPath, settings) to return {path, source, extraArgs}
- Manual override (settings.python_path) bypasses auto-detection when set and exists
- Detection order: manual -> .paperforge-test-venv -> .venv -> venv -> py -3 -> python -> python3
- py -3 detection uses extraArgs for proper launcher argument passing
- Stale override re-validated on plugin load; _python_path_stale flag set without clearing
- Update all existing call sites to destructure .path from new return type