When the index changes
When a workspace changes, zvec-grep must answer a harder question than “can I search the files?” It must decide which stored evidence is still current, which files need new representations, and how a search should behave while updates or failures are in progress. Understanding this lifecycle lets you choose an execution mode, interpret fresh and possibly_stale results, and separate a completed command from a complete, current index.
An indexed result is a claim about a relationship between two states: the workspace as it exists now and the representation captured earlier. If those states diverge, relevance and freshness can come apart. A result may still be useful because it points to a real entity, yet no longer describe the current source. Zvec-grep makes that tension visible through file metadata, refresh policies, daemon coordination, and status information instead of treating an index as permanently trustworthy after its first build.
A file moves through explicit states
The lifecycle begins with a scan of the configured workspace scope. Zvec-grep compares what the scanner sees with the file records already held by the index. The comparison uses file size and modification time as quick signals and uses content hashes when it needs to distinguish a real change from metadata that changed without changing the content. From that comparison, a file can be classified as added, modified, pending, deleted, or unchanged.
An unchanged file is not re-embedded merely because a search has occurred. Reusing its stored entities and vectors saves work and preserves the representation that was already committed. A file whose content has changed becomes a candidate for replacement. A newly discovered file is added. A file that is no longer present in the scanned scope is deleted from the index. A pending file is one whose indexing has not reached a successful indexed state, including a file left incomplete by an earlier failure.
The difference between modified and unchanged is more precise than a timestamp check alone. A file can have the same size and modification time as its stored record and be reused when its content hash is available. If the quick metadata does not settle the question, zvec-grep computes a hash and compares it with the stored value. This avoids rebuilding content that is effectively the same while still detecting a change that matters to retrieval. The operation is selective: the index updates what the scanner and comparison identify, not every file on every pass.
When a file needs indexing, the stored representation is replaced as a unit. Zvec-grep reads the current source, runs the appropriate extractor, prepares the fragments, obtains vectors, and commits the text, metadata, ranges, and vectors together. Before the new content is committed, the file can be marked dirty or pending so the stored status does not falsely imply that the previous representation is current. Once the replacement succeeds, the record receives an indexed time, an entity count, and any truncation information returned by the embedding step.
Deletion has a different transition. The index removes the file’s stored documents and metadata rather than retaining old evidence under a path that no longer belongs to the active scan. This matters for negative reasoning. If a search result disappears because a file was deleted from the workspace, that is different from a result disappearing because the file remains present but has not yet completed its update. The persisted file state gives the operator a way to distinguish those cases.
Failure interrupts the normal path. Reading a source can fail, extraction can fail, an embedding request can fail, or storage can reject a commit. Zvec-grep records the file as failed or pending with an error rather than presenting an empty successful replacement.