Commit Graph
2214 Commits
Author SHA1 Message Date
Sameer6305 f75469f472 Merge remote-tracking branch 'semantica-agi/main' into fix/843-vectorstore-persistent-backend-accessors 2026-08-07 22:23:39 +05:30
Mohd Kaif 50758f6f25 Merge pull request #846 from SaurabhScripts/codex/fix-markdown-import-path-errors
fix(context): preserve Markdown import path errors
2026-08-07 16:49:24 +05:30
Saurabh 2756916573 Merge branch 'main' into codex/fix-markdown-import-path-errors 2026-08-07 16:17:17 +05:30
Mohd Kaif f47c730f7e Merge pull request #842 from Sameer6305/fix/839-decisionembeddingpipeline-backend-support
Fix #839: Support persistent backends in DecisionEmbeddingPipeline
2026-08-07 16:05:25 +05:30
KaifAhmad1 721a2f0e9c Fix candidate-embeddings loop dropping matches when pool exhausted
_get_candidate_embeddings()'s expand-and-retry loop widens the search
pool (up to limit*10) when post-filtering leaves too few candidates.
If the backend keeps returning a full page and filtered matches never
reach `limit`, the loop exited via the while condition instead of the
break branch, so the pre-loop empty embeddings/metadata/scores lists
were returned instead of the matches actually found in the final
iteration. This silently returned [] for filtered queries against
large persistent-backend stores even when matches existed - exactly
the scenario this PR adds support for.

Falls back to the last collected batch instead of discarding it.
Also documents this PR and #839 in the changelog.
2026-08-07 15:53:55 +05:30
Sameer6305 dd42b7fa95 fix(milvus): add backward compatibility alias and sanitize query
- Added insert_vectors alias to add_vectors for backward compatibility.
- Sanitized vector_id in get_vector and get_metadata to prevent query injection.
2026-08-07 12:11:48 +05:30
Sameer6305 248d028b09 fixed qodo reviews
- FAISSStore: get_metadata now correctly retrieves from self.metadata instead of raising NotImplementedError.
- MilvusStore:
  - Changed schema to support String IDs (VARCHAR) instead of auto-generated INT64, preventing loss of IDs during insert.
  - Added metadata storage using JSON.
  - Replaced insert_vectors with add_vectors accepting ids and metadata (added insert_vectors alias for backward compatibility).
  - Implemented get_vector and get_metadata with safe parameterized querying to prevent query injection.
- PgVectorStore & SQLiteVecStore:
  - Fixed get_vector and get_metadata to call self.get([vector_id]) instead of the non-existent get_vectors([vector_id]), fixing the silent None return bug.
2026-08-07 12:04:47 +05:30
Saurabh Meena 77a2ab7b18 fix(context): retain path inspection diagnostics 2026-08-07 11:27:52 +05:30
Sameer6305 c8b59b47f5 fix(vector-store): fix get_vector/get_metadata crash on persistent backends (#843)
- VectorStore.get_vector() and get_metadata() were hardcoded to access
  self.vectors and self.metadata dicts, which are only initialized for
  the inmemory backend, causing AttributeError on all persistent backends
  (FAISS, Qdrant, Pinecone, Milvus, Weaviate, PgVector, SQLiteVec).

Changes:
- Refactor VectorStore.get_vector() and get_metadata() to branch on
  self.backend == 'inmemory' (zero behavior change) and delegate to
  self._backend_store otherwise.
- Harden save() to use getattr(self, 'vectors', {}) / getattr(self,
  'metadata', {}) to prevent crash when saving a persistent backend store.
- Add get_vector() and get_metadata() to all 7 backend wrappers:
  - FAISSStore: get_vector uses index.reconstruct(); get_metadata raises
    NotImplementedError (FAISS has no metadata storage natively).
  - QdrantStore: uses client.retrieve() with with_vectors/with_payload.
  - PineconeStore: wraps existing fetch_vectors() call.
  - MilvusStore: raises NotImplementedError (auto_id=True schema discards
    string IDs at insert time, making by-ID lookup impossible in this
    wrapper's current schema).
  - WeaviateStore: uses collection.query.fetch_object_by_id().
  - PgVectorStore: wraps existing get_vectors() SQL method.
  - SQLiteVecStore: wraps existing get_vectors() SQL method.
- Add TestVectorStoreRetrieval regression tests covering inmemory and
  FAISS backends with real (non-mocked) assertions.

All 28 tests pass.
2026-08-07 11:21:42 +05:30
Saurabh Meena c0b6a80480 fix(context): preserve Markdown path errors 2026-08-07 01:15:55 +05:30
Sameer Kadam 36071819b5 Merge branch 'main' into fix/839-decisionembeddingpipeline-backend-support 2026-08-06 20:15:05 +05:30
Sameer6305 a4dac2342b fixed qodo reviews 2026-08-06 19:44:23 +05:30
Sameer6305 7d272f40e8 Fix #839: Support persistent backends in DecisionEmbeddingPipeline
- Replace direct .vectors and .metadata access with VectorStore.search_vectors().
- Add a fallback in HybridSimilarityCalculator (via ind_similar_decisions) to use the search score when backend vector databases do not natively return the raw vector array.
- Fix get_decision_statistics to gracefully fall back when .metadata is not fully supported by the underlying DB.
- Add regression tests utilizing the real FAISS and inmemory backends directly without mocking.
2026-08-06 19:11:35 +05:30
Mohd Kaif 3e5d2672ad Merge pull request #841 from divyankshah/fix/gh-840-qdrant-metadata-key
fix(vector_store): normalize QdrantStore.search_vectors() to return "metadata"
2026-08-06 19:10:42 +05:30
KaifAhmad1 b4b10a4928 docs(changelog): document Qdrant metadata key normalization
Adds an Unreleased/Fixed entry for #841 (closes #840) — QdrantStore
search results were keyed "payload" instead of "metadata", breaking
HybridSearch.filter_by_metadata() for Qdrant results.
2026-08-06 18:53:40 +05:30
Mohd Kaif 48c58a0753 Merge branch 'main' into fix/gh-840-qdrant-metadata-key 2026-08-06 17:26:02 +05:30
Mohd Kaif 6b143ef401 Merge pull request #838 from Linxiushen/feat/embedded-triplet-store
feat(triplet-store): add embedded Oxigraph backend
2026-08-06 16:33:13 +05:30
Mohd Kaif 49f458e927 Merge branch 'main' into feat/embedded-triplet-store 2026-08-06 16:22:56 +05:30
KaifAhmad1 c77184bd77 docs(changelog): document embedded Oxigraph backend and ImportError fix
Adds an Unreleased/Added entry for #838 (closes #834), including the
follow-up fix that preserves ImportError for a missing pyoxigraph
install instead of masking it as a generic ProcessingError.
2026-08-06 16:15:47 +05:30
Mohd Kaif fa77f5cc47 Merge pull request #836 from Sameer6305/fix/830-temporal-panel-render-loop
fix(explorer): resolve infinite render loop preventing Temporal panel from rendering (#830)
2026-08-06 13:24:17 +05:30
KaifAhmad1 7bddee0111 ci: update stale github/codeql-action v4 pin
Upstream moved the v4 tag to 5595ccaf912efad79be6eef63a5619ff05969be3
(v4.37.6), which the repo's own verify-action-pins.sh now (correctly)
flags as a mismatch against the previously-pinned commit. Pre-existing
drift unrelated to #830/#836, but it was failing this PR's required
"verify" check, so fixing it here.
2026-08-06 13:10:13 +05:30
KaifAhmad1 5cd4407e57 fix(explorer): review follow-ups for #830 render-loop fix
- Wire the Explorer frontend's node --test suites (test:graph-store,
  test:graph-workspace, and the new test:plugin-registry regression
  test) into CI. Previously only `npm run build` ran, so none of the
  frontend tests -- including this fix's own regression coverage --
  executed anywhere except a contributor's local machine.
- Broaden the diagnostics dedup's structureLayer comparison to also
  cover disabledReason/curveCount/bridgeCurveCount/backboneCurveCount,
  not just cacheKey/lastDrawAt/enabled, so a disabledReason-only
  transition doesn't leave the dev diagnostics panel stale.
2026-08-06 13:03:56 +05:30
KaifAhmad1 1850cdd617 Merge remote-tracking branch 'origin/main' into fix-830-followup
# Conflicts:
#	CHANGELOG.md
2026-08-06 13:03:28 +05:30
Mohd Kaif 5f00c00be3 Merge pull request #837 from semantica-agi/fix/833-hybridsearch-attributeerror-non-inmemory-backends
fix: HybridSearch.search() crashes with AttributeError on non-inmemor…
2026-08-06 12:06:18 +05:30
Mohd Kaif dee55112ef Merge branch 'main' into fix/833-hybridsearch-attributeerror-non-inmemory-backends 2026-08-06 11:59:30 +05:30
shah b7ac05b6f2 fix(vector_store): normalize QdrantStore.search_vectors() to return "metadata"
QdrantStore.search_vectors() returned results keyed by "payload" while
HybridSearch and PineconeStore both expect/return "metadata". This silently
dropped metadata from Qdrant results and caused HybridSearch.filter_by_metadata
to reject every candidate when a filter was applied (empty result sets).

Fixes #840
2026-08-06 02:33:50 +02:00
Mohd Kaif d9118410bc Merge pull request #829 from Sameer6305/feat/793-temporal-diff-ui
feat(explorer): add temporal diff comparison UI to the Temporal panel (#793)
2026-08-05 21:30:30 +05:30
Mohd Kaif d16db085d8 Merge branch 'main' into feat/793-temporal-diff-ui 2026-08-05 21:23:59 +05:30
Sameer6305 cb716cec61 Merge semantica-agi/main into fix/833-hybridsearch-attributeerror-non-inmemory-backends 2026-08-05 21:12:11 +05:30
Sameer6305 712a6e6d4c test(hybrid_search): add backend delegation regression coverage 2026-08-05 20:31:59 +05:30
林SO b52cdd5bbe fix(triplet-store): preserve missing backend dependency errors 2026-08-05 22:36:19 +08:00
Mohd KaifandSameer6305 d0e018a1c9 fix(vector_store): stop dropping metadata for add_vectors-only backends (#835)
* fix(vector_store): stop dropping metadata for add_vectors-only backends

VectorStore.store_vectors() previously discarded the metadata argument
whenever the backend only exposed add_vectors() (e.g. FAISSStore), even
though add_vectors() supports it. Now metadata is forwarded, and is only
passed when the backend's add_vectors() signature actually accepts it
(checked via inspect.signature), avoiding a TypeError for stricter
backend signatures.

Fixes #832

* fix(vector_store): guard signature introspection in store_vectors

inspect.signature() can raise ValueError/TypeError for some callables
(e.g. certain C-implemented or dynamically built methods). Wrap the
add_vectors() signature probe in try/except, consistent with the same
pattern already used in ProvenanceManager.trace_lineage(), defaulting
to attempting to pass metadata when introspection fails.

* docs(changelog): document VectorStore metadata-drop fix (#832, #835)

* test(vector_store): add regression coverage for metadata forwarding

---------

Co-authored-by: Sameer6305 <sskadam6305@gmail.com>
2026-08-05 19:59:53 +05:30
Sameer6305 bd8d6c5913 docs: add #830 Explorer Temporal panel fix to CHANGELOG.md 2026-08-05 18:06:45 +05:30
Sameer6305 667e69a0c1 refactor: tighten comments across #830 changes for clarity
- pluginRegistryPredicates.ts: consolidate 8-line JSDoc to 5 lines,
  removing redundant detail that restated implementation mechanics
  already obvious from the code.

- GraphWorkspace.tsx: shorten the lastScrubberMsRef comment from 5 lines
  to 2; trim the handleDiagnosticsChange block comment by removing the
  'rather than bailing out' implementation-alternative sentence; tighten
  the distanceVisual inline comment.

- pluginRegistry.temporal.test.mjs: replace 17-line file-level JSDoc
  with 9 lines focused on the invariant rather than the root-cause
  narrative (already covered in pluginRegistryPredicates.ts); remove
  two tsx loader implementation-detail comments; tighten two test-level
  inline comments.

No logic, types, or test assertions changed. All 42 tests pass.
2026-08-05 17:52:21 +05:30
KaifAhmad1 9c7dd16126 docs: add CHANGELOG entry for HybridSearch AttributeError fix (#833, #837) 2026-08-05 17:45:13 +05:30
KaifAhmad1 94adcf7ad3 fix: address code review findings on backend-delegated search path
- Legacy top_k kwarg was read but not removed from options, so it got
  forwarded via **options into VectorStore.search_vectors(), colliding
  with backends that call search(..., top_k=k, **options) (e.g. sqlite,
  pgvector) and raising "got multiple values for keyword argument
  'top_k'". Now popped instead of just read.
- VectorStore.search_vectors()'s dispatch only recognized backend
  methods named search/search_similar, so HybridSearch's delegation
  still hit NotImplementedError for qdrant/milvus/pinecone, which name
  their method search_vectors() with a differently-named count
  parameter (limit vs k). Added a third dispatch branch that binds the
  count positionally so it works regardless of the backend's parameter
  name.
- Backend-delegated results defaulted a missing "distance" to the raw
  score, silently reusing the local path's cosine-similarity convention
  (distance = 1 - score) even for backends using unrelated metrics
  (L2, inner product). A missing distance is now left as None instead
  of a fabricated, metric-inconsistent value.
2026-08-05 17:41:31 +05:30
Sameer6305 80de3652cf fixed qodo findings
Two issues addressed:

1. Plugin-loading useEffect unnecessarily depended on temporalState.
   After the #830 fix, no shouldLoad predicate reads temporalState, but
   the effect's dep array still included it, causing extra re-runs on
   every scrubber update. Removed temporalState from the dep array and
   the shouldLoad call site. Made temporalState optional in the
   LazyPluginRegistryEntry shouldLoad context type to match.

2. Regression test imported a local copy of shouldLoad instead of the
   production predicate. Extracted all three shouldLoad predicates into
   pluginRegistryPredicates.ts (pure module, no React/DOM dependencies),
   wired GraphWorkspace.tsx to use the imported functions, and updated
   the test to import and exercise the real production code via tsx.
   Verified: introducing the old broken condition causes the test to fail;
   the correct implementation passes all 7 assertions.
2026-08-05 17:37:33 +05:30
林SO 0e1b88a593 feat(triplet-store): add embedded Oxigraph backend 2026-08-05 20:06:20 +08:00
KaifAhmad1 b4f820568a fix: HybridSearch.search() crashes with AttributeError on non-inmemory backends
HybridSearch.search() directly accessed self.vector_store.vectors, a dict
that VectorStore only creates for backend="inmemory". Every other backend
(faiss, weaviate, qdrant, milvus, pinecone, pgvector, sqlite) raised
AttributeError. It now delegates to VectorStore.search_vectors() for
non-inmemory backends, applying metadata_filter as a post-filter and
normalizing results to a consistent {id, score, distance, metadata} shape.

Also fixes two related bugs surfaced while testing the backend-delegated
path end to end:
- vector_ids could remain None when explicit vectors/metadata were passed
  without vector_ids, crashing downstream indexing.
- query_vector passed as a plain list crashed backend stores (e.g.
  FAISSStore.search_similar) that call .ndim on it; now normalized to a
  numpy array up front.

And in vector_store.py: VectorStore.store_vectors() silently dropped
metadata for FAISS (and any add_vectors-only backend) because it called
add_vectors(vectors, **options) without forwarding metadata, even though
FAISSStore.add_vectors() accepts it. This blocked HybridSearch's metadata
filtering from working at all against FAISS.

Fixes #833
2026-08-05 17:16:56 +05:30
Sameer6305 8d52281cdf chore(explorer): clean up #830 branch — remove #793 file, add regression test
temporalDiffState.ts belongs to feat/793-temporal-diff-ui and should not
appear in the #830 diff. Remove it from this branch's tracked files.

Add the pluginRegistry.temporal.test.mjs regression test that covers the
shouldLoad fix committed in the main #830 commit (it was never committed).

Add test:plugin-registry script to package.json so the regression test
can be run via npm run test:plugin-registry.
2026-08-05 16:26:24 +05:30
Sameer6305 6a0eecbe02 fix(explorer): resolve #830 — Maximum update depth exceeded on Temporal panel open
Two independent render loops were causing the Temporal panel to remain
stuck on 'Loading temporal...' in npm run dev:

Loop 1 — diagnostics state churn (GraphWorkspace.tsx):
  handleDiagnosticsChange unconditionally called setGraphDiagnosticsState
  with a new object on every invocation. buildEffectAvailability (called
  inside GraphCanvas's diagnostics useEffect) always returns a new object,
  so setGraphDiagnosticsState was called on every effect run, creating a
  cycle: setGraphDiagnosticsState  graphDiagnosticsState new
  diagnosticsSnapshot new  pluginContext new  handleInteractionStateChange
  new  GraphCanvas re-renders  diagnostics effect fires again.

  Fix: before calling setGraphDiagnosticsState, compare the incoming
  diagnostics field-by-field against the last accepted snapshot via a ref
  (lastDiagnosticsRef). All effectAvailability entries, edgeClasses.updatedAt,
  structureLayer.cacheKey/lastDrawAt/enabled, and distanceVisual identity
  must differ for a state update to proceed. The ref approach avoids
  scheduling a re-render at all, rather than bailing out inside a functional
  updater after the render has already been committed.

Loop 2 — scrubberTime churn (GraphWorkspace.tsx + GraphWorkspaceShell.tsx):
  TimelinePanel.tsx calls onTimeChange(defaultTime) whenever its useEffect
  re-runs. React 18 concurrent mode re-runs effects with structurally-new
  Date objects for the same timestamp when speculative renders discard
  useMemo caches, causing setScrubberTime to be called repeatedly with a
  new Date that has the same millisecond value — triggering temporalState
  churn, the diagnostics effect, and eventually the same loop.

  Fix: wrap setScrubberTime in an onTimeChange useCallback that compares the
  incoming time's millisecond value against the last sent value (via
  lastScrubberMsRef). Redundant calls with the same timestamp are dropped
  before reaching setScrubberTime. Stable useCallback identity also prevents
  TimelinePanel's useEffect from re-firing solely due to prop identity churn.

Both fixes applied to GraphWorkspace.tsx and identically to
GraphWorkspaceShell.tsx which has the same pattern.

Verified:
- npm run dev: 0 'Maximum update depth exceeded' errors
- Temporal panel renders with real data in dev mode
- Effects and Neighbors panels unaffected
- npm run build + preview: identical behavior, 0 errors
- All 42 frontend tests pass (34 graph-workspace, 1 graph-store, 7 plugin-registry)
2026-08-05 16:01:18 +05:30
Sameer6305 aa85535d47 fixed copilot review 2026-08-04 16:45:33 +05:30
Sameer6305 7d936d0f7c fix(explorer): write diff highlights to displayGraph as well as store graph
fixed qodo review

applyDiffHighlight/clearDiffHighlight were writing baseColor only to
graphStore.graph (the store singleton), but Sigma is constructed with
displayGraphRef.current and the nodeReducer reads attributes from that
instance. When the display graph is a derived copy (aggregated,
focused, or grouped view), the store write has no effect on the
currently-rendered frame -- sigma.scheduleRefresh() flushes the
reducer over the display graph, which did not receive the mutation.

Fix: introduce writeBaseColor(context, nodeId, color) which writes to
BOTH the store graph (so the color propagates into the next display
graph rebuild via aggregateDisplayGraph's shallow attribute copy) AND
context.displayGraph (the live Graph instance currently bound to
Sigma, so the change is visible in the current frame immediately).

The dg !== graph guard skips the display-graph write when they happen
to be the same object (non-aggregated full view), avoiding a redundant
double-write in that case.

Original baseColor is still captured from the store graph (the
authoritative source, since aggregateDisplayGraph copies from there),
so restore remains correct across all view modes.
2026-08-04 16:32:04 +05:30
Sameer6305 47531d8365 feat(explorer): add temporal diff comparison to the Temporal panel
Adds a Compare section to the existing Temporal Context panel
(temporalOverlayPlugin.tsx) that lets a user pick two ISO timestamps
and diff the graph's node set between them via the existing, previously
UI-less GET /api/temporal/diff backend route.

- New temporalDiffState.ts: typed fetch wrapper (fetchTemporalDiff)
  matching the route's added_nodes/removed_nodes response shape.
- Diff results recolor affected nodes via baseColor (not
  ringColor/haloColor -- traced and confirmed those are only read by
  the sigma reducer for hovered/selected/path-state nodes and are
  silently discarded for default-state nodes).
- Validates both timestamps are present, parseable, and from < to
  before firing a request.
- Distinct idle/loading/error/empty/success states -- an empty diff
  (no changes) is rendered as its own state, not as an error.
- Cancels any in-flight request via AbortController on re-submission
  and on unmount; restores each highlighted node's original baseColor
  (captured before overwrite, not cleared to a fallback default) on
  both paths.
- Reuses existing theme tokens (GRAPH_THEME.palette.semantic[2],
  ui.control.dangerText) and existing button/input/loading/error
  visual patterns already established in this same plugins directory
  and in GraphInspectorPanel.tsx, rather than introducing new styling.
2026-08-04 15:57:53 +05:30
Mohd Kaif 86f115d200 docs: surface pip install command at the top of README and docs (#828)
Makes the install command the first actionable thing visible on both
the README and docs landing page, ahead of the fold.
2026-08-04 12:55:51 +05:30
Mohd Kaif 9c5c3c4ce0 Merge pull request #826 from Sameer6305/fix/785-provenance-storage-failure-tests
test(provenance): expand storage failure regression coverage (#785)
2026-08-04 12:13:41 +05:30
Mohd Kaif 26a5c4a1fb Merge branch 'main' into fix/785-provenance-storage-failure-tests 2026-08-04 12:08:23 +05:30
Mohd Kaif 2adc67e25e Merge pull request #827 from semantica-agi/feat/825-provenance-prov-o-compliance
Provenance: close PROV-O compliance gaps and high-stakes trust blockers
2026-08-04 11:33:42 +05:30
Sameer6305 e9e05fedbd fix(provenance): reset in-memory chain state on clear 2026-08-04 00:01:50 +05:30
KaifAhmad1 0a8330cbb0 fix(provenance): address code review findings on PR #827
- SQLiteStorage now migrates an existing (pre-#825) provenance.db in place
  via ALTER TABLE ADD COLUMN for any columns introduced since, instead of
  only ever running CREATE TABLE IF NOT EXISTS. Without this, opening an
  older database with the new code would break on the first insert/select
  since the row width and _row_to_entry's fixed indices grew past the old
  schema. Added test_migrates_pre_existing_old_schema_database.

- verify_chain() now also checks that sequence_id is exactly the
  predecessor's plus one (no gap, no duplicate), in addition to the existing
  previous_checksum comparison. Hardens against the narrow case where
  compute_checksum()'s deliberate exclusion of entity_id could let two
  distinct rows coincidentally share a checksum, which alone would let a
  checksum-only comparison miss a gap. Added
  test_verify_chain_detects_tampered_sequence_gap.

- Explorer provenance route: edge ids now include direction
  (f"{src}-{eid}-{direction}") to match the seen_edges dedupe key, which
  already included it. The same (src, target) pair can legitimately appear
  in both the upstream and downstream chains (cycles/overlap), and without
  this the two edges collided on the same id. Added
  test_add_chain_edges_ids_distinguish_direction.

- Removed an unused `Any` import in parse_provenance.py.
2026-08-03 22:52:34 +05:30