- Removed headless_setup call from CLI dispatch entirely. --headless,
--modular, and bare all construct the same SetupPlan with identical
_cfg/zotero_path/agent_type/skip_checks. Only the deprecation notice
differs per entry point.
- Added skip_checks parameter to SetupPlan (forwarded to CLI arg).
- ConfigWriter always writes schema_version '2' unconditionally (never
preserves a v1 value from existing config).
RED commands:
python -m pytest tests/test_setup_plan_v2.py::TestConfigWriterSchemaVersion -v
python -m pytest tests/test_setup_plan_v2.py::TestCliHeadlessViaSetupPlan -v
GREEN commands (same, after fixes): 61/61 passed.
- --headless now delegates to SetupPlan for canonical config, then runs
headless_setup for full deployment; canonical ConfigWriter pass ensures
v2 vault_config format.
- --zotero-data is forwarded through SetupPlan.zotero_path for both
--modular and bare paths.
- Deprecation warnings use print(stderr) instead of filtered
DeprecationWarning so users always see them.
- ConfigWriter.PATH_KEYS extended to converge all seven legacy path keys
(system_dir, resources_dir, literature_dir, control_dir, base_dir,
skill_dir, command_dir) into vault_config, preserving non-path metadata.
- Added CLI-level tests: deprecation on stderr, config canonicalization,
--literature-dir forwarding, --zotero-data plumbing.
ConfigWriter now writes v2 canonical format (nested vault_config with
schema_version). On rerun it merges with existing config rather than
overwriting, making repeated runs idempotent.
load_vault_config reverses the v1 precedence: vault_config block now
wins over legacy top-level path keys, which are treated as a read-only
fallback with a UserWarning. This is the N+1 transition — old v1
configs remain readable with a warning; all writes produce v2 only.
Bare and --headless setup now delegate to the canonical SetupPlan engine
(the --modular path) with a DeprecationWarning.
Closes#75.
Record the completed six-module control-center and maintenance-inbox
prototype wave. Both prototype pairs passed independent Critical/Important
PASS review and direct browser verification at 768px without production
code changes. Update executive summary, active queue, decision log,
session timeline, and milestone checkpoint.
- #71 resolved: six-module control-center HTML prototype
(5 scenarios x 6 modules, plain-button switcher, responsive 768px)
- #72 resolved: actionable-only maintenance inbox prototype
(single-action rows, inline issue-draft, confirmation-first report)
- #73 promoted to active frontier: integrate accepted model into
production control-center plugin
- Update PROJECT-MANAGEMENT.md for #69/#70 resolved, #71/#72 as live frontier
- Add orthogonal capability/activity/attention model and managed-runtime immutable-slot
architecture decisions to decision log and timeline
- Record OCR maintenance regression: canonical per-row action routing (display_action->verb),
redo confirmation gate, cache manifest preservation (19/19 tests pass)
- Add research reports: docs/research/2026-07-14-capability-state-action-contract.md,
docs/research/2026-07-14-managed-runtime-architecture.md
- Update project/current/ocr-v2-active-queue.md with resolved items and new frontier
The previous ordering wrote encoded payloads first, then deleted ALL
vectors for that paper (including the just-written ones). Swap the
ordering so old vectors are deleted first and new ones survive.
Replace shutil.rmtree on the ChromaDB path with DROP TABLE IF EXISTS
on vec0 virtual tables and their companion meta tables. Force rebuild
now opens paperforge.db and drops vec_fulltext, vec_body, vec_objects,
vec_fulltext_meta, vec_body_meta, and vec_objects_meta.
Also replaced the remaining get_vector_db_path reference in the error
handler with get_memory_db_path. Removed get_vector_db_path import
from embed.py since it is no longer used in active control flow.
Replace get_vector_db_path() directory existence check with vec0
meta table row counts via SQLite. Resume now checks whether any
rows exist in vec_fulltext_meta, vec_body_meta, or vec_objects_meta.
If none exist, starts a fresh build. This removes the last ChromaDB
path dependency from the resume control flow.
Embed status no longer checks for chromadb import — vec0 runs in
paperforge.db and doesn't need the ChromaDB library. The preflight
check also no longer requires chromadb since vec0 backends do not
depend on it. The chroma_backend module remains for legacy test
compatibility but no longer gates any production build/status path.
Adds _renderSearchState() rendering 8 distinguishable states:
idle, searching (M/@), results, empty, vectors-not-built,
backend-unavailable, timeout, model-changed.
Keyboard: / focuses search, Escape cancels, ArrowUp/Down navigates
results, Enter opens note, Ctrl+Enter forces deep mode.
Accessibility: role=alert on errors, aria-live=polite on results
and progress, role=listbox with aria-selected/aria-posinset on cards,
aria-setsize, tabindex=0 on result cards, focus management on
state transitions.
Focus management: Stop button on build start, first result on
search complete, error banner on failure.
Maps 7 retrieval error codes (VECTOR_NOT_BUILT, VECTOR_CORRUPTED,
MODEL_CHANGED, BACKEND_UNAVAILABLE, TIMEOUT, INTERNAL_ERROR, NO_PYTHON)
to distinct UI states with type, message, recoverable flag, and action.
Adds 7 new test cases for the error classification routing.
Adds all retrieval state labels, button text, warning messages, and
descriptive copy in English and Chinese under the retrieval_* prefix.
Prepares i18n foundation for search domain (8 states) and build domain
(10 states) per PRD #57 and issue #62.
getVectorRuntime now calls embed status --json synchronously with
a 2s time-based cache before falling back to the JSON snapshot.
During build, a 2s polling interval reads embed status --json for
live build state and detects remote stop.
Stop button calls embed stop --json only (no direct .kill() on the
child process), letting the CLI handle cooperative stop.
ISettingPlugin interface extended with _embedPollInterval and
_embedPolling properties.
embed stop now sets status=stopping, waits for the build PID to exit
(8s timeout), force-kills as last resort, then settles to idle.
Build loop checks the cancellation flag (read_vector_build_state)
between papers in the main loop and drains in-flight work before
cleanly exiting without marking 'completed'.
Fixes pre-existing UnboundLocalError from a local import shadowing
the global mark_vector_build_state symbol in the run() function.
embed status now runs a zero-vector k-NN query on each vec0 table
that has companion meta rows. If the probe fails (table dropped,
extension unavailable, index corrupted), healthy=false and
corrupted=true are reported even when meta row counts > 0.
Includes integration test that drops vec_fulltext and verifies
healthy=false.
The vec_fulltext_meta table DDL was referenced by ensure_schema()
but never defined. ADD the missing CREATE_VEC_FULLTEXT_META variable
so the meta table is created alongside vec_body_meta and vec_objects_meta.
schema.py: CREATE_VEC_FULLTEXT_META was referenced at line 328 but
never defined. Adds the missing DDL constant so the v5 schema migration
does not raise NameError on fresh databases.
tests: add embedding test suite with four tests covering vec0 resume
detection, empty-table fallback, force drop, and delete-then-write
ordering verification.
Replace shutil.rmtree on the ChromaDB path with DROP TABLE IF EXISTS
on vec0 virtual tables and their companion meta tables. Force rebuild
now opens paperforge.db and drops vec_fulltext, vec_body, vec_objects,
vec_fulltext_meta, vec_body_meta, and vec_objects_meta.
Also replaced the remaining get_vector_db_path reference in the error
handler with get_memory_db_path. Removed get_vector_db_path import
from embed.py since it is no longer used in active control flow.
Replace get_vector_db_path() directory existence check with vec0
meta table row counts via SQLite. Resume now checks whether any
rows exist in vec_fulltext_meta, vec_body_meta, or vec_objects_meta.
If none exist, starts a fresh build. This removes the last ChromaDB
path dependency from the resume control flow.
Embed status no longer checks for chromadb import — vec0 runs in
paperforge.db and doesn't need the ChromaDB library. The preflight
check also no longer requires chromadb since vec0 backends do not
depend on it. The chroma_backend module remains for legacy test
compatibility but no longer gates any production build/status path.
The previous ordering wrote encoded payloads first, then deleted ALL
vectors for that paper (including the just-written ones). Swap the
ordering so old vectors are deleted first and new ones survive.
- search.py: normalize FTS results to unified field set (score from rank,
add text/heading/source keys). Result key unchanged (already 'matches').
- retrieve.py: rename data.chunks to data.matches in standard and deep paths.
Map field names: paper_id->zotero_key, chunk_text->text, section_path->heading.
Expand enrichment SQL to fetch journal and domain.
--deep flag already wired in CLI parser.
- tests/cli/test_json_contracts.py: add contract tests verifying PFResult
envelope shape, data.matches key presence, unified field names,
--deep flag acceptance, and field type correctness.
- search.py: normalize FTS results to unified field set (score from rank,
add text/heading/source keys). Result key unchanged (already 'matches').
- retrieve.py: rename data.chunks to data.matches in standard and deep paths.
Map field names: paper_id->zotero_key, chunk_text->text, section_path->heading.
Expand enrichment SQL to fetch journal and domain.
--deep flag already wired in CLI parser.
- tests/cli/test_json_contracts.py: add contract tests verifying PFResult
envelope shape, data.matches key presence, unified field names,
--deep flag acceptance, and field type correctness.
- Remove paperforge/plugin/src/services/db.ts (sql.js wrapper, initDatabase/searchMetadata/SearchResultItem)
- Remove paperforge/plugin/sql-wasm.wasm (644KB binary)
- Remove sql.js and @types/sql.js from package.json; npm install to update lockfile
- dashboard.ts: remove import of db.ts, remove _sqlJsInitialized/_sqlJsFailed state,
remove the sql.js search path block entirely — all searches go straight to CLI spawn.
Clean up stale comments.
- Bundle drops from 346KB to 167KB; 6 test files / 58 tests still pass