fix: add missing port/out and adapter/out sources; fix .gitignore and .dockerignore
- .gitignore had bare 'out/' matching source directories; changed to '/out/' - All 45 files under trueref-domain/port/out and trueref-adapters/.../out were silently excluded from the initial commit - Added .dockerignore to exclude data/, runtime/, logs/ from build context
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package com.trueref.domain.port.out;
|
||||
|
||||
import com.trueref.domain.model.Chunk;
|
||||
import com.trueref.domain.model.ChunkId;
|
||||
import com.trueref.domain.model.ChunkVersion;
|
||||
import com.trueref.domain.model.Embedding;
|
||||
import com.trueref.domain.model.SearchHit;
|
||||
import com.trueref.domain.model.SearchScope;
|
||||
import com.trueref.domain.model.VersionId;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Combined chunk metadata + vector + lexical store. The Lucene adapter implements this with a
|
||||
* single index that holds both BM25-tokenized text and an HNSW kNN field.
|
||||
*/
|
||||
public interface ChunkStore {
|
||||
|
||||
/** Looks up an existing chunk by content hash so callers can avoid re-embedding. */
|
||||
Optional<Chunk> findByContentHash(String contentHash);
|
||||
|
||||
/** Persists a brand-new chunk and its embedding. Idempotent on {@code contentHash}. */
|
||||
Chunk upsertChunk(Chunk chunk, Embedding embedding);
|
||||
|
||||
/** Adds membership rows linking chunks to a version's source files. */
|
||||
void linkChunks(Collection<ChunkVersion> links);
|
||||
|
||||
/** Removes all chunk-version links for the given version. */
|
||||
void unlinkVersion(VersionId versionId);
|
||||
|
||||
/** Returns the set of {@link ChunkId}s reachable from the given version. */
|
||||
Set<ChunkId> chunkIdsForVersion(VersionId versionId);
|
||||
|
||||
/** BM25 lexical search restricted to the given scope. */
|
||||
List<SearchHit> bm25Search(String queryText, SearchScope scope, int topK);
|
||||
|
||||
/** HNSW dense kNN search restricted to the given scope. */
|
||||
List<SearchHit> denseSearch(float[] queryVector, SearchScope scope, int topK);
|
||||
|
||||
/** Forces a Lucene commit. Called at the end of an indexing job. */
|
||||
void commit();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.trueref.domain.port.out;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Parses a single source file into a list of code chunks. Implementations use tree-sitter for
|
||||
* supported languages and a sliding-window text splitter as fallback.
|
||||
*/
|
||||
public interface CodeParser {
|
||||
|
||||
/** True if at least one grammar can handle the given file. */
|
||||
boolean supports(Path file);
|
||||
|
||||
List<ParsedChunk> parse(Path file, String repoRelativePath);
|
||||
|
||||
record ParsedChunk(
|
||||
String content,
|
||||
String language,
|
||||
@Nullable String symbol,
|
||||
int startLine,
|
||||
int endLine) {}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.trueref.domain.port.out;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/** Persistent on-disk cache of embedding vectors keyed by content hash. */
|
||||
public interface EmbeddingCache {
|
||||
|
||||
Optional<float[]> get(String contentHash);
|
||||
|
||||
void put(String contentHash, float[] vector);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.trueref.domain.port.out;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Generates dense embedding vectors. Implementations are expected to be batch-friendly. */
|
||||
public interface EmbeddingService {
|
||||
|
||||
/** Embedding dimensionality of the underlying model. */
|
||||
int dimension();
|
||||
|
||||
/** Embeds a batch of texts. Implementations should call out to GPU through a semaphore. */
|
||||
List<float[]> embed(List<String> texts);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.trueref.domain.port.out;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/** Git operations the application needs. Implementations: JGit. */
|
||||
public interface GitClient {
|
||||
|
||||
/** Clones a remote repository to a local directory (no-op if it already exists). */
|
||||
void cloneRepo(String remoteUrl, Path localPath);
|
||||
|
||||
/** Runs git fetch on an existing local repository (no-op for non-managed repos that lack a remote). */
|
||||
void fetch(Path localPath);
|
||||
|
||||
/** Lists tags currently present in the local repository. */
|
||||
List<TagInfo> listTags(Path localPath);
|
||||
|
||||
/** Resolves a ref (tag or branch) to its commit SHA. */
|
||||
String resolveRef(Path localPath, String ref);
|
||||
|
||||
/**
|
||||
* Checks the given ref out into a transient worktree directory the caller is responsible for
|
||||
* cleaning up. Returns the worktree root.
|
||||
*/
|
||||
Path checkoutWorktree(Path repoPath, String ref);
|
||||
|
||||
/** Removes a worktree previously created by {@link #checkoutWorktree}. */
|
||||
void removeWorktree(Path repoPath, Path worktree);
|
||||
|
||||
/**
|
||||
* Returns the list of files changed between two commits, classified by status.
|
||||
*
|
||||
* @param baseRef the previously indexed tag/commit (may be null when there is no parent)
|
||||
*/
|
||||
List<DiffEntry> diff(Path repoPath, @Nullable String baseRef, String headRef);
|
||||
|
||||
record TagInfo(String name, String commitSha, long taggerEpochSeconds) {}
|
||||
|
||||
record DiffEntry(String path, @Nullable String oldPath, ChangeType change) {
|
||||
|
||||
public enum ChangeType {
|
||||
ADDED,
|
||||
MODIFIED,
|
||||
DELETED,
|
||||
RENAMED,
|
||||
COPIED
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.trueref.domain.port.out;
|
||||
|
||||
import com.trueref.domain.model.IngestionJob;
|
||||
import com.trueref.domain.model.JobId;
|
||||
import com.trueref.domain.model.JobLogEvent;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* In-process pub/sub bus for ingestion observability events. The application publishes; REST/SSE
|
||||
* adapters subscribe to fan events out to UI clients.
|
||||
*/
|
||||
public interface JobEventBus {
|
||||
|
||||
void publishJob(IngestionJob job);
|
||||
|
||||
void publishLog(JobLogEvent event);
|
||||
|
||||
AutoCloseable subscribeJobs(Consumer<IngestionJob> listener);
|
||||
|
||||
AutoCloseable subscribeLogs(JobId jobId, Consumer<JobLogEvent> listener);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.trueref.domain.port.out;
|
||||
|
||||
import com.trueref.domain.model.IngestionJob;
|
||||
import com.trueref.domain.model.JobId;
|
||||
import com.trueref.domain.model.JobStage;
|
||||
import com.trueref.domain.model.JobStatus;
|
||||
import com.trueref.domain.model.RepositoryId;
|
||||
import com.trueref.domain.model.VersionId;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/** Persistence SPI for ingestion jobs and their stages. */
|
||||
public interface JobStore {
|
||||
|
||||
IngestionJob save(IngestionJob job);
|
||||
|
||||
Optional<IngestionJob> findById(JobId id);
|
||||
|
||||
List<IngestionJob> findRunning();
|
||||
|
||||
List<IngestionJob> find(
|
||||
@Nullable RepositoryId repoId, @Nullable VersionId versionId, @Nullable JobStatus status, int limit);
|
||||
|
||||
void updateStatus(
|
||||
JobId id,
|
||||
JobStatus status,
|
||||
@Nullable Instant startedAt,
|
||||
@Nullable Instant finishedAt);
|
||||
|
||||
void upsertStage(JobStage stage);
|
||||
|
||||
/**
|
||||
* Marks all RUNNING and QUEUED jobs as FAILED and their RUNNING stages as FAILED.
|
||||
* Called once on startup to clear jobs that were interrupted by a previous crash or restart.
|
||||
*
|
||||
* @return the number of jobs that were transitioned to FAILED
|
||||
*/
|
||||
int failStaleJobs(Instant finishedAt);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.trueref.domain.port.out;
|
||||
|
||||
import com.trueref.domain.model.Repository;
|
||||
import com.trueref.domain.model.RepositoryId;
|
||||
import com.trueref.domain.model.Version;
|
||||
import com.trueref.domain.model.VersionId;
|
||||
import com.trueref.domain.model.VersionStatus;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/** Persistence SPI for repositories and their versions. */
|
||||
public interface RepositoryStore {
|
||||
|
||||
Repository save(Repository repo);
|
||||
|
||||
Optional<Repository> findById(RepositoryId id);
|
||||
|
||||
Optional<Repository> findByName(String name);
|
||||
|
||||
List<Repository> findAll();
|
||||
|
||||
void delete(RepositoryId id);
|
||||
|
||||
Version saveVersion(Version version);
|
||||
|
||||
Optional<Version> findVersion(VersionId id);
|
||||
|
||||
Optional<Version> findVersionByTag(RepositoryId repoId, String tag);
|
||||
|
||||
List<Version> findVersionsByRepo(RepositoryId repoId);
|
||||
|
||||
List<Version> findVersionsByStatus(@Nullable RepositoryId repoId, VersionStatus status);
|
||||
|
||||
void updateVersionStatus(VersionId id, VersionStatus status, @Nullable String errorMessage);
|
||||
|
||||
/** Updates {@code chunkCount} and sets {@code indexedAt = now()}. */
|
||||
void markVersionIndexed(VersionId id, int chunkCount);
|
||||
|
||||
/**
|
||||
* Marks all INDEXING versions as FAILED.
|
||||
* Called once on startup to clear versions whose indexing job was interrupted.
|
||||
*
|
||||
* @return the number of versions transitioned to FAILED
|
||||
*/
|
||||
int failStaleIndexingVersions(String errorMessage);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.trueref.domain.port.out;
|
||||
|
||||
import com.trueref.domain.model.SearchHit;
|
||||
import java.util.List;
|
||||
|
||||
/** Cross-encoder reranker. Re-scores a candidate list against a query. */
|
||||
public interface RerankerService {
|
||||
|
||||
/** Returns the candidates re-sorted by cross-encoder score, with score replaced. */
|
||||
List<SearchHit> rerank(String query, List<SearchHit> candidates);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Driven ports — SPIs implemented by adapters (persistence, vector store, embedding service, git,
|
||||
* parser, etc.) and called by the application layer.
|
||||
*/
|
||||
@org.jspecify.annotations.NullMarked
|
||||
package com.trueref.domain.port.out;
|
||||
Reference in New Issue
Block a user