Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .tegami/asset-owned-catalog-chunk-values.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
packages:
orgmemory: patch
subject: Move catalog and chunk values to Knowledge Asset
---

# Move catalog and chunk values to Knowledge Asset

## Improvements

Knowledge Asset now owns its catalog projection, normalized text-chunk value,
and PostgreSQL vector encoding, so Retrieval and other consumers depend on the
domain that persists and publishes those values.
3 changes: 3 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ replaced. Asset promotion receives validated normalized facts through a Source
Ledger-owned request, and Asset publication advances the current source
revision through a Source Ledger-owned `MANDATORY` service inside the existing
publication transaction; Asset consumes no Source Ledger entity or repository.
Asset also owns catalog projections, normalized chunk values, and the pgvector
encoding used by its chunk store; Retrieval and Asset Registry consume those
root-package Asset contracts rather than owning persistence-facing DTOs.
Asset and Retrieval remain explicitly open while their remaining
cross-owned persistence and orchestration seams are replaced by intentional
APIs.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.orgmemory.api.knowledge;

import com.orgmemory.api.security.CurrentActorProvider;
import com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogItem;
import com.orgmemory.core.knowledge.asset.KnowledgeCatalogItem;
import com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogService;
import io.swagger.v3.oas.annotations.Operation;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
import com.orgmemory.core.authorization.RelationshipTupleWriteResult;
import com.orgmemory.core.authorization.ResourceRef;
import com.orgmemory.core.shared.error.BusinessValidationException;
import com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogItem;
import com.orgmemory.core.knowledge.asset.KnowledgeCatalogItem;
import com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogService;
import com.orgmemory.core.knowledge.retrieval.QueryEmbeddingPort;
import com.orgmemory.core.knowledge.retrieval.PermissionAwareKnowledgeSearch;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import com.orgmemory.core.knowledge.retrieval.EmbeddingProfileSpec;
import com.orgmemory.core.knowledge.asset.KnowledgeAssetRef;
import com.orgmemory.core.knowledge.asset.KnowledgeChunkDraftAssembler;
import com.orgmemory.core.knowledge.retrieval.KnowledgeTextChunk;
import com.orgmemory.core.knowledge.asset.KnowledgeTextChunk;
import com.orgmemory.core.knowledge.asset.KnowledgeAssetPublicationService;
import com.orgmemory.core.knowledge.asset.PublishKnowledgeAssetCommand;
import com.orgmemory.core.knowledge.storage.ObjectKey;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.orgmemory.core.assetregistry;

import com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogItem;
import com.orgmemory.core.knowledge.asset.KnowledgeCatalogItem;
import com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogService;
import com.orgmemory.core.organization.CurrentActor;
import java.time.Instant;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.orgmemory.core.knowledge.asset;

import com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogItem;

import java.util.Optional;
import java.util.Collection;
import java.util.List;
Expand All @@ -20,7 +18,7 @@ Optional<KnowledgeAssetVersion> findByKnowledgeAssetIdAndStatus(
UUID knowledgeAssetId, KnowledgeAssetVersionStatus status);

@Query("""
select new com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogItem(
select new com.orgmemory.core.knowledge.asset.KnowledgeCatalogItem(
asset.id,
version.id,
version.versionNumber,
Expand All @@ -46,7 +44,7 @@ List<KnowledgeCatalogItem> findCurrentCatalogItems(
@Param("assetIds") Collection<UUID> assetIds);

@Query("""
select new com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogItem(
select new com.orgmemory.core.knowledge.asset.KnowledgeCatalogItem(
asset.id,
version.id,
version.versionNumber,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.orgmemory.core.knowledge.retrieval;
package com.orgmemory.core.knowledge.asset;

import com.orgmemory.core.permission.KnowledgeClassification;
import java.util.UUID;

/** Asset-owned catalog projection for one current or historical version. */
public record KnowledgeCatalogItem(
UUID knowledgeAssetId,
UUID knowledgeVersionId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.orgmemory.core.knowledge.asset;

import com.orgmemory.core.knowledge.retrieval.KnowledgeTextChunk;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.orgmemory.core.knowledge.asset;

import com.orgmemory.core.knowledge.retrieval.EmbeddingProfileRef;
import com.orgmemory.core.knowledge.retrieval.PgVectorLiteral;

import java.sql.Types;
import java.time.Instant;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.orgmemory.core.knowledge.retrieval;
package com.orgmemory.core.knowledge.asset;

import java.util.Objects;
import java.util.List;
import java.util.Objects;

/** Asset-owned normalized text and source-location facts for one chunk. */
public record KnowledgeTextChunk(
String content,
Integer startPage,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.orgmemory.core.knowledge.retrieval;
package com.orgmemory.core.knowledge.asset;

import com.orgmemory.graphrag.model.FloatVector;

/** PostgreSQL vector encoding used by Asset chunk persistence and Retrieval queries. */
public final class PgVectorLiteral {

private PgVectorLiteral() {}
Expand Down Expand Up @@ -31,7 +32,8 @@ public static FloatVector parse(String encoded) {
float[] values = new float[parts.length];
for (int index = 0; index < parts.length; index++) {
if (parts[index].isBlank()) {
throw new IllegalArgumentException("pgvector literal components must not be empty");
throw new IllegalArgumentException(
"pgvector literal components must not be empty");
}
values[index] = Float.parseFloat(parts[index]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
*
* <p>Graph consumers now resolve immutable asset, version, and chunk facts through an Asset-owned
* query boundary. Promotion and source publication use Source Ledger-owned contracts rather than
* its entities or repositories. This nested module remains open while direct Retrieval and
* external Asset Registry dependencies are replaced with intentional APIs.
* its entities or repositories. Catalog projections, normalized text chunks, and pgvector
* encoding are Asset-owned values consumed by Retrieval and Asset Registry. This nested module
* remains open while its remaining direct Retrieval behavior is replaced with intentional APIs.
*/
@org.springframework.modulith.ApplicationModule(
type = org.springframework.modulith.ApplicationModule.Type.OPEN)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.orgmemory.core.knowledge.retrieval;

import com.orgmemory.core.knowledge.asset.KnowledgeCatalogItem;
import com.orgmemory.core.knowledge.asset.KnowledgeAssetVersionRepository;
import com.orgmemory.core.organization.CurrentActor;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.orgmemory.core.knowledge.retrieval;

import com.orgmemory.core.knowledge.retrieval.QueryEmbedding;
import com.orgmemory.core.knowledge.asset.PgVectorLiteral;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
* query embeddings, and projection identity.
*
* <p>This nested module also implements the source-owned visibility and embedding-profile ports.
* Graph indexing now resolves profiles through the registry instead of profile persistence. The
* module remains open while its broader sibling-module consumer surface is replaced by
* Graph indexing now resolves profiles through the registry instead of profile persistence.
* Catalog, text-chunk, and vector-literal values belong to Asset and are consumed here one way.
* The module remains open while its broader sibling-module consumer surface is replaced by
* intentional interfaces during the Knowledge module-closing phase.
*/
@org.springframework.modulith.ApplicationModule(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,40 @@ void knowledgeAssetConsumesOnlySourceLedgerPublicContracts() {
consumedTypes);
}

@Test
void knowledgeAssetOwnsItsCatalogAndChunkValues() {
var assetClasses = new ClassFileImporter()
.importPackages("com.orgmemory.core.knowledge.asset");
var expectedOwnedTypes = Set.of(
"com.orgmemory.core.knowledge.asset.KnowledgeCatalogItem",
"com.orgmemory.core.knowledge.asset.KnowledgeTextChunk",
"com.orgmemory.core.knowledge.asset.PgVectorLiteral");

noClasses()
.that()
.resideInAPackage("com.orgmemory.core.knowledge.asset..")
.should()
.dependOnClassesThat()
.haveFullyQualifiedName(
"com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogItem")
.orShould()
.dependOnClassesThat()
.haveFullyQualifiedName(
"com.orgmemory.core.knowledge.retrieval.KnowledgeTextChunk")
.orShould()
.dependOnClassesThat()
.haveFullyQualifiedName(
"com.orgmemory.core.knowledge.retrieval.PgVectorLiteral")
.check(assetClasses);

var ownedTypes = assetClasses.stream()
.map(type -> type.getName())
.filter(expectedOwnedTypes::contains)
.collect(TreeSet::new, Set::add, Set::addAll);

assertEquals(expectedOwnedTypes, ownedTypes);
}

@Test
void knowledgeGraphIsAClosedNestedModule() {
var graph = modules.getModuleByName("knowledge.graph").orElseThrow();
Expand Down Expand Up @@ -660,8 +694,6 @@ void knowledgeRetrievalTemporaryOpenBoundaryDoesNotGainNewConsumers() {
"com.orgmemory.core.assistant.AssistantService",
"com.orgmemory.core.knowledge.asset.KnowledgeAssetLifecycleService",
"com.orgmemory.core.knowledge.asset.KnowledgeAssetPublicationOutbox",
"com.orgmemory.core.knowledge.asset.KnowledgeAssetVersionRepository",
"com.orgmemory.core.knowledge.asset.KnowledgeChunkDraftAssembler",
"com.orgmemory.core.knowledge.asset.KnowledgeChunkProjectionStore",
"com.orgmemory.core.knowledge.asset.PublishKnowledgeAssetCommand",
"com.orgmemory.core.knowledge.connector.ConnectorEmbeddingResult",
Expand All @@ -678,14 +710,11 @@ void knowledgeRetrievalTemporaryOpenBoundaryDoesNotGainNewConsumers() {
Set.of(
"com.orgmemory.core.knowledge.retrieval.EmbeddingProfileRef",
"com.orgmemory.core.knowledge.retrieval.EmbeddingProfileRegistry",
"com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogItem",
"com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogService",
"com.orgmemory.core.knowledge.retrieval.KnowledgeEvidenceScopeResolver",
"com.orgmemory.core.knowledge.retrieval.KnowledgeProjectionNamespaces",
"com.orgmemory.core.knowledge.retrieval.KnowledgeRetrievalUnavailableException",
"com.orgmemory.core.knowledge.retrieval.KnowledgeTextChunk",
"com.orgmemory.core.knowledge.retrieval.PermissionAwareKnowledgeSearch",
"com.orgmemory.core.knowledge.retrieval.PgVectorLiteral",
"com.orgmemory.core.knowledge.retrieval.ResolvedKnowledgeEvidenceScope",
"com.orgmemory.core.knowledge.retrieval.RetrievedKnowledgeEvidence",
"com.orgmemory.core.knowledge.retrieval.SecureKnowledgeRetrievalStore",
Expand Down Expand Up @@ -730,12 +759,15 @@ void knowledgeAssetTemporaryOpenBoundaryDoesNotGainNewConsumers() {

assertEquals(
Set.of(
"com.orgmemory.core.assetregistry.AssetDeliveryService",
"com.orgmemory.core.assetregistry.CapabilityPackService",
"com.orgmemory.core.knowledge.retrieval.AuthorizationResourceDirectory",
"com.orgmemory.core.knowledge.graph.GraphIndexingCoordinator",
"com.orgmemory.core.knowledge.graph.GraphIndexJobQueue",
"com.orgmemory.core.knowledge.graph.GraphIndexLifecycleService",
"com.orgmemory.core.knowledge.retrieval.KnowledgeCatalogService",
"com.orgmemory.core.knowledge.retrieval.KnowledgeEvidenceScopeResolver",
"com.orgmemory.core.knowledge.retrieval.SecureKnowledgeRetrievalStore",
"com.orgmemory.core.knowledge.graph.KnowledgeGraphCurationService",
"com.orgmemory.core.knowledge.connector.ConnectorReconciler",
"com.orgmemory.core.knowledge.connector.ConnectorSourceRevisionCoordinator"),
Expand All @@ -752,7 +784,9 @@ void knowledgeAssetTemporaryOpenBoundaryDoesNotGainNewConsumers() {
"com.orgmemory.core.knowledge.asset.KnowledgeAssetVersion",
"com.orgmemory.core.knowledge.asset.KnowledgeAssetVersionGraphRef",
"com.orgmemory.core.knowledge.asset.KnowledgeAssetVersionRepository",
"com.orgmemory.core.knowledge.asset.KnowledgeCatalogItem",
"com.orgmemory.core.knowledge.asset.KnowledgeChunkDraft",
"com.orgmemory.core.knowledge.asset.PgVectorLiteral",
"com.orgmemory.core.knowledge.asset.PublishKnowledgeAssetCommand"),
consumedInternalTypes);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.orgmemory.core.knowledge.asset;

import com.orgmemory.core.knowledge.retrieval.KnowledgeTextChunk;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.orgmemory.core.knowledge.retrieval;
package com.orgmemory.core.knowledge.asset;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;

import com.orgmemory.core.knowledge.asset.KnowledgeCatalogItem;
import com.orgmemory.core.knowledge.asset.KnowledgeAssetVersionRepository;
import com.orgmemory.core.organization.CurrentActor;
import com.orgmemory.core.permission.KnowledgeClassification;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ temporary open-owner documentation were fixed, while the duplicate challenge
record request was answered with the existing Fable 5 verdict. Direct audit
confirmed all three review threads resolved before merge.

## Current Pull Request Gates
## Thirty-second Pull Request Evidence

- The Source Ledger-owned promotion request carries every validated normalized
fact needed to create an immutable Asset version; the Asset adapter no longer
Expand All @@ -920,3 +920,46 @@ mirrored domain pairs; all 37 release-policy tests passed under Node 24.15;
and the terminating repository-wide `clean test` completed successfully in
1m02s across 99 tasks. Mechanical package, zero-byte, migration-name, diff,
zero Asset-to-Source-Ledger-persistence-import, and 14-path scope checks passed.

PR #233 merged as `9e2e7248` after all required CI checks passed. CodeRabbit
was rate limited, and direct inspection confirmed zero inline comments,
reviews, or review threads before merge.

## Current Pull Request Gates

- `KnowledgeCatalogItem`, `KnowledgeTextChunk`, and `PgVectorLiteral` move from
Retrieval to their Asset owner without changing their data shape or behavior.
- Asset persistence and assembly no longer depend on those Retrieval types;
Retrieval, Asset Registry, API, and Worker consumers now import Asset-owned
root contracts, making the dependency direction one way for these values.
- JPQL constructor projections target the new Asset FQN, vector parsing tests
move with the utility, and catalog/chunk tests retain their previous coverage.
- A failing-first ArchUnit regression proves the three old Asset-to-Retrieval
edges existed, then prevents them from returning; exact temporary-boundary
assertions pin the reduced Retrieval consumer/type surface and expanded
Asset-owned surface.
- Full Core/API/Worker tests pass and the code PR remains below 100 files before
the remaining embedding-profile and projection-namespace seams are handled.

Pre-PR verification completed: the new ownership test failed first against the
three Retrieval-owned values, then repository compilation passed in 14s and
focused moved-value/catalog/chunk/Modulith tests passed in 29s. The combined
full Core/API/Worker gate passed in 5m48s; the documentation operating-model
check passed across 446 Markdown files and 8 mirrored domain pairs; all 37
release-policy tests passed under Node 24.15; and the terminating repository
`clean test` completed successfully in 58s across 99 tasks. Mechanical package,
zero-byte, migration-name, diff, zero old-Retrieval-value-import, and 25-path
scope checks passed.

After merging current `origin/main`, the focused moved-value and Modulith tests
passed again in 7s; the documentation check passed across 451 Markdown files;
all 37 release-policy tests passed again under Node 24.15; and the final PR diff
contains 21 paths because Git recognizes the four package moves as renames.

CodeRabbit review found that the ownership regression proved only absence of
the three legacy Retrieval names. The test now also asserts the exact three
Asset-owned class names, so deletion or relocation outside Asset fails alongside
any reintroduced legacy dependency.

Review-fix verification passed: the focused positive/negative ownership test in
25s, full `:core:test` in 1m43s, and the 451-file documentation check.