mirror of
https://github.com/lllin000/PaperForge.git
synced 2026-07-22 06:50:53 +00:00
fix: remove deprecated control_dir from doctor/setup/repair; enable repair button; fix UTF-8 encoding in doctor output
This commit is contained in:
parent
33bc401cc7
commit
15d849f7e6
11 changed files with 30 additions and 55 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "paperforge",
|
||||
"name": "PaperForge",
|
||||
"version": "1.4.17rc4",
|
||||
"version": "1.4.17",
|
||||
"minAppVersion": "1.9.0",
|
||||
"description": "PaperForge — Zotero literature pipeline. Sync PDFs, run OCR, and read with AI-assisted deep reading.",
|
||||
"author": "Lin Zhaoxuan",
|
||||
|
|
|
|||
|
|
@ -309,11 +309,6 @@ def build_parser() -> argparse.ArgumentParser:
|
|||
metavar="NAME",
|
||||
help="Literature directory name (default: Literature)",
|
||||
)
|
||||
p_setup.add_argument(
|
||||
"--control-dir",
|
||||
metavar="NAME",
|
||||
help="Control directory name (default: LiteratureControl)",
|
||||
)
|
||||
p_setup.add_argument(
|
||||
"--base-dir",
|
||||
metavar="NAME",
|
||||
|
|
@ -497,7 +492,6 @@ def main(argv: list[str] | None = None) -> int:
|
|||
"system_dir": getattr(args, "system_dir", None) or "System",
|
||||
"resources_dir": getattr(args, "resources_dir", None) or "Resources",
|
||||
"literature_dir": getattr(args, "literature_dir", None) or "Literature",
|
||||
"control_dir": getattr(args, "control_dir", None) or "LiteratureControl",
|
||||
"base_dir": getattr(args, "base_dir", None) or "Bases",
|
||||
}
|
||||
plan = SetupPlan(
|
||||
|
|
|
|||
|
|
@ -57,16 +57,17 @@ def run(args: argparse.Namespace) -> int:
|
|||
)
|
||||
|
||||
# ── Build PFResult ──
|
||||
divergent = result.get("divergent", 0)
|
||||
path_errors = result.get("path_errors", {})
|
||||
divergent: list = result.get("divergent", [])
|
||||
path_errors: dict = result.get("path_errors", {})
|
||||
divergent_count = len(divergent)
|
||||
path_error_total = path_errors.get("total", 0)
|
||||
has_issues = bool(divergent) or path_error_total > 0
|
||||
has_issues = divergent_count > 0 or path_error_total > 0
|
||||
|
||||
pf_error = None
|
||||
if has_issues:
|
||||
pf_error = PFError(
|
||||
code=ErrorCode.VALIDATION_ERROR,
|
||||
message=f"Repair found {divergent} divergences and {path_error_total} path errors",
|
||||
message=f"Repair found {divergent_count} divergences and {path_error_total} path errors",
|
||||
details=result,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -165,8 +165,6 @@ const ACTIONS = [
|
|||
cmd: "repair",
|
||||
args: ["--fix", "--fix-paths"],
|
||||
okMsg: "Repair complete",
|
||||
disabled: true,
|
||||
disabledMsg: "Repair Issues will be available in a future update.",
|
||||
},
|
||||
{
|
||||
id: "paperforge-copy-context",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "paperforge",
|
||||
"name": "PaperForge",
|
||||
"version": "1.4.17rc4",
|
||||
"version": "1.4.17",
|
||||
"minAppVersion": "1.9.0",
|
||||
"description": "PaperForge — Zotero literature pipeline. Sync PDFs, run OCR, and read with AI-assisted deep reading.",
|
||||
"author": "Lin Zhaoxuan",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"1.4.3": "1.0.0",
|
||||
"1.4.17rc3": "1.9.0",
|
||||
"1.4.17rc4": "1.9.0"
|
||||
"1.4.17": "1.9.0"
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ from paperforge.setup import SetupStepResult
|
|||
class ConfigWriter:
|
||||
"""Write paperforge.json atomically using tempfile + os.replace."""
|
||||
|
||||
REQUIRED_KEYS = ["system_dir", "resources_dir", "literature_dir", "control_dir"]
|
||||
REQUIRED_KEYS = ["system_dir", "resources_dir", "literature_dir"]
|
||||
|
||||
def __init__(self, vault: Path):
|
||||
self.vault = vault
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class VaultInitializer:
|
|||
"system_dir": "99_System",
|
||||
"resources_dir": "03_Resources",
|
||||
"literature_dir": "Literature",
|
||||
"control_dir": "99_System/PaperForge",
|
||||
# control_dir 已淘汰 (v2.1+ workspace 架构)
|
||||
}
|
||||
|
||||
def __init__(self, vault: Path, config: dict):
|
||||
|
|
@ -29,7 +29,7 @@ class VaultInitializer:
|
|||
self.vault / "paperforge.json",
|
||||
]
|
||||
|
||||
for key in ("system_dir", "resources_dir", "literature_dir", "control_dir"):
|
||||
for key in ("system_dir", "resources_dir", "literature_dir"):
|
||||
rel = self.config.get(key, self.DEFAULT_DIRS.get(key, ""))
|
||||
if rel:
|
||||
dirs_to_create.append(self.vault / rel)
|
||||
|
|
|
|||
|
|
@ -423,7 +423,6 @@ def _substitute_vars(
|
|||
system_dir: str,
|
||||
resources_dir: str,
|
||||
literature_dir: str,
|
||||
control_dir: str,
|
||||
base_dir: str,
|
||||
skill_dir: str,
|
||||
prefix: str = "/",
|
||||
|
|
@ -433,7 +432,6 @@ def _substitute_vars(
|
|||
("<system_dir>", system_dir),
|
||||
("<resources_dir>", resources_dir),
|
||||
("<literature_dir>", literature_dir),
|
||||
("<control_dir>", control_dir),
|
||||
("<base_dir>", base_dir),
|
||||
("<skill_dir>", skill_dir),
|
||||
("<prefix>", prefix),
|
||||
|
|
@ -519,7 +517,6 @@ def _deploy_skill_directory(
|
|||
system_dir: str,
|
||||
resources_dir: str,
|
||||
literature_dir: str,
|
||||
control_dir: str,
|
||||
base_dir: str,
|
||||
prefix: str = "/",
|
||||
) -> list[str]:
|
||||
|
|
@ -543,7 +540,7 @@ def _deploy_skill_directory(
|
|||
skill_dst.mkdir(parents=True, exist_ok=True)
|
||||
text = skill_file.read_text(encoding="utf-8")
|
||||
text = _substitute_vars(
|
||||
text, system_dir, resources_dir, literature_dir, control_dir, base_dir, skill_dir, prefix
|
||||
text, system_dir, resources_dir, literature_dir, base_dir, skill_dir, prefix
|
||||
)
|
||||
_write_text_incremental(skill_dst / "SKILL.md", text)
|
||||
imported.append(skill_name)
|
||||
|
|
@ -573,7 +570,6 @@ def _deploy_flat_command(
|
|||
system_dir: str,
|
||||
resources_dir: str,
|
||||
literature_dir: str,
|
||||
control_dir: str,
|
||||
base_dir: str,
|
||||
skill_dir: str,
|
||||
) -> list[str]:
|
||||
|
|
@ -589,7 +585,7 @@ def _deploy_flat_command(
|
|||
command_dst.mkdir(parents=True, exist_ok=True)
|
||||
for f in command_src.glob("pf-*.md"):
|
||||
text = f.read_text(encoding="utf-8")
|
||||
text = _substitute_vars(text, system_dir, resources_dir, literature_dir, control_dir, base_dir, skill_dir)
|
||||
text = _substitute_vars(text, system_dir, resources_dir, literature_dir, base_dir, skill_dir)
|
||||
_write_text_incremental(command_dst / f.name, text)
|
||||
imported.append(f.stem)
|
||||
|
||||
|
|
@ -603,7 +599,6 @@ def _deploy_rules_file(
|
|||
system_dir: str,
|
||||
resources_dir: str,
|
||||
literature_dir: str,
|
||||
control_dir: str,
|
||||
base_dir: str,
|
||||
skill_dir_path: str,
|
||||
) -> list[str]:
|
||||
|
|
@ -638,7 +633,6 @@ def headless_setup(
|
|||
system_dir: str = "System",
|
||||
resources_dir: str = "Resources",
|
||||
literature_dir: str = "Literature",
|
||||
control_dir: str = "LiteratureControl",
|
||||
base_dir: str = "Bases",
|
||||
zotero_data: str | None = None,
|
||||
skip_checks: bool = False,
|
||||
|
|
@ -657,7 +651,6 @@ def headless_setup(
|
|||
system_dir: System directory name.
|
||||
resources_dir: Resources directory name.
|
||||
literature_dir: Literature subdirectory name.
|
||||
control_dir: Control subdirectory name.
|
||||
base_dir: Base directory name.
|
||||
zotero_data: Zotero data directory (auto-detect if None).
|
||||
skip_checks: Skip environment validation.
|
||||
|
|
@ -770,7 +763,6 @@ def headless_setup(
|
|||
"system_dir": system_dir,
|
||||
"resources_dir": resources_dir,
|
||||
"literature_dir": literature_dir,
|
||||
"control_dir": control_dir,
|
||||
"base_dir": base_dir,
|
||||
}
|
||||
|
||||
|
|
@ -867,7 +859,6 @@ def headless_setup(
|
|||
system_dir,
|
||||
resources_dir,
|
||||
literature_dir,
|
||||
control_dir,
|
||||
base_dir,
|
||||
skill_dir,
|
||||
)
|
||||
|
|
@ -879,7 +870,6 @@ def headless_setup(
|
|||
system_dir,
|
||||
resources_dir,
|
||||
literature_dir,
|
||||
control_dir,
|
||||
base_dir,
|
||||
prefix,
|
||||
)
|
||||
|
|
@ -891,7 +881,6 @@ def headless_setup(
|
|||
system_dir,
|
||||
resources_dir,
|
||||
literature_dir,
|
||||
control_dir,
|
||||
base_dir,
|
||||
skill_dir,
|
||||
)
|
||||
|
|
@ -904,7 +893,6 @@ def headless_setup(
|
|||
system_dir,
|
||||
resources_dir,
|
||||
literature_dir,
|
||||
control_dir,
|
||||
base_dir,
|
||||
prefix,
|
||||
)
|
||||
|
|
@ -965,7 +953,6 @@ def headless_setup(
|
|||
("<system_dir>", system_dir),
|
||||
("<resources_dir>", resources_dir),
|
||||
("<literature_dir>", literature_dir),
|
||||
("<control_dir>", control_dir),
|
||||
("<base_dir>", base_dir),
|
||||
("<skill_dir>", skill_dir),
|
||||
]:
|
||||
|
|
|
|||
|
|
@ -354,6 +354,21 @@ def _query_resolved_module(interp: str, extra_args: list[str], module_name: str)
|
|||
return None
|
||||
|
||||
|
||||
if sys.platform == "win32":
|
||||
try:
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
except AttributeError:
|
||||
import codecs
|
||||
|
||||
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.buffer)
|
||||
try:
|
||||
import ctypes
|
||||
|
||||
ctypes.windll.kernel32.SetConsoleOutputCP(65001)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def run_doctor(vault: Path, verbose: bool = False, json_output: bool = False) -> int:
|
||||
"""Validate PaperForge setup and report by category.
|
||||
|
||||
|
|
@ -491,16 +506,7 @@ def run_doctor(vault: Path, verbose: bool = False, json_output: bool = False) ->
|
|||
"Vault 结构", "fail", f"resources_dir 不存在: {cfg['resources_dir']}", f"运行: mkdir {cfg['resources_dir']}"
|
||||
)
|
||||
|
||||
control_dir = resources_dir / cfg.get("control_dir", "LiteratureControl")
|
||||
if control_dir.exists():
|
||||
add_check("Vault 结构", "pass", f"control_dir 存在: {cfg.get('control_dir', 'LiteratureControl')}")
|
||||
else:
|
||||
add_check(
|
||||
"Vault 结构",
|
||||
"fail",
|
||||
f"control_dir 不存在: {cfg.get('control_dir', 'LiteratureControl')}",
|
||||
f"运行: mkdir {cfg['resources_dir']}/{cfg.get('control_dir', 'LiteratureControl')}",
|
||||
)
|
||||
# control_dir 已完全淘汰 (v2.1+ workspace 架构不再需要 LiteratureControl)
|
||||
|
||||
zotero_link = system_dir / "Zotero"
|
||||
if zotero_link.exists():
|
||||
|
|
@ -798,17 +804,6 @@ def run_doctor(vault: Path, verbose: bool = False, json_output: bool = False) ->
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
# LRD-05: Stale record detection in control directory
|
||||
_lr_dir = paths.get("control")
|
||||
if _lr_dir and _lr_dir.exists():
|
||||
_stale_count = sum(1 for _ in _lr_dir.rglob("*.md"))
|
||||
if _stale_count > 0:
|
||||
add_check(
|
||||
"Index Health",
|
||||
"warn",
|
||||
f"{_stale_count} stale record(s) found in control directory",
|
||||
"Review and remove stale files from the control directory",
|
||||
)
|
||||
else:
|
||||
add_check("Index Health", "info", "No canonical index -- run `paperforge sync` to generate")
|
||||
|
||||
|
|
@ -1114,7 +1109,6 @@ def run_status(vault: Path, verbose: bool = False, json_output: bool = False) ->
|
|||
print(f"- system_dir: {cfg['system_dir']}")
|
||||
print(f"- resources_dir: {cfg['resources_dir']}")
|
||||
print(f"- literature_dir: {cfg['literature_dir']}")
|
||||
print(f"- control_dir: {cfg['control_dir']}")
|
||||
print(f"- exports: {len(export_files)} JSON file(s)")
|
||||
print(f"- domains: {len(config.get('domains', []))}")
|
||||
print(f"- formal_notes: {record_count}")
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ def cli_invoker(vault_builder):
|
|||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
timeout=60,
|
||||
input=input_text,
|
||||
env=base_env,
|
||||
|
|
|
|||
Loading…
Reference in a new issue