Commit graph

200 commits

Author SHA1 Message Date
LLLin000
9a15f36485 docs: define control center UX redesign 2026-07-20 01:49:33 +08:00
LLLin000
e56a5faf44 docs: record control-center PRD and setup migration 2026-07-15 02:30:05 +08:00
LLLin000
b97e82ab7c docs: close #71/#72 prototypes, set #73 as active frontier
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
2026-07-15 00:41:28 +08:00
LLLin000
d7b0a52780 closeout: record #69/#70 resolution, capability model, runtime architecture, maintenance regression fixes
- 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
2026-07-15 00:03:16 +08:00
LLLin000
29a0e27077 docs: research control center recovery patterns 2026-07-14 23:08:26 +08:00
LLLin000
68f342ddf9 docs: audit control center contracts 2026-07-14 19:58:30 +08:00
LLLin000
b4ac277438 Merge branch 'feat/retrieval-recovery'
# Conflicts:
#	paperforge/commands/embed.py
2026-07-11 01:26:37 +08:00
LLLin000
f52124bcf7 docs: retrieval recovery design — Approach A (Python CLI sole owner) recommended 2026-07-10 23:01:57 +08:00
LLLin000
e3c41cc07d chore: add sql.js WASM, DB service, and PRD document 2026-07-10 02:49:49 +08:00
LLLin000
4ff165ae49 feat(#38, #40): version history panel + @ Deep Search
#38: File Recovery-style version history panel with i18n (en/zh).
- _renderVersionMode() with paper list + timeline + restore/compare
- version-history.ts service for scan/restore/compare
- Paper mode [版本历史] button
- i18n strings for all panel text

#40: @ Deep Search with query rewrite + hybrid retrieval.
- query_rewrite.py: abbreviation expansion (28 terms) + synonyms (12)
- hybrid_search(): BM25 FTS5 + vec0 k-NN + score fusion (0.3/0.7)
- retrieve --deep flag routes to hybrid_search
- Graceful vec0 fallback (FTS5-only)
- 17 new tests

Co-authored-by: VersionPanel <agent>
Co-authored-by: DeepSearch <agent>
2026-07-10 01:01:48 +08:00
LLLin000
27e45f9419 feat(#37): auto-backup fulltext before rebuild
backup_render_before_rebuild() copies render/fulltext.md (and
render-map.json, heading-events.json) to versions/v{N}/ before
rebuild overwrites them. Creates/updates versions/manifest.json
with version metadata. Idempotent: skips when no render exists.

Hook placed between phase 3 and phase 4 in _rebuild_one_paper.

6 new tests.
2026-07-10 00:34:44 +08:00
LLLin000
06fec04651 feat: Phase 0, 1, 3a — legacy OCR fix, ChromaDB migration, search bar UI
Phase 0 (#35): _needs_derived_rebuild returns (False, 'legacy_ocr') for
papers without structured blocks and derived_version. _can_rebuild adds
has_structured check. No misleading rebuild suggestions for legacy users.

Phase 1 (#36): migrate_chroma_to_vec0() copies existing ChromaDB vectors
to vec0 tables with zero API calls. Idempotent (skips by paper_id).
delete_paper_vectors() cleans both ChromaDB and vec0. CLI: embed migrate.
5 new tests.

Phase 3a (#39): Search bar in collection panel — two-mode input
(M metadata / @ deep) with card results display. JSON output parsed
from search/retrieve CLI. 289 lines TypeScript, 175 lines CSS.
Build passes clean.

Co-authored-by: Phase0LegacyOcr <agent>
Co-authored-by: ChromaMigration <agent>
Co-authored-by: SearchBarUI <agent>
2026-07-10 00:02:02 +08:00
LLLin000
cc064bd74a fix: address 5 PR9 embedding pipeline issues from triage
- #13: Critical — swap delete/write order in _complete_one (write new
  vectors before deleting old ones) to prevent data loss on write failure
- #12: Add logger.warning() to 3 resume-skip except blocks so silent
  re-embed fallbacks are observable
- #14: Add lightweight HNSW query probe to _assert_collections_healthy
- #11: Log collection query failures in merge_retrieve instead of silent
  continue
- #16: Reuse provider across payloads in encode_paper_job — one creation
  per worker per paper instead of per payload
2026-07-09 01:46:22 +08:00
LLLin000
45022c3e16 docs: archive superpowers specs/plans, commit PR9A-C plan files
- Archive 173 design/plan/analysis docs from docs/superpowers/ →
  docs/archive/superpowers/ (all features shipped)
- Commit 5 PR9A-C plan files to docs/plans/ (historical record)
- Rebuild plugin bundle (main.js: 2172→49 lines, minified)
- Fix settings.ts type assertion
2026-07-09 00:39:39 +08:00
LLLin000
0dfbf2a68d feat: PR 8 — Object Vector Retrieval (paperforge_objects collection)
New paperforge_objects collection in ChromaDB for figure/table caption
vector search, completing the memory layer retrieval triad:

  paperforge_fulltext → legacy_chunk
  paperforge_body     → body_unit
  paperforge_objects  → object_unit (NEW)

Changes:
- manifest.py: compute_object_units_hash(), manifest records both hashes
- _chroma.py: _COLLECTION_NAMES includes paperforge_objects
- builder.py: get_object_units_for_embedding() + embed_object_units()
- status.py: object_chunk_count, total_chunks
- state_snapshot.py: write_vector_runtime() extended with new fields
- search.py: 3rd collection, dict-based source mapping, object_kind/label
- __init__.py: exports for new functions
- commands/embed.py: _has_object_units_in_db, body+object structured
  path routing with dual-hash resume, extended counters
- Test fix: test_build_paper_manifest data complete for hash functions

Verification: 20 object vectors embedded, all per-paper counts match,
status total consistent (58266 = 57435 + 811 + 20),
object caption queries return object_unit results via merge_retrieve.
Unit tests: 153 pass, 1 skip.
2026-07-06 19:58:46 +08:00
LLLin000
e551f79a77 fix: PR 7 post-test hardening — object units, node_id, expanded tests
P0 fixes from test report review:
- object unit_id: fallback to f"{obj_type}:p{page}:{block_id}" when
  figure_id/table_id missing (prevents DB overwrite on INSERT OR REPLACE)
- object caption_key: page-qualified f"p{page}:{caption_bid}" to match
  page-qualified subtree_block_ids in find_owning_node
- object block_map: page-qualified keys for consistency with body_units
- structure node_id: changed from sec:{block_id} to sec:p{page}:{block_id}
  for stability (reduces vector ID churn from emitted_order changes)

New tests:
- Section 4b: Object units DB persistence (unit_id unique, non-empty labels,
  DB count == list count after upsert)
- Section 5b: Coverage gate (v2_tree / render_map / body_papers counts)

Layer A: 1669/1669 pass (+60 checks from 4b + 5b)
Unit tests: 153 pass, 1 skip
2026-07-06 19:34:05 +08:00
LLLin000
01461330bb fix: final hardening — policy revision + Layer A all green
- _body_unit_role_kind now excludes only reference_item/reference_heading
  (per policy: everything in fulltext except ref zone)
- backmatter_body unit_kind removed; all units are 'body'
- bounds_map in structure_tree uses page-qualified key (fixes collision
  when same block_id appears on different pages)
- Layer A test plan: emitted_ids uses page-qualified keys + handles
  block_id=0 (falsy value)
- Layer A: 1609 passed, 0 failed on real vault (22 papers)
- Unit tests: 152 passed, 1 pre-existing skip
2026-07-06 19:08:54 +08:00
LLLin000
77a6e0cfec fix: heading→emitted events, backmatter→heading events, page-qualified keys
- Section/subsection headings now appear in BOTH heading_events and
  emitted_block_events (emitted_as='heading') for complete event stream
- Backmatter headings (Funding/Acknowledgments/Data Availability/Conflicts)
  now generate heading_events → appear as structure tree sections with
  their own body_units
- Page-qualified block IDs (p{page}:{block_id}) in tree own/subtree_block_ids
  and body_units block_map: eliminates ambiguous block_id collisions when
  same block_id appears on multiple pages in real OCR data
- TC-9.2 wording fix, KEYS empty guard, global unit_id uniqueness check
2026-07-06 18:19:17 +08:00
LLLin000
897afdaecb fix: token cap recursive split + policy version check + test plan update
- _split_if_oversized: recursive _halve_text until every part <= 1000 tokens
- _incremental_units_only: also checks retrieval_policy_version match
- _rebuild_paper_units: use RETRIEVAL_POLICY_VERSION constant
- Functional test plan: Layer A (artifact) + Layer B (API), all 8 review
  fixes incorporated (persisted artifacts, no jump-assertion, stronger
  object/backmatter/abstract tests, proper embed flow)
2026-07-06 17:05:13 +08:00
LLLin000
1ef0899fec docs: comprehensive functional test plan for memory layer
10 sections covering Render Events, Structure Tree, Body Units,
Object Units, FTS, Content Discovery, Memory Builder, Embed Build,
Retrieve Merge, and Regression. Includes auto-test script skeleton.
2026-07-06 16:59:31 +08:00
LLLin000
288829bb5b feat: PR 1 — nested structure tree + body_units correctness
- RenderOutput dataclass with heading_events/emitted_block_events tracking
- Stack-algorithm structure tree with own/subtree block IDs
- Recursive body_units builder with role helper + token cap splitting
- Schema v4: section_path_json, section_level, section_title, part_ordinal
- Phase 4/5 reorder in ocr_rebuild.py and ocr.py
- 12 new test cases for tree nesting, own_block_ids, rendered-order intervals
2026-07-06 16:42:08 +08:00
LLLin000
7b29ab68ca feat: improve vnext figure matching and split OCR status
This batch implements the validated PR-2 / PR-3 workstreams.

PR-2b: continued captions in vnext
- add figure continuation helpers
- mark continuation legends in candidate indexing
- run ContinuationCaptionPass before PrimarySamePagePass
- emit unique continuation records with trace metadata
- skip continuation legends in ordinary same-page proposals

PR-2a: short-caption geometry
- reuse _TRUNCATED_LEGEND_ONLY_PATTERN
- add narrow short-caption branch at the vnext group/page seam
- require same page, same column/x-overlap, tight gap, and local uniqueness
- avoid global threshold changes or score_figure_match edits

PR-3: completeness normalization and additive status split
- normalize legacy/vnext figure completeness shapes
- keep overall unchanged
- add structure_status, figure_status, table_status,
  dimension_statuses, status_reasons

Verification:
- 443 targeted tests passing
- real-vault rebuilds:
  * SKXTCE6M: unmatched_legends 6->0, overall green
  * SRNJDAA2: unmatched_legends 9->0, figure green
  * 6QNRHRKX: matched 0->4, figure yellow (improved, not solved)
  * 9DM6MCIF: unmatched_legends 3->0, figure green
  * XGT9Z257: unmatched_legends 4->0, figure green
  * V4UTP5X7: figure green while structure remains red
2026-07-06 00:55:40 +08:00
LLLin000
7c702b1bcf fix: exclude table-owned media and inline figure body refs from figure matching
PR-1 of the architecture review fixes.

Two entry-level filters before figure matching:

1. _is_table_owned_media(): excludes media_asset blocks with table
   roles/raw_labels/hints from the figure asset pool. Previously these
   entered as figure candidates and ended up as unmatched legends/orphans.

2. _looks_like_inline_figure_body_reference(): detects body text like
   'Figure 11-10 shows...' (hyphenated ranges, list ranges) and flags
   it as an inline reference, not a figure legend. Applied in both
   ocr_figures.py and ocr_roles.py for consistent early rejection.

Verified on real vault:
  SKXTCE6M: unmatched_legends 6→0, overall yellow→green
  SRNJDAA2: unmatched_legends 9→0

Tests: 384 pass (+9 new), 0 fail
2026-07-05 22:36:17 +08:00
LLLin000
cd352cb007 fix: rebuild path writes meta.ocr_health_overall
_phase4_render_health now returns (markdown, health_overall),
_phase5_finalize writes it to meta before write_json.

Also adds ADR with architecture review decisions:
- #2 Meta divergence — fixed
- #3 Quality signals for consumers — deferred to role-override v1
- #4 Health report richness — keep all fields
- #5 PDF lines cache — rejected
- #6 Integration tests — deferred to role-override v1
2026-07-05 22:02:40 +08:00
LLLin000
c34ebbce81 feat: rebuild speed-up with parallel rebuild, threaded asset cropping, maintenance refactor, embed progress, CLI docs 2026-07-05 19:43:07 +08:00
LLLin000
380f935f83 docs: add fulltext rebuild safety implementation plan 2026-07-05 17:14:13 +08:00
LLLin000
a21fdf304b docs: tighten rebuild safety spec 2026-07-05 16:10:07 +08:00
LLLin000
35e66197b4 docs: add fulltext rebuild safety design 2026-07-05 16:00:54 +08:00
LLLin000
88838c1842 docs: keep paper lookup at identity boundary 2026-07-05 15:06:23 +08:00
LLLin000
b02e762ce4 docs: plan Layer 4 retrieval substrate 2026-07-05 02:27:47 +08:00
LLLin000
9bc12bd6a0 docs: tighten Layer 4 retrieval spec 2026-07-05 02:22:17 +08:00
LLLin000
f8d928d6ed docs: design Layer 4 retrieval substrate 2026-07-05 02:05:27 +08:00
LLLin000
44bbad9250 docs: plan v2 — fix all P0/P1 (deps, error status, redo keys, health-bound, i18n) 2026-07-05 00:36:21 +08:00
LLLin000
069c344af7 docs: implementation plan for maintenance tab — 3 PRs (row model, CLI, plugin UI) 2026-07-05 00:28:58 +08:00
LLLin000
b4edea8ee6 docs: spec cleanup — remove duplicate old UI, add row model display fields + mapping contract 2026-07-05 00:27:44 +08:00
LLLin000
ac55a519db docs: maintenance tab design spec v2 — action-first labels, legacy handling, cache strategy 2026-07-05 00:24:08 +08:00
LLLin000
96fd9771ef fix(ocr-quality): contract polish — 4 P0/P1 fixes
1. compute_use_cases output uses status/gates/reasons (not recommended/gate_results)
2. write_feedback validates every mark has result_hash and fulltext_hash
3. load_readiness_policy(policy=...) bypasses user override (reproducible)
4. confidence_and_fallbacks yellow for degraded=True or weak span coverage

Minor: append_mark doesn't mutate caller dict; has_figure_evidence includes
unmatched_legend_count and held_count.
2026-07-04 23:38:03 +08:00
LLLin000
b07ac7a177 docs: add Layer 2 spec and implementation plan 2026-07-04 23:32:55 +08:00
LLLin000
3222ac42fa docs: apply 5 corrections to implementation plan
Corrections from review:
1. Move CONSUMED_FRONTMATTER_ROLES to module-level constant
2. Frontmatter fallback reads text/block_content, dedupes, no render_default gate
3. PR 2 body escape defaults to body_paragraph; only display_zone+legend_like bypasses
4. PR 3 page_width helper with 1200 as final fallback only
5. PR 4 enrich column_band after _candidate_group_entry() (Scheme B, no signature change)
Also: fixed PR 2 2HJSWV3V acceptance wording, PR 3 'FALSE POSITIVE' wording
2026-07-04 21:45:08 +08:00
LLLin000
fc968f550a docs: update spec with 8 corrections, add implementation plan
8 spec corrections from review:
1. PR 1: field-based return, not lines; insertion before title
2. PR 2: explicit body_paragraph escape in assign_block_role
3. PR 2: caption syntax supports delimiter + title patterns
4. PR 3: use existing ref_heading_block, no new scan
5. PR 3: same_page_tail_blocks + column check, test body rendering
6. PR 4: split None into full_width vs ambiguous_center
7. PR 4: column check before safe_auto_match, no sidecar exception
8. PR 2: fixture verification criteria per-fixture, not blanket
2026-07-04 21:39:50 +08:00
LLLin000
bdf96af6fd docs: four-PR architecture hardening spec
Based on layout truth audit findings (6 bug patterns), designs 4
independent PRs with precise code locations, helper contracts,
column-aware zone inference, caption formalness tightening,
and render frontmatter fallback. Includes before/after Mermaid
diagrams, test specs, and execution order.
2026-07-04 21:34:02 +08:00
LLLin000
26715a9d7e feat: layout-category truth audit complete
Workstream X: 11 papers audited across 6 layout classes,
5 verified via vision subagents. 6 real bug patterns identified
with code locations and root cause analysis.

Bug patterns:
A - _is_obviously_formal_figure_caption heuristic too aggressive
    (ocr_roles.py:193)
B - Cross-column figure asset mis-assignment ignores boundaries
    (ocr_figures.py:704)
C - Render frontmatter skip silently drops authors/affiliations
    (ocr_render.py)
D - Two-column same-page boundary body→backmatter zone pollution
    (ocr_document.py)
E - Frontmatter headings misclassified (ocr_roles.py)
F - Supplementary-only PDFs not handled

Full report: docs/superpowers/analysis/2026-07-05-layout-truth-audit-findings.md

Also: codebase-memory-mcp 0.8.1 installed and repo indexed.
2026-07-04 21:26:15 +08:00
LLLin000
914acd6aa5 feat: enable OCR_PIPELINE_V3 by default
The V3 pipeline has been tested against the full 555-paper vault vs legacy:

  No diff: 547 (98.6%)
  Diff:     5 (0.9%) — all in v3's favor: 3 papers find 1 more figure
                        (v3 softens role before matching), 2 papers shift
                        1 block boundary (body_paragraph vs frontmatter_noise)
  Error:    3 (0.5%) — 2 missing raw data, 1 pre-existing v3 pipeline edge case

The 5 diffs are marginal improvements, not regressions. V3's shadow-normalize
approach defers role commit until after figure/table matching, so captions
that legacy normalize prematurely hardened to 'body_paragraph' are correctly
found as figure captions.

Changes:
- _ocr_pipeline_v3_enabled() defaults to True now; set OCR_PIPELINE_V3=0 to
  revert to legacy normalize-then-match order
- Test updated to assert default=True
- Full vault corpus diff script + result report archived
2026-07-04 20:04:39 +08:00
LLLin000
f688baf839 docs: add v3-legacy corpus diff report (86 papers, 86/86 no diff) 2026-07-04 19:23:26 +08:00
LLLin000
268462c781 docs: sync OCR records after A/B/C merge 2026-07-04 18:00:38 +08:00
LLLin000
7856d6e202 fix: pre-merge blockers A-D
- A: page-qualified object writeback lookup (key by (page, block_id))
- B: contained figure text routed through ownership evidence
- C: v3 path rescue_roles_with_document_context equivalence
- D: regression tests for all 4 blockers
  - test_apply_object_writebacks_respects_page_for_duplicate_block_ids
  - test_contained_figure_text_stamps_ownership_evidence
  - test_post_match_normalize_runs_rescue_roles
  - test_v3_synthetic_parity_with_legacy_reference_boundaries
2026-07-04 16:40:53 +08:00
LLLin000
d82949ee58 C1: shadow normalize in pre_match_normalize + _match_role helpers
- Rewrite pre_match_normalize to run a shadow normalize pass that
  populates role_candidate on each block while preserving public role
- Add _match_role(block) helper to ocr_figures.py (role_candidate > role > seed_role)
- Port matching-time role reads in figure builders to use _match_role
- Add _match_role(block) helper to ocr_tables.py (same priority)
- Port matching-time role reads in table builders to use _match_role
- Port role reads in FigureCorpus.from_blocks and TableCorpus.from_blocks
- Add 3 C1 tests to test_ocr_pipeline_v3.py
- All 325 OCR tests pass (6 C0+C1 + 4 rendering + 5 writeback + 310 figures)
2026-07-04 16:02:55 +08:00
LLLin000
7bf652c42f feat: Workstream B — OCR tail settlement extraction and report
- B0: extract tail/backmatter settlement helpers into ocr_tail_settlement.py
- B1: add TailSettlementReport dataclass attached to DocumentStructure
- B2 gate: 41/41 tests pass (3 B0/B1 + 6 tail regressions + 32 A regression)
2026-07-04 13:37:45 +08:00
LLLin000
3cda942f96 fix: appendix numbering cross-cutting bugs (TABLE regex, int block_id, table alpha prefix, weak-caption tie-break)
3 distinct bugs found and fixed:

1. TABLE in figure regex (_FIGURE_NUMBER_PATTERN)
   Removed TABLE/Table from figure regex — caused table captions to be
   extracted as figure numbers and roadmapped into figure inventory.
   Added unit tests (table_numeric_caption_is_not_a_figure_number,
   table_appendix_caption_marker_has_no_figure_number).

2. int block_id type mismatch in cross-page lookup
   CrossPageSettlementPass and PrimarySamePagePass compared block_id
   with === but deduped_legends use int keys while ResourceRef stores
   str.  Fixed by casting both to str.  Table continuation lookup
   missed page filter, picking wrong page's same block_id.  Added
   page filter + int_block_id tests.

3. Table appendix support gaps
   - Table prefix regex only accepted digits/roman, not 'TABLE A1'.
     Added [A-Z]\d+ token and strip-leading-alpha in parse.
   - _is_validation_first_table_candidate didn't cover figure_title
     raw_label blocks with table_caption_like style.  Added second
     gate.
   - _is_weak_explicit_table_caption only checked table_caption roles.
     Extended to include validation-first candidates.
   - Same-page tie-break didn't apply for weak-explicit captions.
     Ported _bare_table_tie_break into vnext pass.
   - figure_caption_candidate not excluded from note attachment.
   - Continuation merge stripped leading duplicate table marker.

M84CTEM9 vault verification: 6/6 figures matched (3 main + 3
appendix + assets), 4/4 tables (Table 1,2 + Table A1,A2 + assets),
0 false positives, 0 figure asset leakage.
2026-07-04 01:29:06 +08:00
LLLin000
0f94123ed5 docs(ocr): add Plan A implementation document 2026-07-03 19:36:16 +08:00