Status: Historical compatibility-window record
Last Updated: 2026-04-24
Scope: historical execution order for directory and path migration. This file preserves the compatibility-window migration record; it is no longer the source of truth for the active breaking-cleanup runtime.
2026-04-24 breaking cleanup note:
- this document remains the historical execution record for the compatibility-window generation
- current runtime behavior is no longer compatibility-window behavior: legacy public import facades are removed and legacy runtime roots are no longer auto-opened
- the active breaking-generation execution authority is kept in internal release-gate records
- the hardened post-migration user cleanup flow is now
scholaraio migrate finalize --confirm
This document defines the recommended execution order for migrating ScholarAIO toward the target directory structure described in docs/design-docs/directory-structure-spec.md.
This is an implementation-order document, not a vision document. Its job is to answer:
- what MUST be frozen first
- what MUST be abstracted before any physical move
- when migration control-plane work MUST land before real user-data moves
- which migrations are low-risk leaf moves
- which migrations are high-risk and MUST be deferred
- how to keep multi-agent skill discovery and current CLI behavior working during the transition
This document should be read together with:
docs/design-docs/migration-mechanism-spec.md
That companion document defines the control-plane contract (instance.json, migration.lock, journal, verification, cleanup gating). This document defines when that machinery must appear in the execution order.
The sequence below is based on direct inspection of the current codebase and on path-related regression tests revalidated on 2026-04-19 after the earlier 2026-04-16, 2026-04-17, and 2026-04-18 audits.
The entries in this subsection describe the compatibility-window state that was audited before the 2026-04-24 breaking cleanup. Parenthetical legacy import paths below are historical targets from that window; they are not active public facades in the current release generation.
scholaraio/core/config.py(scholaraio.configcompatibility alias)scholaraio/cli.pyscholaraio/projects/workspace.py(scholaraio.workspacecompatibility alias)scholaraio/services/insights.py(scholaraio.insightscompatibility alias)scholaraio/services/setup.py(scholaraio.setupcompatibility alias)scholaraio/services/index.py(scholaraio.indexcompatibility alias)scholaraio/services/loader.py(scholaraio.loadercompatibility alias)scholaraio/services/topics.py(scholaraio.topicscompatibility alias)scholaraio/services/vectors.py(scholaraio.vectorscompatibility alias)scholaraio/stores/explore.py(scholaraio.explorecompatibility alias)scholaraio/services/diagram.py(scholaraio.diagramcompatibility alias)scholaraio/stores/proceedings.py(scholaraio.proceedingscompatibility alias)scholaraio/services/patent_fetch.py(scholaraio.patent_fetchcompatibility alias)scholaraio/providers/arxiv.py(scholaraio.sources.arxivcompatibility alias)scholaraio/providers/endnote.py(scholaraio.sources.endnotecompatibility alias)scholaraio/providers/zotero.py(scholaraio.sources.zoterocompatibility alias)scholaraio/providers/mineru.py(scholaraio.ingest.minerucompatibility alias)scholaraio/providers/pdf_fallback.py(scholaraio.ingest.pdf_fallbackcompatibility alias)scholaraio/services/ingest_metadata/extractor.py(scholaraio.ingest.extractorcompatibility alias)scholaraio/services/ingest/parser_matrix_benchmark.py(scholaraio.ingest.parser_matrix_benchmarkcompatibility alias)scholaraio/services/ingest/proceedings_volume.py(scholaraio.ingest.proceedingscompatibility alias)scholaraio/providers/uspto_odp.py(scholaraio.uspto_odpcompatibility alias)scholaraio/providers/uspto_ppubs.py(scholaraio.uspto_ppubscompatibility alias)scholaraio/services/backup.py(scholaraio.backupcompatibility alias)scholaraio/sources/webtools.pyscholaraio/toolref/paths.pyscholaraio/toolref/_legacy_snapshot.pyscholaraio/stores/citation_styles.py(scholaraio.citation_stylescompatibility alias)scholaraio/services/translate.py(scholaraio.translatecompatibility alias)scholaraio/services/ingest/pipeline.py(scholaraio.ingest.pipelinecompatibility alias).qwen/QWEN.mdclawhub.yaml.cursor/rules/scholaraio.mdc
Historical audited facts from the compatibility-window generation:
The following bullets intentionally preserve the pre-cleanup compatibility
language used during migration planning. In the active release generation, legacy
public import facades have been removed; see the internal breaking-cleanup
release gate and docs/guide/agent-reference.md for the current contract.
scholaraio/core/config.pynow exposes a much broader runtime-path accessor surface and routesensure_dirs()through those accessors, which lowers path-migration risk but does not yet remove direct path construction in downstream modulesscholaraio/core/config.pynow resolvesindex_db,metrics_db_path, andtopics_model_dirthrough logicalstate_rootsubdirectories for fresh installs, while still auto-detecting existing legacydata/index.db,data/metrics.db, anddata/topic_model/storesscholaraio/core/config.pylocks current root-levelconfig.yamldiscovery behavior;scholaraio.configremains the legacy import path for compatibilityscholaraio/projects/workspace.pynow owns the workspace paper-index layout contract and supports both legacy rootpapers.jsonand future-compatiblerefs/papers.json;scholaraio.workspaceremains the compatibility aliasscholaraio/cli.pynow routes workspace-root defaults through_workspace_root()and defers workspace index existence checks toscholaraio.workspacescholaraio/services/setup.py:531-537now checks current runtime directories viaConfigaccessors instead of fixed string literalsscholaraio/services/index.pynow owns keyword search, proceedings search, registry lookup, citation graph helpers, and unified search orchestration;scholaraio.indexremains a module alias so CLI and tests can keep using the public legacy import pathscholaraio/services/loader.pynow owns L1-L4 layered paper loading, agent notes, TOC enrichment, and L3 extraction;scholaraio.loaderremains a module alias so CLI and tests can keep using the public legacy import pathscholaraio/services/topics.pynow owns BERTopic fitting, topic browsing, reduction/merge helpers, model persistence, and visualizations;scholaraio.topicsremains a module alias so CLI, explore, workspace, and tests can keep using the public legacy import pathscholaraio/services/vectors.pynow owns embedding backend selection, vector index maintenance, FAISS helpers, and semantic search;scholaraio.vectorsremains a module alias so CLI, topics, explore, and tests can keep using the public legacy import pathscholaraio/stores/explore.pynow followscfg.explore_root;scholaraio.exploreremains the compatibility alias, fresh instances default todata/libraries/explore/, while existing legacydata/explore/remains auto-detectedscholaraio/services/diagram.pynow routes default output throughcfg.workspace_figures_dir; fresh instances default toworkspace/_system/figures/scholaraio/stores/proceedings.pynow owns proceedings storage iteration and proceedings DB path helpers;scholaraio.proceedingsremains a module alias so existing imports and monkeypatches still target the same implementationscholaraio/services/patent_fetch.py:download_patent_pdfnow preferscfg.patent_inbox_dir; fresh no-config defaults usedata/spool/inbox-patent, while legacydata/inbox-patentremains auto-detected throughConfigscholaraio/providers/arxiv.pynow owns arXiv search, metadata fetch, and PDF download helpers;scholaraio.sources.arxivremains a module alias so existing imports and monkeypatches still target the same implementationscholaraio/providers/endnote.pynow owns EndNote XML/RIS parsing and PDF attachment discovery;scholaraio.sources.endnoteremains a module alias so existing imports and monkeypatches still target the same implementationscholaraio/providers/zotero.pynow owns Zotero Web API and local SQLite parsing;scholaraio.sources.zoteroremains a module alias so existing imports and monkeypatches still target the same implementationscholaraio/providers/mineru.pynow owns MinerU local/cloud PDF parsing helpers and its module CLI;scholaraio.ingest.mineruremains a module alias/import-compatible CLI delegator so existing imports, monkeypatches, andpython -m scholaraio.ingest.minerustill target the same implementationscholaraio/providers/pdf_fallback.pynow owns Docling/PyMuPDF fallback parsing;scholaraio.ingest.pdf_fallbackremains a module alias so existing imports and monkeypatches still target the same implementationscholaraio/services/ingest_metadata/extractor.pynow owns Stage-1 metadata extraction modes;scholaraio.ingest.extractorremains a module alias so existing imports and monkeypatches still target the same implementationscholaraio/services/ingest/parser_matrix_benchmark.pynow owns parser matrix benchmarking helpers;scholaraio.ingest.parser_matrix_benchmarkremains a module alias so existing imports and monkeypatches still target the same implementationscholaraio/services/ingest/proceedings_volume.pynow owns proceedings volume preparation, split-plan application, and clean-plan application;scholaraio.ingest.proceedingsremains a module alias so existing imports and monkeypatches still target the same implementationscholaraio/providers/uspto_odp.pynow owns the USPTO ODP API client;scholaraio.uspto_odpremains a module alias so existing imports and monkeypatches still target the same implementationscholaraio/providers/uspto_ppubs.pynow owns the USPTO PPUBS session/search/PDF-export client;scholaraio.uspto_ppubsremains a module alias so existing imports and monkeypatches still target the same implementationscholaraio/services/ingest/pipeline.pynow exposes the ingest pipeline compatibility facade, and routes inbox/pending/proceedings defaults through small accessor helpers (_inbox_dir,_pending_dir,_proceedings_dir, etc.), with fresh queue defaults underdata/spool/scholaraio/services/backup.pyplusscholaraio/core/config.pyconfirm backup still defaults to syncingdata/, not the full runtime rootscholaraio/providers/webtools.pyforms the external-adapter seam; the current default product exposes rendered extraction through both legacy HTTP/extractand qt-web-extractor MCPfetch_url, while the old search adapter remains an unregistered compatibility implementationscholaraio/toolref/paths.py:9-20now followscfg.toolref_root; fresh instances default todata/libraries/toolref/, while existing legacydata/toolref/remains auto-detectedscholaraio/toolref/_legacy_snapshot.py:111-130preserves the samecfg.toolref_rootbehavior in a parallel legacy implementationscholaraio/stores/citation_styles.py:253-255now followscfg.citation_styles_dir; fresh instances default todata/libraries/citation_styles/, while existing legacydata/citation_styles/remains auto-detectedscholaraio/services/translate.pynow resolves portable translation bundles throughcfg.translation_bundle_root; fresh instances default toworkspace/_system/translation-bundles/scholaraio/services/ingest/pipeline.pystill concentrates the compatibility surface for queue/proceedings orchestration, but its default directory resolution now flows through explicit helper functions instead of raw literals.qwen/QWEN.md:9-13andclawhub.yaml:16-127confirm that skill discovery is rooted in.claude/skills/tests/test_cursor_rules.py:8-27,tests/test_academic_writing_skills.py:80-87,tests/test_workspace.py,tests/test_explore.py:42-43, andtests/test_translate.py:230-320lock the current discovery and path contracts, including workspace legacy/future compatibility plus configured translation-bundle overrides
The following test batches were executed successfully as migration-baseline verification:
python -m pytest -q \
tests/test_cursor_rules.py \
tests/test_writing_docs_alignment.py \
tests/test_academic_writing_skills.py \
tests/test_skill_routing_smoke.py \
tests/test_workspace.py \
tests/test_config.py
python -m pytest -q \
tests/test_explore.py \
tests/test_translate.py \
tests/test_webtools_source.py \
tests/test_ingest_link_cli.py \
tests/test_proceedings.py \
tests/test_cli_messages.py
# 2026-04-17 revalidation after additional develop-branch merges
python -m pytest -q \
tests/test_config.py \
tests/test_explore.py \
tests/test_translate.py \
tests/test_proceedings.py \
tests/test_metrics.py
python -m pytest -q \
tests/test_patent_tools.py \
tests/test_backup.py \
tests/test_diagram.py \
tests/test_document.pyObserved result:
- the combined baseline batch list above currently re-runs as
283passing tests on 2026-04-18 - the 2026-04-17 revalidation batches also passed with
165passing tests plus100passing tests and3skips - no failures
These constraints are already enforced by current code, wrappers, and tests. The migration sequence MUST treat them as frozen until their replacements are intentionally designed and tested.
Compatibility-window behavior in scholaraio/core/config.py (before removal of
the legacy scholaraio.config import path):
load_config()resolves paths relative to the directory containingconfig.yaml_find_config_file()searches upward forconfig.yaml- fallback global config is
~/.scholaraio/config.yaml
Implication:
config.yamlandconfig.local.yamlMUST remain valid at runtime-instance root during early and middle migration phases- moving config into
config/MUST NOT happen before config discovery is redesigned
Current wrappers and tests assume fixed root-level entry points:
AGENTS.mdCLAUDE.mdAGENTS_CN.md.qwen/QWEN.md.cursor/rules/.clinerules.windsurfrules.github/copilot-instructions.md.claude-plugin/clawhub.yaml
Implication:
- these files and directories MUST NOT be moved as part of directory migration
Current audited behavior:
.claude/skills/is the canonical skill source.agents/skills,.qwen/skills, andskillsare compatibility aliasesclawhub.yamlregisters skill paths as.claude/skills/<name>.qwen/QWEN.mdexplicitly instructs Qwen to use.qwen/skills/- tests assert
.cursor/rules/scholaraio.mdcreferences.claude/skills/*/SKILL.md
Implication:
- no migration phase may move
SKILL.mdfiles intoscholaraio/ - no migration phase may remove the repository-root discovery surfaces for skills
Current code assumes both of the following runtime top-level directories exist:
data/workspace/
Implication:
- early migration phases MUST keep those top-level anchors intact
- physical re-rooting under
data/libraries,data/spool,data/state, and related subtrees can only happen after accessor cutover
Migration MUST follow this order:
- freeze invariants and tests
- add path accessors
- switch consumers to accessors
- add compatibility readers/writers if formats change
- perform physical moves last
Direct physical directory moves before consumer cutover are explicitly out of order.
The execution order below follows the actual current coupling, not the desired architecture.
scholaraio/core/config.py currently exposes accessors for the major runtime roots:
- paper/workspace roots
- queue and pending roots
- proceedings/explore/toolref/citation-style durable-library roots
- state/cache/runtime roots
- control-plane roots
ensure_dirs() now routes through these accessors rather than recreating fixed legacy strings.
Implication:
- physical moves must continue to happen through explicit migration tooling, not by reintroducing raw path construction in consumers
- remaining migration phases should preserve explicit config overrides and legacy fallback behavior until cleanup has archived the old trees
Current behavior:
scholaraio/projects/workspace.pynow owns the paper-index layout contract and can read both<workspace-root>/<name>/papers.jsonand<workspace-root>/<name>/refs/papers.jsonscholaraio/projects/workspace.pystill creates new workspaces with rootpapers.jsonby default, but preserves existing future-compatiblerefs/papers.jsonlayouts for reads and writesscholaraio/cli.pynow routes workspace paths through_workspace_root()/cfg.workspace_dirand usesscholaraio.workspacehelpers for workspace index detectionscholaraio/services/insights.pynow counts workspaces throughscholaraio.workspace.paper_count()scholaraio/services/diagram.pydefaults generated diagrams throughcfg.workspace_figures_dir, which resolves to<workspace>/_system/figures/for fresh instancesscholaraio/interfaces/cli/export.pydefaults DOCX export throughcfg.workspace_docx_output_path, which resolves to<workspace>/_system/output/output.docxfor fresh instancestests/test_workspace.pynow locks both legacy and future-compatible workspace paper-index contractstests/test_translate.pylocks both the fresh portable bundle default underworkspace/_system/translation-bundles/and explicittranslation_bundle_rootoverrides
Implication:
- workspace is still not ready for a direct physical move, but the compatibility bridge now exists inside
projects/workspace.py - later migration steps must build on that module boundary instead of bypassing it with direct
papers.jsonpath checks - migration still must account for both named workspaces and legacy workspace-root output conventions
Current behavior:
scholaraio/services/ingest/pipeline.pystill owns the compatibility surface for queue/proceedings orchestration, but default directory resolution now uses helper accessors wired toConfigscholaraio/cli.pynow routes arXiv downloads throughcfg.inbox_dir/_default_inbox_dir()scholaraio/services/patent_fetch.pynow routes patent downloads throughcfg.patent_inbox_dirwhen available, with legacy fallback preserved for compatibilityscholaraio/services/setup.pychecks configured queue roots, pending spool, and workspace throughConfig
Implication:
- queue/spool migration is a late, high-risk phase
- it MUST wait until path accessors exist and shallow consumers have already moved
Current audited path helpers:
scholaraio/stores/explore.pynow followscfg.explore_rootwith a durable-library fresh default and legacy fallbackscholaraio/toolref/paths.pynow followscfg.toolref_rootwith a durable-library fresh default and legacy fallbackscholaraio/toolref/_legacy_snapshot.pystill mirrors the same config-backed root behaviorscholaraio/stores/citation_styles.pynow followscfg.citation_styles_dirwith a durable-library fresh default and legacy fallbackscholaraio/services/translate.pynow resolves portable translation bundles throughtranslation_bundle_root
Implication:
- these modules now already sit behind config-backed accessors before larger pipeline moves
explore,toolref,citation_styles, and portable translation outputs are safer physical-move candidates thanpapers
Current behavior:
services/backup.pysyncscfg.backup_source_dir- default backup scope is still
data/ - the backup feature does not automatically cover
workspace/, config files, or future migration-control metadata
Implication:
- backup remains a useful operator tool
- but migration design MUST NOT treat it as the primary rollback or relocation contract for runtime-layout upgrades
The migration is split into two tracks:
- Track A: runtime-instance directory migration
- Track B: source-repository package migration
Track A is the critical path and MUST happen first. Track B SHOULD begin only after Track A has established stable accessors and compatibility layers.
Objective:
- lock down the currently relied-on root integration surfaces and path contracts
Actions:
- keep root agent wrappers and
.claude/skills/unchanged - keep top-level
data/andworkspace/unchanged - treat the current test batches in Section 2.2 as the minimum migration baseline
- add any missing tests only for newly introduced accessors and compatibility behavior
Do not do yet:
- no directory renames
- no symlink migration tricks
- no moving
config.yaml
Exit criteria:
- path-related baseline tests remain green
- migration work starts from a known compatibility floor
Objective:
- eliminate hardcoded runtime paths from leaf modules and orchestration code by first exposing them through
Config
Primary audit reference: internal config-surface audit records.
Required additions in or around scholaraio/core/config.py:
- inbox path accessors
inbox_dirdoc_inbox_dirthesis_inbox_dirpatent_inbox_dirproceedings_inbox_dir
- durable/runtime accessors
pending_dirproceedings_direxplore_roottoolref_rootcitation_styles_dirtranslation_bundle_root
- future-state accessors
state_rootcache_rootruntime_root
Immediate consumer updates in this phase:
Config.ensure_dirs()must switch to the new accessorsscholaraio/services/setup.pydirectory checks must switch to the new accessors
Rationale:
- these are the lowest-level central choke points
- if this phase is skipped, later moves will produce duplicated path logic
Exit criteria:
- no module still needs to invent raw runtime paths for the directories above
- defaults still resolve to the current physical layout
- existing behavior remains unchanged
Objective:
- convert low-blast-radius modules to accessor-based path resolution while keeping the physical layout unchanged
Modules in scope:
scholaraio/stores/explore.py(scholaraio.explorecompatibility alias)scholaraio/toolref/paths.pyscholaraio/toolref/_legacy_snapshot.pyscholaraio/stores/citation_styles.py(scholaraio.citation_stylescompatibility alias)scholaraio/services/translate.py(scholaraio.translatecompatibility alias)
Required changes:
- replace
cfg._root / "data" / ...constructions withConfigaccessors - preserve the new
citation_styles_diraccessor behavior: fresh durable-library default plus legacy fallback until cleanup is complete - stop hardcoding
workspace/translation-ws/in helper implementations; route throughtranslation_bundle_root
Why this phase comes early:
- these modules already have narrow, local path boundaries
- they are easier to validate than
pipeline.py
Exit criteria:
tests/test_explore.pyandtests/test_translate.pystill pass- equivalent path-override tests exist for the new accessors
- no physical directory move has happened yet
Objective:
- remove direct
cfg._root / "workspace"and similar constructions from non-orchestration interface code
Modules in scope:
scholaraio/cli.pyscholaraio/services/insights.py(scholaraio.insightscompatibility alias)
Required changes:
- use
cfg.workspace_direverywhere instead of re-constructing workspace root - use new path accessors for explore, translation, and patent-fetch defaults
- isolate legacy workspace-root output conventions such as
workspace/figures/andworkspace/output.docxbehind explicit helpers or compatibility rules instead of raw literals - keep CLI surface behavior unchanged
Why this phase is separate from A2:
- the CLI touches more commands and user-facing defaults
- but it is still lower risk than workspace schema change or ingest queue migration
Exit criteria:
cmd_ws,_resolve_ws_paper_ids, arXiv inbox download, patent fetch defaults, and insights workspace listing no longer hardcode raw runtime paths where an accessor exists- CLI output and user-facing defaults remain backward compatible
Objective:
- make workspace independently evolvable without breaking the current
workspace/<name>/papers.jsoncontract
Current constraint:
- current code and tests treat
papers.jsonat workspace root as the canonical paper-ref index
Required changes:
- extend
scholaraio/projects/workspace.pyto become the single authority for workspace layout - add compatibility helpers so the module can read:
- legacy root
papers.json - future
refs/papers.json
- legacy root
- if a future
workspace.yamlmanifest is introduced, treat it as additive first, not replacing legacy files immediately - keep named workspaces as opaque/free-form project roots instead of turning them into rigid templates
Do not do yet:
- do not move workspaces out of the top-level
workspace/ - do not remove support for root
papers.json - do not remove legacy workspace-root outputs until explicit compatibility helpers or migration rules own them
Rationale:
- workspace is evolving from paper subset into project boundary
- that evolution needs a compatibility bridge, not a direct cut
For the compatibility window and the next migration design pass, the workspace-topology direction is now fixed:
- named workspaces remain opaque/free-form project roots
workspace/translation-ws/->workspace/_system/translation-bundles/workspace/figures/->workspace/_system/figures/workspace/output.*->workspace/_system/output/- the minimal additive
workspace.yamlenvelope isschema_version, optionalname/description/tags, optional explicitmounts, and optionaloutputs; it MUST NOT replace rootpapers.jsonor future-compatiblerefs/papers.json - the validation/normalization policy for that minimal envelope is also fixed: absent manifests stay valid, unknown keys are preserved,
outputs.default_dirstays workspace-relative, and shared-store mounts are logical IDs rather than physical paths exploreremains a shared store for the compatibility window; if workspace-local mounts are added later, they MUST be explicit manifest-declared opt-ins and SHOULD start read-only.claude/skills/remains the canonical skill source and is not a migration target- only outputs that are explicitly scoped to a named workspace should later use
workspace/<name>/outputs/
Exit criteria:
workspace.pyowns the layout contracttests/test_workspace.pystill pass- new tests cover legacy and future-compatible readers
Implementation status (2026-04-20):
- completed in code:
workspace.py,cli.py, andinsights.pynow consume the compatibility layer instead of assuming only rootpapers.json - completed in code:
projects/workspace.py:read_manifest()now parsesworkspace.yamlwhen present, normalizes supported schema-v1 metadata, preserves unknown top-level keys, rejects path-like shared-store mounts, and treats newer schema versions as opaque metadata instead of rewriting them blindly - completed in code:
interfaces/cli/workspace.pynow surfaces additiveworkspace.yamlmetadata inws list/ws show, while keeping manifest-declared mounts informational only and not turning them into active runtime routing - verified with targeted tests plus real CLI smoke on a future-compatible
refs/papers.jsonworkspace
Objective:
- cut over the highest-risk runtime path knot only after accessor and workspace groundwork are in place
Modules in scope:
scholaraio/services/ingest/pipeline.py(scholaraio.ingest.pipelinecompatibility alias)- queue-related parts of
scholaraio/cli.py scholaraio/services/setup.py(scholaraio.setupcompatibility alias)
Required changes:
- replace all hardcoded queue and pending paths in
run_pipeline() - replace queue and proceedings path construction in helper functions such as:
import_external()_move_to_pending()- proceedings ingest context helpers
- route arXiv and ingest-link related temporary and default paths through accessors where appropriate
Why this is late:
pipeline.pyis the densest operational hub for runtime directories- changing it before A1-A4 would mix accessor introduction, queue semantics, and physical moves in one step
Exit criteria:
- pipeline logic can operate entirely from accessor-provided queue/store paths
tests/test_ingest_link_cli.pyandtests/test_proceedings.pystill pass- the physical layout is still backward compatible
Objective:
- make internal state directories explicit while leaving user-facing libraries stable
Current central state locations:
index.dbmetrics.dbtopic_model/
Required changes:
- back them with explicit logical roots such as:
data/state/search/data/state/metrics/data/state/topics/
- treat cache-like directories separately from durable stores
- keep existing defaults until all consumers are accessorized
Why this phase precedes major library moves:
- state and cache boundaries are easier to isolate than
papers - they reduce later ambiguity over what is safe to rebuild
Exit criteria:
- search, metrics, and topic-model paths are no longer special cases hidden in unrelated config fields
- migration can now distinguish durable stores from rebuildable internals
Implementation status (2026-04-19):
- completed in code:
Confignow exposes logicalsearch_state_dir,metrics_state_dir, andtopics_state_dir - completed in code: fresh configs default to
data/state/search/index.db,data/state/metrics/metrics.db, anddata/state/topics/ - compatibility retained: existing
data/index.db,data/metrics.db, anddata/topic_model/are still discovered automatically when present - remaining work: physical migration tooling and broader state/cache policy are still deferred to later phases
Objective:
- land the minimum migration control plane before any real user-data directory relocation happens
Required changes:
- reserve the root-level
.scholaraio-control/directory - introduce
instance.json - introduce
migration.lock - introduce per-run migration journals
- introduce explicit verification state
- ensure startup still does compatibility reading without silently performing large moves
Required reference:
- align this phase with
docs/design-docs/migration-mechanism-spec.md
Why this phase exists here:
- once A7 starts, ScholarAIO is no longer just refactoring paths; it is performing real user-data migration work
- physical moves without the control plane would make rollback, verification, and operator support much weaker
Exit criteria:
- the codebase has a stable root-level control directory contract
- migration can mark runtime roots as legacy / normal / migrating / recovery-needed
- command gating exists while migration is active
- no physical move depends on implicit or startup-time relocation
Historical implementation status during the compatibility window (2026-04-23, superseded by the 2026-04-24 breaking cleanup):
The bullets below are retained as an execution log. Statements that a legacy module path "remains" an alias refer to the compatibility-window implementation, not to the active release generation.
- completed in code for the compatibility window:
Configexposes.scholaraio-control/,instance.json,migration.lock, and journal-root accessors - completed in code for the compatibility window: normal CLI startup bootstraps a minimal
instance.jsonwithlegacy_implicitstate when metadata is absent - completed in code for the compatibility window: normal CLI commands fail fast while
migration.lockexists, andscholaraio migrate status|recover --clear-lockprovides the recovery surface - completed in code for the compatibility window: normal CLI commands also fail fast when
instance.json.layout_versionis newer than the running program supports, whilemigrate statusremains available for diagnosis - completed in code for the compatibility window: migration journals can be scaffolded under
.scholaraio-control/migrations/<migration-id>/, andmigrate statusreports the current journal inventory - completed in code for the compatibility window:
scholaraio migrate plancreates a non-executing journal-backed inventory record (plan.json) with store-level target metadata and planned legacy-move records - completed in code for the compatibility window:
scholaraio migrate verifyrefreshesverify.jsonand records component-aware checks covering papers/workspaces/index-registry/keyword-search/citation-style loadability/explore openability/toolref current-version resolution/proceedings search/translation-resume inventory - completed in code for the compatibility window:
scholaraio migrate run --store citation_styles --confirm,toolref,explore,proceedings,spool, andpaperscopy legacy stores into their current targets and record cleanup candidates - completed in code for the compatibility window:
scholaraio migrate cleanupenforces a passed-verify gate, records preview/confirm journal steps, and archives explicit cleanup candidates under the migration journal instead of deleting them directly - policy is fixed: compatibility fallback readers stay in place through a full deprecation window and may be removed only in a later breaking-layout generation with an approved rollout plan
Objective:
- perform the first real physical directory moves on lower-risk durable stores
Recommended move order:
citation_stylestoolrefexplore
Target subtree:
data/libraries/
Recommended approach:
- switch defaults to the new target paths only after A1-A6.5 are complete
- use explicit migration tooling as the primary mechanism
- only use temporary compatibility symlinks if they are covered by the same migration and verification flow
Why these three come first:
- they already have relatively self-contained path logic
- they are less central than
papers - current tests already isolate
exploreand writing/skill discovery separately
Exit criteria:
- each store can be relocated without editing unrelated modules
- path consumers read only from accessors
- compatibility behavior is documented and tested
Objective:
- move
data/proceedingsinto the durable-library subtree only after pipeline consumers no longer depend on fixed raw paths
Target:
data/libraries/proceedings/
Why this is not grouped with A7:
proceedingsis more tightly coupled to ingest orchestration thantoolref,explore, orcitation_styles- it should move only after A5 has finished queue/proceedings path abstraction
Why this still happens before papers:
- it is materially less central than the main paper library
- moving it earlier helps validate the durable-library migration pattern before the highest-risk store move
Exit criteria:
- proceedings ingest helpers, CLI flows, and tests no longer assume the legacy physical location directly
- durable proceedings storage is clearly separated from proceedings inbox/spool semantics
Implementation status (2026-04-20):
- completed in code for the compatibility window: fresh
Config.proceedings_dirresolves todata/libraries/proceedings/, existingdata/proceedings/remains readable as a legacy fallback,migrate run --store proceedings --confirmcopies the full tree, andmigrate cleanup --confirmarchives the legacy tree into the migration journal
Objective:
- move queue-like content under
data/spool/only after pipeline consumers have been fully abstracted
Recommended target:
data/spool/inboxdata/spool/inbox-thesisdata/spool/inbox-patentdata/spool/inbox-docdata/spool/inbox-proceedingsdata/spool/pending
Notes:
- queue migration MUST include user-facing documentation changes because users directly interact with inbox directories
Exit criteria:
- ingest commands, setup checks, and docs all agree on spool semantics
- no pipeline code still assumes legacy queue paths directly
Implementation status (2026-04-20):
- completed in code for the compatibility window: fresh
Configqueue roots resolve todata/spool/inbox*anddata/spool/pending, existing legacydata/inbox*anddata/pendingqueues remain readable as legacy fallbacks,migrate run --store spool --confirmcopies all queue roots intodata/spool/, andmigrate cleanup --confirmarchives the legacy queue roots into the migration journal
Objective:
- migrate the main paper library only after all less-central stores and queue/state layers are already stable
Target:
data/libraries/papers/
Why this is last:
papersis used by the largest number of modulespapersaffects search, vectors, topics, workspace references, notes, export, enrich, audit, translate, and many CLI flows- current tests, docs, and code all assume it is the center of the system
Required preconditions:
- A1 through A9 complete
- no remaining direct consumer builds
data/papersby string/path convention - registry and UUID-based lookups remain stable across the move
Exit criteria:
papersphysical location is no longer special-cased anywhere outside configuration and explicit migration tooling
Implementation status (2026-04-20):
- completed in code for the compatibility window: fresh
Config.papers_dirresolves todata/libraries/papers/, legacy-default aliases such asdata/paperscontinue to auto-detect existing legacy libraries,migrate run --store papers --confirmcopies the full paper tree, andmigrate cleanup --confirmarchives the legacy paper tree into the migration journal
Objective:
- finish Track A for this upgrade generation without breaking existing runtime roots
Actions:
- keep legacy fallback readers during the migration-capable compatibility window
- update
AGENTS.md,CLAUDE.md, README, setup docs, and relevant skills to describe the final runtime layout plus explicit legacy auto-detection - keep skill discovery surfaces unchanged unless a separate wrapper-versioning plan exists
Exit criteria:
- current public docs point users at the new layout while still explaining how existing legacy layouts are handled
- compatibility-removal work is not attempted until a later breaking-layout generation has an approved rollout plan
Do not do yet:
- do not remove
Configlegacy fallback readers in this branch - do not remove workspace
papers.jsoncompatibility - do not delete legacy import paths while Track B only has namespace skeletons
Implementation status (2026-04-20):
- completed for the non-breaking upgrade window: public docs, agent instructions, setup guidance, and relevant skills now point to
data/libraries/,data/spool/, anddata/state/defaults while documenting legacy auto-detection and explicit migration tooling
Track B is intentionally later and slower than Track A.
Low-risk action:
- create or keep top-level
gui/as a reserved source directory at any time
Constraint:
gui/MUST remain presentation-only- it MUST NOT read raw runtime directories as if they were stable internal APIs
Implementation status (2026-04-20):
- completed as a boundary reservation:
gui/README.mdexists and documents that GUI code must remain presentation-oriented and must not become the source of truth for runtime layout or business behavior
Recommended target namespaces:
scholaraio/core/scholaraio/providers/scholaraio/stores/scholaraio/projects/scholaraio/services/scholaraio/interfaces/scholaraio/compat/
Method:
- introduce new packages first
- use re-export shims from old module locations during migration
Why not earlier:
- at the time of the initial plan, imports were still broadly flat
- moving source files before runtime-path stabilization would have mixed two refactors into one risk envelope
Historical implementation status during the compatibility window (2026-04-23; superseded by the 2026-04-24 breaking cleanup):
- completed for the then-active compatibility window: the target packages were importable, behavior had moved into canonical
core/providers/stores/projects/servicesnamespaces, and legacy public module paths were still compatibility aliases at that time - completed in code for canonical implementation roots: internal imports now target canonical namespaces directly instead of depending on legacy facade modules
Recommended order:
- store-like or provider-like leaves
toolref/*explore.pycitation_styles.pyproceedings.pysources/webtools.pyuspto_odp.pyuspto_ppubs.py
- project boundary module
workspace.py
- service modules
diagram.pytranslate.pyinsights.py- ingest metadata helpers
Additional constraint for webtools:
- preserve current user-facing capability names such as
webextractandingest-link - but move the backend contract toward a provider boundary so the same logical capability can later be backed either by the current HTTP services or by an MCP-style transport without rewriting the CLI/skill surface first
- do not treat the current skill packaging or localhost HTTP defaults as the long-term architectural contract
Late movers:
cli.pyservices/ingest/pipeline.py(ingest/pipeline.pycompatibility alias)
Reason:
- these two remain the largest cross-cutting surfaces in the current architecture
Historical implementation status during the compatibility window (2026-04-23; superseded by the 2026-04-24 breaking cleanup):
The bullets below are retained as historical execution notes. Statements that a legacy module path "remains" an alias do not describe the active breaking-cleanup release generation.
- started with non-disruptive namespace adapters only:
scholaraio.core.config,scholaraio.core.log,scholaraio.stores.citation_styles,scholaraio.stores.toolref,scholaraio.stores.explore,scholaraio.stores.proceedings,scholaraio.providers.arxiv,scholaraio.providers.endnote,scholaraio.providers.zotero,scholaraio.providers.mineru,scholaraio.providers.pdf_fallback,scholaraio.providers.webtools,scholaraio.providers.uspto_odp,scholaraio.providers.uspto_ppubs,scholaraio.projects.workspace,scholaraio.services.audit,scholaraio.services.backup,scholaraio.services.citation_check,scholaraio.services.diagram,scholaraio.services.document,scholaraio.services.export,scholaraio.services.index,scholaraio.services.loader,scholaraio.services.migration_control,scholaraio.services.patent_fetch,scholaraio.services.setup,scholaraio.services.topics,scholaraio.services.translate,scholaraio.services.vectors,scholaraio.services.insights,scholaraio.services.ingest_metadata(includingextractor),scholaraio.services.ingest.parser_matrix_benchmark, andscholaraio.services.ingest.proceedings_volumenow re-export the existing implementations configimplementation has moved toscholaraio.core.config;scholaraio.configremains a module alias so legacy monkeypatch/import paths still target the real implementationlogimplementation has moved toscholaraio.core.log;scholaraio.logremains a module alias so legacy monkeypatch/import paths still target the real implementationauditimplementation has moved toscholaraio.services.audit;scholaraio.auditremains a module alias so legacy monkeypatch/import paths still target the real implementationcitation_stylesimplementation has moved toscholaraio.stores.citation_styles;scholaraio.citation_stylesremains a module alias so legacy monkeypatch/import paths still target the real implementationpapersimplementation has moved toscholaraio.stores.papers;scholaraio.papersremains a module alias so legacy monkeypatch/import paths still target the real implementationproceedingsimplementation has moved toscholaraio.stores.proceedings;scholaraio.proceedingsremains a module alias so legacy monkeypatch/import paths still target the real implementationwebtoolsimplementation has moved toscholaraio.providers.webtools;scholaraio.sources.webtoolsremains a module alias so legacy monkeypatch/import paths still target the real implementationarxivimplementation has moved toscholaraio.providers.arxiv;scholaraio.sources.arxivremains a module alias so legacy monkeypatch/import paths still target the real implementationendnoteimplementation has moved toscholaraio.providers.endnote;scholaraio.sources.endnoteremains a module alias so legacy monkeypatch/import paths still target the real implementationzoteroimplementation has moved toscholaraio.providers.zotero;scholaraio.sources.zoteroremains a module alias so legacy monkeypatch/import paths still target the real implementationmineruimplementation has moved toscholaraio.providers.mineru;scholaraio.ingest.mineruremains a module alias and module-CLI delegator so legacy monkeypatch/import andpython -mpaths still target the real implementationpdf_fallbackimplementation has moved toscholaraio.providers.pdf_fallback;scholaraio.ingest.pdf_fallbackremains a module alias so legacy monkeypatch/import paths still target the real implementationingest.extractorimplementation has moved toscholaraio.services.ingest_metadata.extractor;scholaraio.ingest.extractorremains a module alias so legacy monkeypatch/import paths still target the real implementationparser_matrix_benchmarkimplementation has moved toscholaraio.services.ingest.parser_matrix_benchmark;scholaraio.ingest.parser_matrix_benchmarkremains a module alias so legacy monkeypatch/import paths still target the real implementationingest.proceedingsvolume implementation has moved toscholaraio.services.ingest.proceedings_volume;scholaraio.ingest.proceedingsremains a module alias so legacy monkeypatch/import paths still target the real implementationuspto_odpimplementation has moved toscholaraio.providers.uspto_odp;scholaraio.uspto_odpremains a module alias so legacy monkeypatch/import paths still target the real implementationuspto_ppubsimplementation has moved toscholaraio.providers.uspto_ppubs;scholaraio.uspto_ppubsremains a module alias so legacy monkeypatch/import paths still target the real implementationexploreimplementation has moved toscholaraio.stores.explore;scholaraio.exploreremains a module alias so legacy monkeypatch/import paths still target the real implementationworkspaceimplementation has moved toscholaraio.projects.workspace;scholaraio.workspaceremains a module alias so legacy monkeypatch/import paths still target the real implementationtranslateimplementation has moved toscholaraio.services.translate;scholaraio.translateremains a module alias so legacy monkeypatch/import paths still target the real implementationinsightsimplementation has moved toscholaraio.services.insights;scholaraio.insightsremains a module alias so legacy monkeypatch/import paths still target the real implementationmetricsimplementation has moved toscholaraio.services.metrics;scholaraio.metricsremains a module alias so legacy monkeypatch/import paths still target the real implementationbackupimplementation has moved toscholaraio.services.backup;scholaraio.backupremains a module alias so legacy monkeypatch/import paths still target the real implementationcitation_checkimplementation has moved toscholaraio.services.citation_check;scholaraio.citation_checkremains a module alias so legacy monkeypatch/import paths still target the real implementationdiagramimplementation has moved toscholaraio.services.diagram;scholaraio.diagramremains a module alias so legacy monkeypatch/import paths still target the real implementationdocumentimplementation has moved toscholaraio.services.document;scholaraio.documentremains a module alias so legacy monkeypatch/import paths still target the real implementationexportimplementation has moved toscholaraio.services.export;scholaraio.exportremains a module alias so legacy monkeypatch/import paths still target the real implementationindeximplementation has moved toscholaraio.services.index;scholaraio.indexremains a module alias so legacy monkeypatch/import paths still target the real implementationloaderimplementation has moved toscholaraio.services.loader;scholaraio.loaderremains a module alias so legacy monkeypatch/import paths still target the real implementationtopicsimplementation has moved toscholaraio.services.topics;scholaraio.topicsremains a module alias so legacy monkeypatch/import paths still target the real implementationvectorsimplementation has moved toscholaraio.services.vectors;scholaraio.vectorsremains a module alias so legacy monkeypatch/import paths still target the real implementationmigration_controlimplementation has moved toscholaraio.services.migration_control;scholaraio.migration_controlremains a module alias so legacy monkeypatch/import paths still target the real implementationpatent_fetchimplementation has moved toscholaraio.services.patent_fetch;scholaraio.patent_fetchremains a module alias so legacy monkeypatch/import paths still target the real implementationsetupimplementation has moved toscholaraio.services.setup;scholaraio.setupremains a module alias so legacy monkeypatch/import paths still target the real implementationtoolrefimplementation has moved toscholaraio.stores.toolref;scholaraio.toolrefremains a package alias, including legacy submodule aliases such asscholaraio.toolref.storageingest.metadataimplementation has moved toscholaraio.services.ingest_metadata;scholaraio.ingest.metadataremains a package alias, including legacy submodule aliases such asscholaraio.ingest.metadata._api- late movers (
cli.pyandingest/pipeline.py) are now covered by Phase B3 facade splits; the ingest pipeline compatibility facade now lives atscholaraio.services.ingest.pipeline, whilescholaraio.ingest.pipelineremains a module alias
Recommended target:
interfaces/cli/for command registration and per-domain handlersservices/ingest/for pipeline orchestration and ingest subflows
Precondition:
- Track A runtime path abstraction must already be complete enough that these files are not also carrying directory migration risk
Implementation status (2026-04-20):
insightscommand handling has moved toscholaraio.interfaces.cli.insights;scholaraio.cli.cmd_insightsremains the parser-facing callablemetricscommand handling has moved toscholaraio.interfaces.cli.metrics;scholaraio.cli.cmd_metricsremains the parser-facing callabletranslatecommand handling has moved toscholaraio.interfaces.cli.translate;scholaraio.cli.cmd_translateremains the parser-facing callablebackupcommand handling has moved toscholaraio.interfaces.cli.backup;scholaraio.cli.cmd_backupremains the parser-facing callablestylecommand handling has moved toscholaraio.interfaces.cli.style;scholaraio.cli.cmd_styleremains the parser-facing callabledocumentcommand handling has moved toscholaraio.interfaces.cli.document;scholaraio.cli.cmd_documentremains the parser-facing callableexportcommand handling has moved toscholaraio.interfaces.cli.export;scholaraio.cli.cmd_exportand existing_cmd_export_*helper aliases remain availablediagramcommand handling has moved toscholaraio.interfaces.cli.diagram;scholaraio.cli.cmd_diagramand existing diagram helper aliases remain availablesetupcommand handling has moved toscholaraio.interfaces.cli.setup;scholaraio.cli.cmd_setupremains the parser-facing callableindexcommand handling has moved toscholaraio.interfaces.cli.index;scholaraio.cli.cmd_indexremains the parser-facing callablesearchandsearch-authorcommand handling has moved toscholaraio.interfaces.cli.search;scholaraio.cli.cmd_searchandscholaraio.cli.cmd_search_authorremain parser-facing callablestop-citedcommand handling has moved toscholaraio.interfaces.cli.citations;scholaraio.cli.cmd_top_citedremains the parser-facing callablerenamecommand handling has moved toscholaraio.interfaces.cli.rename;scholaraio.cli.cmd_renameremains the parser-facing callableauditcommand handling has moved toscholaraio.interfaces.cli.audit;scholaraio.cli.cmd_auditremains the parser-facing callable- citation-graph command handling (
refs,citing,shared-refs) has moved toscholaraio.interfaces.cli.graph; the correspondingscholaraio.cli.cmd_*callables remain parser-facing aliases toolrefcommand handling has moved toscholaraio.interfaces.cli.toolref;scholaraio.cli.cmd_toolrefremains the parser-facing callableshowcommand handling has moved toscholaraio.interfaces.cli.show;scholaraio.cli.cmd_showremains the parser-facing callablecitation-checkcommand handling has moved toscholaraio.interfaces.cli.citation_check;scholaraio.cli.cmd_citation_checkremains the parser-facing callablemigratecommand handling has moved toscholaraio.interfaces.cli.migrate;scholaraio.cli.cmd_migrateremains the parser-facing callableproceedingscommand handling has moved toscholaraio.interfaces.cli.proceedings;scholaraio.cli.cmd_proceedingsremains the parser-facing callableimport-endnotecommand handling has moved toscholaraio.interfaces.cli.import_endnote;scholaraio.cli.cmd_import_endnoteremains the parser-facing callableimport-zoterocommand handling has moved toscholaraio.interfaces.cli.import_zotero;scholaraio.cli.cmd_import_zoteroand the existing_import_zotero_collections_as_workspaceshelper alias remain availablefsearchcommand handling has moved toscholaraio.interfaces.cli.fsearch;scholaraio.cli.cmd_fsearchand existing arXiv lookup helper aliases remain availablewscommand handling has moved toscholaraio.interfaces.cli.workspace;scholaraio.cli.cmd_wsremains the parser-facing callable- retrieval command handling (
embed,vsearch,usearch) has moved toscholaraio.interfaces.cli.retrieval; the correspondingscholaraio.cli.cmd_*callables remain parser-facing aliases repaircommand handling has moved toscholaraio.interfaces.cli.repair;scholaraio.cli.cmd_repairremains the parser-facing callablepipelinecommand handling has moved toscholaraio.interfaces.cli.pipeline;scholaraio.cli.cmd_pipelineremains the parser-facing callablebackfill-abstractcommand handling has moved toscholaraio.interfaces.cli.backfill_abstract;scholaraio.cli.cmd_backfill_abstractremains the parser-facing callabletopicscommand handling has moved toscholaraio.interfaces.cli.topics;scholaraio.cli.cmd_topicsand the existing_write_all_vizhelper alias remain availablerefetchcommand handling has moved toscholaraio.interfaces.cli.refetch;scholaraio.cli.cmd_refetchremains the parser-facing callable- enrichment command handling (
enrich-toc,enrich-l3) has moved toscholaraio.interfaces.cli.enrich;scholaraio.cli.cmd_enrich_*and existing enrichment helper aliases remain available - arXiv command handling (
arxiv search,arxiv fetch) has moved toscholaraio.interfaces.cli.arxiv; the correspondingscholaraio.cli.cmd_arxiv_*callables remain parser-facing aliases - rendered web command handling (
webextract) has moved toscholaraio.interfaces.cli.web; the_terminal_previewhelper alias remains available explorecommand handling has moved toscholaraio.interfaces.cli.explore;scholaraio.cli.cmd_exploreand the existing_explore_roothelper alias remain availableingest-linkcommand handling has moved toscholaraio.interfaces.cli.ingest_link;scholaraio.cli.cmd_ingest_linkand existing ingest-link helper aliases remain available- patent command handling (
patent-fetch,patent-search) has moved toscholaraio.interfaces.cli.patent; the correspondingscholaraio.cli.cmd_patent_*callables remain parser-facing aliases attach-pdfcommand handling has moved toscholaraio.interfaces.cli.attach_pdf;scholaraio.cli.cmd_attach_pdfand the existing_batch_convert_pdfshelper alias remain available- shared CLI argument helpers have moved to
scholaraio.interfaces.cli.arguments; legacyscholaraio.cli._add_result_limit_arg,_resolve_result_limit,_resolve_top, and_add_filter_argsremain aliases - shared CLI output/search formatting helpers have moved to
scholaraio.interfaces.cli.output; legacyscholaraio.cli._print_search_result,_print_search_next_steps,_format_match_tag, and_format_citationsremain aliases - shared CLI optional-dependency diagnostics have moved to
scholaraio.interfaces.cli.dependencies; legacyscholaraio.cli._INSTALL_HINTSand_check_import_errorremain aliases and keep the old logging monkeypatch point - shared CLI workspace/inbox path helpers have moved to
scholaraio.interfaces.cli.paths; legacyscholaraio.cli._resolve_ws_paper_ids,_workspace_root, and_default_inbox_dirremain aliases and keep old UI/helper monkeypatch points - shared CLI paper resolution/display helpers have moved to
scholaraio.interfaces.cli.paper; legacyscholaraio.cli._lookup_registry_by_candidates,_resolve_paper,_print_header, and_enrich_show_headerremain aliases and keep old UI/logging/helper monkeypatch points - shared CLI search metrics recording has moved to
scholaraio.interfaces.cli.search_metrics; legacyscholaraio.cli._record_search_metricsremains an alias and keeps the old logging monkeypatch point - CLI runtime startup/gating has moved to
scholaraio.interfaces.cli.runtime; legacyscholaraio.cli.mainremains the script entrypoint alias and keeps old config/UI/parser monkeypatch points - CLI parser construction has moved to
scholaraio.interfaces.cli.parser; legacyscholaraio.cli._build_parserremains an alias and dynamically binds parser defaults from currentscholaraio.clicommand/helper aliases - ingest pipeline orchestration facade has moved to
scholaraio.services.ingest.pipeline; current CLI-interface consumers import that target namespace, whilescholaraio.ingest.pipelineremains the same module object for legacy imports and monkeypatch paths - ingest queue/proceedings path helpers have moved to
scholaraio.services.ingest.paths; legacy private helpers such asscholaraio.ingest.pipeline._inbox_dirremain aliases during the compatibility window - ingest pipeline type definitions (
StepResult,StepDef,InboxCtx) have moved toscholaraio.services.ingest.types;scholaraio.ingest.pipelinekeeps the same public names as compatibility aliases - ingest MinerU asset discovery and move/cleanup helpers have moved to
scholaraio.services.ingest.assets; legacy private helper names inscholaraio.ingest.pipelineremain aliases - ingest duplicate-detection identifier helpers have moved to
scholaraio.services.ingest.identifiers; legacyscholaraio.ingest.pipeline._collect_existing_*and_normalize_arxiv_idremain aliases - ingest document-detection JSON parsing and patent/thesis/book classifier helpers have moved to
scholaraio.services.ingest.detection; legacy pipeline private helper names remain aliases - ingest document sidecar metadata loading and post-ingest abstract repair have moved to
scholaraio.services.ingest.documents; legacy pipeline private helper names remain aliases - ingest search-registry update helpers have moved to
scholaraio.services.ingest.registry; legacy_ensure_registry_schema,_update_registry, and_registry_migratedremain aliases - ingest inbox cleanup has moved to
scholaraio.services.ingest.cleanup; legacyscholaraio.ingest.pipeline._cleanup_inboxremains an alias - ingest pending-spool file movement has moved to
scholaraio.services.ingest.pending; legacyscholaraio.ingest.pipeline._move_to_pendingremains an alias - ingest proceedings routing has moved to
scholaraio.services.ingest.proceedings; proceedings volume preparation has moved toscholaraio.services.ingest.proceedings_volume; legacyscholaraio.ingest.pipeline._ingest_proceedings_ctxandscholaraio.ingest.proceedingsremain aliases - ingest paper/global pipeline steps (
toc,l3,translate,refetch,embed,index) have moved toscholaraio.services.ingest.steps; legacy publicscholaraio.ingest.pipeline.step_*names remain aliases - ingest batch-conversion asset helpers have moved to
scholaraio.services.ingest.batch_assets; legacy_move_batch_imagesand_flatten_cloud_batch_outputremain aliases - ingest single-file batch conversion postprocessing has moved to
scholaraio.services.ingest.batch_postprocess; legacy_postprocess_convertremains an alias - ingest batch conversion postprocessing has moved to
scholaraio.services.ingest.batch_postprocess; legacy_batch_postprocessremains an alias and still honors pipeline-level step/UI monkeypatches - ingest batch PDF conversion orchestration has moved to
scholaraio.services.ingest.batch_convert; legacybatch_convert_pdfsremains an alias and still honors pipeline-level helper/UI monkeypatches - ingest external reference-manager import orchestration has moved to
scholaraio.services.ingest.external_import; legacyimport_externalremains an alias and still honors pipeline-level helper/step/UI monkeypatches - ingest pipeline step registry and presets have moved to
scholaraio.services.ingest.step_registry; legacySTEPS,PRESETS,_DOC_INBOX_STEPS, and_OFFICE_EXTENSIONSremain aliases - ingest per-inbox orchestration has moved to
scholaraio.services.ingest.inbox_orchestration; legacy_process_inboxremains an alias and still honors pipeline-level step/helper/UI/logging monkeypatches - ingest top-level pipeline runner has moved to
scholaraio.services.ingest.pipeline_runner; legacyrun_pipelineremains an alias and still honors pipeline-level step/helper/UI/logging monkeypatches - ingest Office inbox conversion step has moved to
scholaraio.services.ingest.inbox_steps; legacystep_office_convertremains an alias and still honors pipeline-level logging monkeypatches - ingest MinerU/PDF conversion step has moved to
scholaraio.services.ingest.inbox_steps; legacystep_mineruremains an alias and still honors pipeline-level UI/logging monkeypatches - ingest metadata extraction inbox steps have moved to
scholaraio.services.ingest.inbox_steps; legacystep_extract_docandstep_extractremain aliases and still honor pipeline-level helper/UI/logging monkeypatches - ingest dedup/API-completion step has moved to
scholaraio.services.ingest.inbox_steps; legacystep_dedupremains an alias and still honors pipeline-level helper/UI/logging monkeypatches - ingest write-to-library step has moved to
scholaraio.services.ingest.inbox_steps; legacystep_ingestremains an alias and still honors pipeline-level helper/UI/logging monkeypatches
The following implementation details should remain deferred until the earlier phases above are complete:
- the concrete
workspace.yamlfield schema beyond the minimal additive metadata/mount envelope above - any actual implementation of manifest-declared workspace-local
exploremounts after the shared-store compatibility window
The safe execution order is:
- freeze root integration and config invariants
- make
Configthe complete path authority - convert leaf modules and shallow CLI consumers to accessors
- introduce a workspace compatibility layer
- abstract queue/proceedings paths in
pipeline.py - separate state/cache/runtime logically
- move isolated libraries first
- move
proceedingsas a durable library - move queue/spool paths
- move
paperslast - clean up compatibility layers
Anything that starts by directly renaming data/, workspace/, or .claude/skills/ is not aligned with the audited current codebase.