chore: establish local platform baseline

This commit is contained in:
Codex Local
2026-08-26 06:41:54 +08:00
commit 29bdf4900f
575 changed files with 95644 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
package retrieval
import (
"context"
"encoding/json"
"fmt"
"data-terminal-cloud/internal/developmentembedding"
"github.com/jackc/pgx/v5"
)
type Memory struct {
MemoryID string `json:"memory_id"`
MemoryVersionID string `json:"memory_version_id"`
VersionNo int64 `json:"version_no"`
Content string `json:"-"`
SourceRefs json.RawMessage `json:"source_refs"`
Sensitivity string `json:"sensitivity"`
Relevance float64 `json:"relevance"`
}
// SelectMemoryForContext fixes the tenant and subject boundary in the SQL
// itself. Callers cannot supply a free-form filter. The first production
// baseline admits only normal-sensitivity memories into a voice context.
func SelectMemoryForContext(ctx context.Context, tx pgx.Tx, tenantID, subjectID, query string, limit int) ([]Memory, error) {
queryVector := developmentembedding.Literal(developmentembedding.Vector(query))
return SelectMemoryForContextVector(ctx, tx, tenantID, subjectID, queryVector, limit)
}
// SelectMemoryForContextVector uses a vector generated before the caller's
// transaction. This keeps production embedding network calls out of the
// conversation creation transaction while retaining the SQL tenant, subject,
// consent and lifecycle boundaries below.
func SelectMemoryForContextVector(ctx context.Context, tx pgx.Tx, tenantID, subjectID, queryVector string, limit int) ([]Memory, error) {
if limit < 1 || limit > 10 {
return nil, fmt.Errorf("memory retrieval limit must be between 1 and 10")
}
if queryVector == "" {
return nil, fmt.Errorf("memory retrieval vector is required")
}
rows, err := tx.Query(ctx, `
SELECT cm.public_id::text,mv.public_id::text,mv.version_no,mv.content,mv.source_refs,
cm.sensitivity,1-(mi.embedding <=> $3::vector) AS relevance
FROM memory_index_entry mi
JOIN curated_memory cm ON cm.id=mi.memory_id AND cm.tenant_id=mi.tenant_id AND cm.subject_id=mi.subject_id
JOIN memory_version mv ON mv.id=mi.memory_version_id AND mv.memory_id=cm.id
WHERE mi.tenant_id=$1::uuid AND mi.subject_id=$2::uuid
AND mi.index_type='pgvector' AND mi.status='ACTIVE' AND mi.embedding IS NOT NULL
AND cm.status='ACTIVE' AND cm.current_version_id=mv.id
AND cm.sensitivity='normal'
AND (cm.valid_from IS NULL OR cm.valid_from<=now())
AND (cm.valid_to IS NULL OR cm.valid_to>now())
AND EXISTS(SELECT 1 FROM consent_record cr
WHERE cr.tenant_id=cm.tenant_id AND cr.subject_id=cm.subject_id
AND cr.consent_type='personalized_memory' AND cr.withdrawn_at IS NULL
AND (cr.expires_at IS NULL OR cr.expires_at>now()))
ORDER BY mi.embedding <=> $3::vector,mv.confirmed_at DESC,mv.id
LIMIT $4`, tenantID, subjectID, queryVector, limit)
if err != nil {
return nil, fmt.Errorf("query eligible memory: %w", err)
}
defer rows.Close()
items := make([]Memory, 0, limit)
for rows.Next() {
var item Memory
if err := rows.Scan(&item.MemoryID, &item.MemoryVersionID, &item.VersionNo, &item.Content, &item.SourceRefs, &item.Sensitivity, &item.Relevance); err != nil {
return nil, fmt.Errorf("scan eligible memory: %w", err)
}
items = append(items, item)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate eligible memory: %w", err)
}
return items, nil
}
@@ -0,0 +1,81 @@
package retrieval
import (
"context"
"os"
"strings"
"testing"
"data-terminal-cloud/internal/developmentembedding"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
)
func TestSelectMemoryForContextAppliesEligibilityBoundary(t *testing.T) {
databaseURL := os.Getenv("TEST_DATABASE_URL")
if databaseURL == "" {
t.Skip("TEST_DATABASE_URL is not set")
}
ctx := context.Background()
pool, err := pgxpool.New(ctx, databaseURL)
if err != nil {
t.Fatal(err)
}
defer pool.Close()
type fixture struct{ memoryID, memoryPublicID, versionID, versionPublicID, sensitivity, content string }
fixtures := []fixture{
{uuid.NewString(), uuid.NewString(), uuid.NewString(), uuid.NewString(), "normal", "长者在河边小学教书。"},
{uuid.NewString(), uuid.NewString(), uuid.NewString(), uuid.NewString(), "sensitive", "合成敏感记忆不得进入语音上下文。"},
}
defer func() {
for _, item := range fixtures {
_, _ = pool.Exec(ctx, `DELETE FROM memory_index_entry WHERE memory_id=$1::uuid`, item.memoryID)
_, _ = pool.Exec(ctx, `UPDATE curated_memory SET current_version_id=NULL WHERE id=$1::uuid`, item.memoryID)
_, _ = pool.Exec(ctx, `DELETE FROM memory_version WHERE memory_id=$1::uuid`, item.memoryID)
_, _ = pool.Exec(ctx, `DELETE FROM curated_memory WHERE id=$1::uuid`, item.memoryID)
}
}()
for _, item := range fixtures {
if _, err := pool.Exec(ctx, `
INSERT INTO curated_memory(id,public_id,tenant_id,subject_id,status,sensitivity,valid_from)
VALUES($1::uuid,$2::uuid,'10000000-0000-0000-0000-000000000001','10000000-0000-0000-0000-000000000401','ACTIVE',$3,now())`,
item.memoryID, item.memoryPublicID, item.sensitivity); err != nil {
t.Fatal(err)
}
if _, err := pool.Exec(ctx, `
INSERT INTO memory_version(id,public_id,memory_id,version_no,content,source_refs,confirmed_by,content_digest)
VALUES($1::uuid,$2::uuid,$3::uuid,1,$4,'[{"type":"integration"}]','10000000-0000-0000-0000-000000000101',$5)`,
item.versionID, item.versionPublicID, item.memoryID, item.content, strings.Repeat("b", 64)); err != nil {
t.Fatal(err)
}
if _, err := pool.Exec(ctx, `UPDATE curated_memory SET current_version_id=$1::uuid WHERE id=$2::uuid`, item.versionID, item.memoryID); err != nil {
t.Fatal(err)
}
if _, err := pool.Exec(ctx, `
INSERT INTO memory_index_entry(tenant_id,subject_id,memory_id,memory_version_id,index_type,embedding,status,provider_ref)
VALUES('10000000-0000-0000-0000-000000000001','10000000-0000-0000-0000-000000000401',$1::uuid,$2::uuid,'pgvector',$3::vector,'ACTIVE','integration')`,
item.memoryID, item.versionID, developmentembedding.Literal(developmentembedding.Vector(item.content))); err != nil {
t.Fatal(err)
}
}
tx, err := pool.Begin(ctx)
if err != nil {
t.Fatal(err)
}
defer tx.Rollback(ctx)
if _, err := SelectMemoryForContext(ctx, tx, "10000000-0000-0000-0000-000000000001", "10000000-0000-0000-0000-000000000401", "河边小学", 0); err == nil {
t.Fatal("invalid retrieval limit was accepted")
}
items, err := SelectMemoryForContext(ctx, tx, "10000000-0000-0000-0000-000000000001", "10000000-0000-0000-0000-000000000401", "河边小学", 5)
if err != nil || len(items) != 1 {
t.Fatalf("eligible memories=%+v err=%v", items, err)
}
if items[0].MemoryID != fixtures[0].memoryPublicID || items[0].MemoryVersionID != fixtures[0].versionPublicID || items[0].Content != fixtures[0].content || items[0].Sensitivity != "normal" {
t.Fatalf("retrieved memory=%+v", items[0])
}
otherSubjectItems, err := SelectMemoryForContext(ctx, tx, "10000000-0000-0000-0000-000000000001", "10000000-0000-0000-0000-000000000402", "河边小学", 5)
if err != nil || len(otherSubjectItems) != 0 {
t.Fatalf("cross-subject memories=%+v err=%v", otherSubjectItems, err)
}
}