Skip to content

Release 1.6: universal local document imports and hardening - #130

Open
Coding-Dev-Tools wants to merge 58 commits into
mainfrom
codex/importers-1.6-review
Open

Release 1.6: universal local document imports and hardening#130
Coding-Dev-Tools wants to merge 58 commits into
mainfrom
codex/importers-1.6-review

Conversation

@Coding-Dev-Tools

Copy link
Copy Markdown
Owner

Summary

  • ship the Engraphis 1.6 hardening line and a production v2 universal local-document importer
  • add engraphis import documents PATH with preview, trusted-local confirmation, resumable per-document writes, temporal revisions, idempotent re-import, conflict policies, and complete reports
  • retain a rich Obsidian compatibility adapter for frontmatter, tags, aliases, wikilinks, embeds, headings, and attachment references
  • add the owner-confirmed dashboard document wizard without exposing filesystem import through MCP or the generic bearer API
  • add schema 16 source collections, source items, job reports, and exact workspace/repo/session lineage integrity

Why

Users need to bring existing unsorted documents into Engraphis locally and repeatedly without creating a hidden AI-only copy, invoking an LLM extractor, or making network requests. Existing generic folder ingestion did not provide safe preview, stable source identity, temporal updates, resumability, rich Markdown links, or durable per-file reporting.

Safety and correctness

  • dry runs create no database, WAL, shared-memory, audit, receipt, or sidecar writes
  • paths are normalized and contained; traversal, symlinks/reparse points, Unicode path collisions, hidden/configuration paths, sensitive names, secret-bearing content, oversized files, ZIP/XML attacks, and malformed inputs fail closed per file
  • browser uploads enforce per-file/total bounds, duplicate detection, attachment manifest limits, and upload/attachment non-overlap at both dashboard and service boundaries
  • new browser sources cannot silently reuse a same-label lineage; resume requires selecting the registered vlt_ source
  • unchanged documents skip without reinforcement; revisions create temporal successors; exact-content renames preserve lineage; missing sources are reported without deleting memories
  • import jobs persist exact session identity, link reconciliation is cancellable and batched, and rename planning is linear
  • configured semantic models are cache/local-only during CLI imports; no model is downloaded

Supported inputs

Native parsers cover Markdown/Obsidian, plain text and logs, RST, HTML, JSON/JSONL, CSV/TSV, YAML, TOML, INI-style files, XML, RTF, common source code, DOCX, ODT, EPUB, XLSX, PPTX, ODS, and ODP. PDF, image, audio, and video use optional configured local extractors. Legacy OLE, encrypted/DRM, and unknown binary formats are rejected and reported rather than guessed.

Validation

  • complete offline tests/ suite passed
  • focused importer, schema, CLI, dashboard, documentation, encryption, sync, receipt, packaging, and entry-point suites passed
  • ruff check .
  • pyright — 0 errors, 0 warnings
  • commercial manifest and dashboard asset-drift gates passed
  • sample and code/conflict retrieval datasets: 1.000 recall@5, hit@5, and answer-token recall
  • ablation, bounded-reinforcement, and adversarial memory-security gates passed
  • wheel built and installed; all 15 console entry points passed
  • installed-wheel dry run created no DB/WAL/SHM files; first import succeeded; unchanged re-import skipped without duplication

Intentional limitations

Conservative top-level YAML is parsed rather than arbitrary executable YAML. Dataview/plugins/macros/scripts and transclusion expansion are not executed. Attachments are catalogued but not copied. Scanned PDFs do not gain automatic OCR, ambiguous links remain warnings, and legacy OLE/encrypted/DRM files remain unsupported.

Store/Schema:
- Transaction rollback safety on Windows (commits_deferred flag)
- Skip redundant index.upsert when index shares store vector table
- Embedding-space contract validation and direct SQL matrix path
- Restore orphaned Store methods (prompt_eligibility_counts,
  embedding_space_health, context_savings_grouped, add_sync_bytes,
  get_sync_stats) and harden _logical_digest for sqlite-vec
- Dashboard startup self-check for orphaned Store methods
- v11 handoff column migration for sessions table

Release readiness:
- Strip dead TEAM scope surface (Scope.TEAM, MemoryRecord.team_id,
  SearchFilter.team_id/caller_id) per AGENTS.md §0
- Remove team_id column from memories table (team_members retained)
- Remove conflict_aware profile (zero callers/tests/docs)
- Add format/group_by params to MemoryService.context_savings()

Other:
- watch_repo key name, LLM fallback chain cost tracking
- context_savings_grouped SELECT columns
- Sync robustness, response budgets, docs sync
- MCP tool engraphis_context_savings: add format and group_by params
- v2 API route /context-savings: add format and group_by query params
- Read-only API /context-savings: add format and group_by query params
- MCP HTTP CLI: minor fix
- eval/extractor_quality.py: offline extractor distillation quality harness
- eval/handoff_quality.py: structured session-handoff eval
- eval/datasets/handoff_quality.jsonl: handoff scenario fixtures
- eval/datasets/sample.jsonl: 3 new entries (link_symbol, hierarchical
  consolidation, extractor/handoff patterns)
- scripts/watch_repo.py: file-watcher for code-graph reindexing
- scripts/validate_compose_contract.py: schema contract validator
- dashboard_app.py: pass workspace to stats() when allowed_workspaces
  is configured (prevents ValidationError on workspace-bound instances)
- Sync classic_assets and static bundles with latest dashboard changes
- test_cli_entrypoints: clear ENGRAPHIS_WORKSPACES env for subprocess isolation
- test_dashboard_security_headers: monkeypatch.delenv ENGRAPHIS_WORKSPACES
- test_savings: adjust for context_savings format/group_by signature
- test_sync: align with sync robustness hardening
- test_update_check: align with 2-part semver acceptance
- test_mcp_server, test_smart_mcp_gateway: align with MCP surface wiring
- test_store_class_integrity: new Store method integrity coverage
- test_dashboard_v2, test_release_infrastructure, test_secret_hygiene: minor
  alignment with pro-feature changes
The restored method from b7e80c2 predated the hash-validation contract
in _public_receipt_row. Without prev_hash and receipt_hash in the SELECT,
every receipt was marked invalid_payload and excluded from aggregation,
causing the grouped method to return 0 groups despite valid receipts.

Verified: all 4 dimensions (workspace/repo/agent/day) now return correct
token aggregation. Savings ratio: 0.6 (180 saved / 300 source).

Found by round-3 ContextSavingsGroupedRuntime scout.
Save JSON reports to a directory with timestamped filenames.
Cherry-picked from codex/fix-pr-104-codeql-v4 (a4928c5).
… preservation, retention SQL, migration safety, port parsing

- llm/client.py: _LLMProviderError accepts *args + message kwarg (fixes TypeError on cost-ceiling path)
- llm/client.py: parse_provider_chain detects URL ports via :// prefix check (prevents port-as-ceiling stripping)
- core/sync.py: quarantine merge preserves prior reasons alongside inherited_quarantine (audit trail)
- stores/vectors.py: upsert_memory preserves existing memory_type when caller passes default semantic
- routes/memory.py: AVG(stability) SQL approximation for retention stats (avoids OOM on large workspaces)
- routes/vault.py: hashlib suffix on smart-import split doc_ids (collision prevention)
- routes/vault.py: health_overview and find_stale bounded to 10k limit
- service.py: Windows-safe two-step rename with staging file and rollback for v1->v2 migration
- stores/__init__.py: graph backfill uses _replace_support_rows + per-namespace rebuild (O(N) not O(N²))
- config.py: embed_dim downstream consumers use 'is not None' pattern
- 6 downstream embed_dim call sites fixed (dashboard_app, mcp_server, read_only_api, inspector, v2_api, embedder)
- eval/longmemeval_v2.py: _stored_memory_type_counts scoped to workspace
- eval/harness.py: --output-dir writing inside try/except for clean CLI errors
- KILO_CODE_INTEGRATION.md: tool count corrected to nine; engraphis_forget row added
- .env.example: ENGRAPHIS_SYNC_TOKEN_ORIGIN documented
- Test file trailing newlines restored
…verage

Closes P1 gap flagged by FinalA_Tests review:
- port-stripping fix (localhost:8080 vs ceiling) — 5 cases
- multi-provider chain parsing with mixed ceilings
- empty/whitespace fallback to default chain
- _LLMProviderError positional+kwarg construction contract
… harness improvements

- .github/workflows/release.yml: CodeQL config-file reference added
- .env.example: ENGRAPHIS_SYNC_TOKEN_ORIGIN documented for standalone sync tokens
- docs/KILO_CODE_INTEGRATION.md: Smart tool count corrected to nine; engraphis_forget row added to Classic table
- engraphis/dashboard_assets/vendor/d3.min.js: unified across classic/static (no new Function)
- eval/longmemeval_v2.py: _stored_memory_type_counts scoped to workspace
- eval/harness.py: --output-dir writing inside try/except for clean CLI errors
- tests/e2e/demo.spec.js, test_dashboard_vendor_assets.py, test_documentation_contracts.py: new coverage
- deploy/force-graph license/yarn lock files added
- docs/benchmark-evidence offline fixtures added
- Multiple doc updates: AGENTS.md, BENCHMARKS.md, CHANGELOG.md, README.md, SECURITY.md, SYNC.md
- Demo infrastructure: screen demo HTML, prepare script, record script
- Integration updates: hermes plugin, pi MCP client
- Skills: engraphis-memory SKILL.md and references updated
Comment thread engraphis/routes/vault.py Fixed
Comment thread engraphis/routes/vault.py Fixed
@Coding-Dev-Tools
Coding-Dev-Tools marked this pull request as ready for review August 9, 2026 08:07

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a214aef834

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread engraphis/service.py
Comment thread engraphis/service.py Outdated
Comment thread engraphis/core/query_planner.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: edec95a288

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread engraphis/core/documents.py Outdated
Comment thread engraphis/core/documents.py
Comment thread scripts/watch_repo.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f72b462b86

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread engraphis/core/sync.py
Comment thread engraphis/service.py
Comment thread engraphis/routes/vault.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1ceea5000e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread engraphis/core/store.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 72d3b26679

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread engraphis/obsidian_import.py Outdated
Comment on lines +1002 to +1004
if len(candidates) != 1:
if candidates:
retire_ambiguous_links(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retire links whose imported target disappears

When a previously imported target file is removed while the referring note remains unchanged, resolution reaches this branch with no candidates, but link retirement runs only when candidates is nonempty. The missing target's memory intentionally remains live, so its existing document_reference/obsidian_wikilink edge also remains live and recall can continue traversing a reference that this run reports as unresolved; invalidate prior derived links that are absent from the newly resolved target set.

AGENTS.md reference: AGENTS.md:L162-L164

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 913af10b77

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

session_id: Optional[str], scope: Scope, memory_type: MemoryType,
policy: str, vault_label: str, attachment_manifest: Optional[list[dict]],
) -> dict:
files = list(outcomes)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include unprocessed plans in terminal reports

When either document or Obsidian importing is cancelled before all plans run (including a CLI --limit pause), or an outer-loop failure stops processing, the durable job items for every unprocessed plan remain result_state="pending", but _final_report() starts only from completed outcomes and adds pending rows only for deferred missing checks. The resulting job can therefore report documents: 2 with an empty files list and no pending count even though both durable items are pending, making resumable progress inconsistent; include all plans without outcomes as pending rows.

AGENTS.md reference: AGENTS.md:L215-L219

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39969abae3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +719 to +721
if old_item is not None:
old_memory_id = self._live_subject_memory(str(old_item.get("subject_key") or ""))
old_memory_id = old_memory_id or str(old_item.get("memory_id") or "") or None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Serialize concurrent imports per source item

When two dashboard jobs or CLI processes import the same changed source concurrently, both can read the same live predecessor here before either write begins. Each transactional finalizer then closes only that shared predecessor, so both successor memories remain live under the same subject_key, the manifest points to whichever finishes last, and both jobs report completion. Serialize imports by source identity or revalidate and close the current subject memory inside the write transaction.

AGENTS.md reference: AGENTS.md:L162-L164

Useful? React with 👍 / 👎.

Comment thread engraphis/obsidian_import.py Outdated
Comment on lines +980 to +985
"UPDATE mem_links SET valid_to=?, valid_to_recorded_at=? "
"WHERE reason=? AND valid_to IS NULL AND expired_at IS NULL "
"AND ((a=? AND b IN (" + marks + ")) "
"OR (b=? AND a IN (" + marks + ")))",
(stamp, stamp, self.LINK_REASON, source_id, *target_ids,
source_id, *target_ids),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retain links with independent source support

When two notes independently support the same undirected relation and one note's reference later becomes ambiguous, this update closes their shared mem_links row even though the other note still has a uniquely resolved reference. Since Store.add_link() deduplicates either direction by pair and relation, whether the valid note reopens the link depends on filename iteration order; for example, an earlier A.md -> C.md reference is removed when later C.md -> [[Alias]] becomes ambiguous. Reconcile the complete desired support set or persist per-reference provenance before retiring the aggregate edge.

AGENTS.md reference: AGENTS.md:L171-L172

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6b4465aafe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread engraphis/obsidian_import.py Outdated
Comment on lines +381 to +383
link_warnings = self._reconcile_links(
scan, vault_id=vault_id, job_id=job_id, cancel_check=cancel_check,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Defer link reconciliation for incomplete scans

When a referenced target lies under a temporarily unreadable subtree, can_finalize_missing correctly prevents missing-item reconciliation, but this unconditional call still reconciles against the incomplete scan.notes. The historical target is then treated as unresolved and its last-good live link is retired; if another scanned file shares its basename, the reference can even be redirected to that file. Skip link reconciliation when the scan is incomplete, or include preserved unreadable paths in the resolution index.

AGENTS.md reference: AGENTS.md:L215-L219

Useful? React with 👍 / 👎.

Comment on lines +1078 to +1081
warnings.append(self._outcome(
note, "warning",
"ambiguous_wikilink" if candidates else "unresolved_wikilink",
))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Persist link-reconciliation warnings in job items

For asynchronous dashboard imports containing an unresolved or ambiguous reference, this warning exists only in the transient outcomes list. _finish_job() persists the warning count, but get_document_import_job() reconstructs files exclusively from source_import_items, so polling can report counts.warning == 1 while every file has an empty reason and zero warnings. Merge these warnings into the corresponding durable job item or persist a dedicated warning item.

AGENTS.md reference: AGENTS.md:L259-L261

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4062dd3a99

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return record
if spec.name == "xml":
body, title, metadata, warnings = _xml_body(raw, fallback)
content = body

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve XML attributes before checking for secrets

When valid XML stores data in attributes, such as <server api_key="..." host="prod">name</server>, assigning content = body discards those values before the secret check; most attributes vanish entirely, while href/src values are still copied into persisted link metadata and can therefore store a credential that the check never sees. Preserve a bounded XML representation or scan every persisted attribute so imports neither lose configuration facts nor bypass the documented secret rejection.

AGENTS.md reference: AGENTS.md:L259-L261

Useful? React with 👍 / 👎.

Comment thread engraphis/core/documents.py Outdated
Comment on lines +1181 to +1183
if self._ignored:
if lower in {"script", "style", "noscript", "template"}:
self._ignored -= 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match ignored HTML closing tags to their opener

When malformed HTML inside noscript or template contains a mismatched ignored closing tag, this decrements _ignored regardless of which tag opened the ignored region; for example, <noscript></style>EVIL</noscript> imports EVIL even though noscript content is supposed to be excluded. Track the ignored tag stack, or only close the matching region, so hidden script/fallback content cannot become canonical memory text.

AGENTS.md reference: AGENTS.md:L259-L261

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d111842e26

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if sum(len(part) for part in parts) + len(text) + (2 if parts else 0) > MAX_CONTAINER_TEXT_CHARS:
raise DocumentParseError("document exceeds 100000 character safety limit")
parts.append(text)
title = next(("".join(item.itertext()).strip() for item in package.iter() if item.tag.endswith("title") and "".join(item.itertext()).strip()), "")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Validate EPUB package titles before exposing them

When an EPUB's OPF <dc:title> contains a credential-shaped value but its chapter text does not, the parser extracts that title here while the secret check validates only content and body. Document previews then return the unredacted value in each file's title before the engine's later write boundary can reject it, violating the import report's no-secret-echo contract. Include EPUB title/package metadata in the bounded secret-validation boundary.

AGENTS.md reference: AGENTS.md:L259-L261

Useful? React with 👍 / 👎.

Comment thread engraphis/core/documents.py Outdated
Comment on lines +922 to +923
elif name in {"odt", "ods", "odp"}:
body, meta = _office_body(archive, "content.xml", "{urn:oasis:names:tc:opendocument:xmlns:text:1.0}", ("h", "p"), None)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Extract attribute-backed ODS cell values

For a valid ODS whose numeric, date, or boolean cells store their values in standard office:value-style attributes without a <text:p> display node, routing ODS through _office_body() extracts only text headings and paragraphs. A numeric-only worksheet consequently produces no readable text and is rejected, despite ODS being advertised as preserving worksheet/cell values. Parse ODS table rows and typed value attributes separately from the word-processing path.

AGENTS.md reference: AGENTS.md:L259-L261

Useful? React with 👍 / 👎.

target_id = memory_by_path.get(candidates[0])
if not target_id or target_id == source_id:
continue
desired_pairs.add(pair_key(source_id, target_id))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retire fallback links when exact resolution changes

When an unchanged [[foo]] initially resolves by basename to sub/foo.md and a later import adds an exact foo.md, this branch adds the new exact-target pair but the old fallback pair never enters retire_pairs, because retirement is performed only in the ambiguous/unresolved branch. Both edges remain live and recall can continue traversing the obsolete target; after building the complete desired pair set, invalidate importer-derived pairs that no source reference still supports.

AGENTS.md reference: AGENTS.md:L162-L164

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5aaa943bd5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread engraphis/core/documents.py Outdated
Comment on lines +1047 to +1049
for _ in range(repeated):
cells.append(value)
cell_count += 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bound repeated ODS cells before materializing them

When an ODS cell combines table:number-columns-repeated="10000" with a large text value, this loop appends the value 10,000 times and joins the entire row before the size check below runs; a roughly 100 KB XML cell can therefore allocate about 1 GB and terminate the import process despite the advertised 100,000-character limit. Check the projected row size before expanding repeated cells.

AGENTS.md reference: AGENTS.md:L259-L261

Useful? React with 👍 / 👎.

Comment thread engraphis/core/documents.py Outdated
fallback = Path(relative_path).stem or "document"
return DocumentRecord(
relative_path=relative_path, format=spec.name, media_type=spec.media_type,
title=title or (headings[0] if headings else fallback), content=content, body=body,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cap extracted titles before creating document records

When metadata supplies an oversized title, this assignment retains it without applying the document text bound; for example, an EPUB OPF can contain a title larger than 100,000 characters while its chapter body is tiny and still pass the content/body checks. The preview then serializes the entire title and the engine concatenates it into embedding input, allowing oversized responses and writes despite the documented cap, so bound the title before returning the record.

AGENTS.md reference: AGENTS.md:L259-L261

Useful? React with 👍 / 👎.

Comment thread engraphis/core/documents.py Outdated
Comment on lines +797 to +800
if content[end] == "\\":
end += 1
if end < len(content) and content[end].isalpha():
while end < len(content) and content[end].isalpha():

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Consume complete RTF Unicode fallback controls

When an RTF Unicode fallback is encoded as a control symbol or hex escape, such as \u945\'3f, this branch advances past only the backslash because the following apostrophe is not alphabetic. The remaining parser consequently imports α'3f rather than α; consume the entire control-symbol or hex-escape fallback as the single character represented by \ucN.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0a2110b64e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +307 to +308
if secret_kind(record.content) is not None or secret_kind(record.body) is not None:
raise DocumentParseError("source appears to contain a secret")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate adapter metadata before returning records

When a custom PDF/OCR/transcription adapter returns safe content and body but places a credential in title or metadata, this check accepts the record because it scans only the two text fields. The title is then exposed by import previews and both values can be persisted in document metadata, contradicting the import report's no-secret-echo boundary; validate every adapter-controlled field that can be returned or stored.

AGENTS.md reference: AGENTS.md:L259-L261

Useful? React with 👍 / 👎.

rows: List[str] = []
cell_count = 0
total = 0
for row in (item for item in root.iter() if item.tag.endswith("table-row")):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve repeated ODS rows

When a valid ODS uses table:number-rows-repeated on a nonempty row, this loop processes the row only once; for example, a row repeated three times is imported as one row and reported with rows == 1. This silently loses spreadsheet values and multiplicity, so account for row repetition while applying the same projected-output bound used for repeated columns.

AGENTS.md reference: AGENTS.md:L259-L261

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: df587ce27a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if raw.startswith((b"\xff\xfe", b"\xfe\xff")):
return _decode_text(raw)
head = raw[:65536]
match = _HTML_CHARSET_RE.search(head) or _HTML_CONTENT_CHARSET_RE.search(head)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse charset only from actual HTML metadata

When valid HTML contains meta-like text inside a comment before its real declaration, such as <!-- <meta charset=windows-1252> --><meta charset=utf-8>, this raw-byte regex selects the ignored declaration. UTF-8 text is then decoded as Windows-1252 and persisted incorrectly (for example, Café becomes Café) without a warning; charset detection needs to ignore comments and other non-metadata content.

Useful? React with 👍 / 👎.

@Coding-Dev-Tools

Copy link
Copy Markdown
Owner Author

Pre-PR Code Review — engraphis#130

Structural Assessment

This is a massive release PR (17,354 additions / 4,830 deletions across 62 files, 50+ commits) covering:

  • Universal local document importer with preview, resumability, and temporal revisions
  • Schema 16 source collections and job reports
  • Pro-feature hardening (store, sync, encryption, analytics)
  • CI/CD alignment, docs corrections, dashboard assets
  • Extensive iterative review from chatgpt-codex-connector (20+ comment cycles)

CI Status: ✅ All 23 checks green

CodeQL, test+lint (Python 3.9–3.14), coverage, typecheck, encryption driver gates, Pi extension (Ubuntu + Windows), browser accessibility, docker build/smoke, wheel build, repo hygiene — all passing.

Security Observations

The PR body documents thorough safety measures:

  • Dry runs create no DB/WAL/SHM writes
  • Path normalization and containment; symlink/traversal/Unicode collision protection
  • Browser upload bounds, duplicate detection, attachment manifest limits
  • No model downloads during CLI imports
  • ZIP/XML attack prevention, malformed input fail-closed

Hard Gate Blocks (cannot approve yet)

  • Contributor count: Only Coding-Dev-Tools has authored commits. The hard gate requires 3 distinct agent contributors before merge approval. While chatgpt-codex-connector provided extensive review feedback, it has not authored commits to this branch.
  • PR scope: This is a release aggregation PR. The individual feature commits have been iteratively reviewed, but the consolidated diff warrants a final pass on integration points (schema migration ordering, import reconciliation with concurrent writes, v1→v2 rename rollback).

Verdict: REQUEST_CHANGES

The code quality appears high based on CI coverage and iterative review history. Once the contributor gate is satisfied (e.g., another agent authors a refinement commit or the contributor requirement is waived for release PRs), this is approvable.

Suggested next steps:

  1. Coordinate with Sentinel for multi-contributor coverage or obtain a waiver for release aggregation PRs.
  2. Ensure schema 16 migration has been tested against a production-sized workspace.
  3. Verify the importer reconciliation handles partial-failure recovery under concurrent access.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants