Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26207d93ef | ||
|
|
42871f2e47 | ||
|
|
6ea1d4b729 | ||
|
|
c6d1ebf36f | ||
|
|
25d8d6d219 | ||
|
|
6cbef9af41 | ||
|
|
2fe9802e5a | ||
|
|
0882df3ad2 | ||
|
|
0acbe53fad | ||
|
|
e634bb946a | ||
|
|
c7ad996cae | ||
|
|
a065382512 |
@@ -533,7 +533,7 @@ func main() {
|
|||||||
log.Printf("interaction principal history loaded: %d utterances", len(recentUserHistory))
|
log.Printf("interaction principal history loaded: %d utterances", len(recentUserHistory))
|
||||||
}
|
}
|
||||||
conversationHistory = append(conversationHistory, recentUserHistory...)
|
conversationHistory = append(conversationHistory, recentUserHistory...)
|
||||||
personalMemory := interactiondomain.CompilePersonalMemory(conversationHistory)
|
gen2Context := interactiondomain.BuildGen2Context(conversationHistory)
|
||||||
if !creativeUserRequest && locationReply == "" {
|
if !creativeUserRequest && locationReply == "" {
|
||||||
if continuation := interactiondomain.ContinueLocalSearch(effectiveTaskMessage, conversationHistory); continuation != "" {
|
if continuation := interactiondomain.ContinueLocalSearch(effectiveTaskMessage, conversationHistory); continuation != "" {
|
||||||
continuationMessage = continuation
|
continuationMessage = continuation
|
||||||
@@ -829,7 +829,7 @@ func main() {
|
|||||||
reply, backed := renderResearchReply(searchQuery, result, researchErr)
|
reply, backed := renderResearchReply(searchQuery, result, researchErr)
|
||||||
if !backed && cognitiveAvailable {
|
if !backed && cognitiveAvailable {
|
||||||
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
||||||
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, part, personalMemory.ContextText(), cognitive.TaskMeaning{
|
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, part, gen2Context.Text, cognitive.TaskMeaning{
|
||||||
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
||||||
})
|
})
|
||||||
cancelAnswer()
|
cancelAnswer()
|
||||||
@@ -869,7 +869,7 @@ func main() {
|
|||||||
canGenerateTextReply := shouldGenerateNonMutatingTextDirective(semantic, routePlan, helpPath, creativeRequest) && planningReply == deterministicReply
|
canGenerateTextReply := shouldGenerateNonMutatingTextDirective(semantic, routePlan, helpPath, creativeRequest) && planningReply == deterministicReply
|
||||||
if (planningReply == "" && needsCognition && semantic.Interpretation.SpeechAct == interaction.SpeechActQuestion || canGenerateTextReply) && !hasChatRoute(routePlan, chatRouteResearch) && !creativeRequest {
|
if (planningReply == "" && needsCognition && semantic.Interpretation.SpeechAct == interaction.SpeechActQuestion || canGenerateTextReply) && !hasChatRoute(routePlan, chatRouteResearch) && !creativeRequest {
|
||||||
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
answerCtx, cancelAnswer := context.WithTimeout(r.Context(), 12*time.Second)
|
||||||
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, effectiveTaskMessage, personalMemory.ContextText(), cognitive.TaskMeaning{
|
answer, answerErr := cognitiveClient.AnswerStableKnowledge(answerCtx, session, effectiveTaskMessage, gen2Context.Text, cognitive.TaskMeaning{
|
||||||
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
SpeechAct: string(semantic.Interpretation.SpeechAct), CapabilityHints: toCapabilityKinds(semantic.CapabilityHints), RequestedOutcome: semantic.Interpretation.RequestedOutcome, InformationRequestKind: semantic.InformationRequestKind, ConfidenceMillis: semantic.Interpretation.ConfidenceMillis,
|
||||||
})
|
})
|
||||||
cancelAnswer()
|
cancelAnswer()
|
||||||
@@ -992,7 +992,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
if strings.TrimSpace(planningReply) != "" {
|
if strings.TrimSpace(planningReply) != "" {
|
||||||
reviewContext, cancelReview := context.WithTimeout(r.Context(), 12*time.Second)
|
reviewContext, cancelReview := context.WithTimeout(r.Context(), 12*time.Second)
|
||||||
reviewedReply, reviewErr := cognitiveClient.ReviewResponse(reviewContext, session, utterance.Content, planningReply, personalMemory.ContextText(), cognitive.TaskMeaning{
|
reviewedReply, reviewErr := cognitiveClient.ReviewResponse(reviewContext, session, utterance.Content, planningReply, gen2Context.Text, cognitive.TaskMeaning{
|
||||||
SpeechAct: string(semantic.Interpretation.SpeechAct),
|
SpeechAct: string(semantic.Interpretation.SpeechAct),
|
||||||
CapabilityHints: toCapabilityKinds(semantic.CapabilityHints),
|
CapabilityHints: toCapabilityKinds(semantic.CapabilityHints),
|
||||||
RequestedOutcome: semantic.Interpretation.RequestedOutcome,
|
RequestedOutcome: semantic.Interpretation.RequestedOutcome,
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package capability
|
||||||
|
|
||||||
|
type IntelligencePath string
|
||||||
|
|
||||||
|
const (
|
||||||
|
PathRule IntelligencePath = "RULE"
|
||||||
|
PathReflex IntelligencePath = "REFLEX"
|
||||||
|
PathSkill IntelligencePath = "SKILL"
|
||||||
|
PathSmallLocal IntelligencePath = "SMALL_LOCAL"
|
||||||
|
PathStrongLocal IntelligencePath = "STRONG_LOCAL"
|
||||||
|
PathExternal IntelligencePath = "EXTERNAL"
|
||||||
|
PathResearch IntelligencePath = "RESEARCH"
|
||||||
|
PathTeam IntelligencePath = "TEAM"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StrategyRequest struct {
|
||||||
|
RequiredQuality int64
|
||||||
|
PreferLowLatency bool
|
||||||
|
CostBudgetMicros int64
|
||||||
|
RiskClass string
|
||||||
|
FreshnessRequired bool
|
||||||
|
CostOfError int64
|
||||||
|
}
|
||||||
|
type StrategyDecision struct {
|
||||||
|
Path IntelligencePath
|
||||||
|
Reason string
|
||||||
|
Escalate bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r StrategyRequest) Select() StrategyDecision {
|
||||||
|
if r.RiskClass == "HIGH" || r.CostOfError >= 800 {
|
||||||
|
return StrategyDecision{Path: PathStrongLocal, Reason: "high consequence requires deeper reasoning", Escalate: true}
|
||||||
|
}
|
||||||
|
if r.RequiredQuality <= 500 && r.CostBudgetMicros > 0 {
|
||||||
|
return StrategyDecision{Path: PathRule, Reason: "bounded low-risk path"}
|
||||||
|
}
|
||||||
|
if r.PreferLowLatency {
|
||||||
|
return StrategyDecision{Path: PathReflex, Reason: "latency preference with later escalation"}
|
||||||
|
}
|
||||||
|
return StrategyDecision{Path: PathSkill, Reason: "validated reusable strategy"}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package capability
|
||||||
|
|
||||||
|
type ReflexID string
|
||||||
|
type ReflexLifecycle string
|
||||||
|
type ReflexKind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ReflexCandidate ReflexLifecycle = "CANDIDATE"
|
||||||
|
ReflexValidating ReflexLifecycle = "VALIDATING"
|
||||||
|
ReflexActive ReflexLifecycle = "ACTIVE"
|
||||||
|
ReflexDegraded ReflexLifecycle = "DEGRADED"
|
||||||
|
ReflexStale ReflexLifecycle = "STALE"
|
||||||
|
ReflexSuspended ReflexLifecycle = "SUSPENDED"
|
||||||
|
ReflexRetired ReflexLifecycle = "RETIRED"
|
||||||
|
ReflexDeterministicCode ReflexKind = "DETERMINISTIC_CODE"
|
||||||
|
ReflexRule ReflexKind = "RULE"
|
||||||
|
ReflexWorkflow ReflexKind = "WORKFLOW"
|
||||||
|
ReflexQueryTemplate ReflexKind = "QUERY_TEMPLATE"
|
||||||
|
ReflexSmallModelChain ReflexKind = "SMALL_MODEL_CHAIN"
|
||||||
|
ReflexBoundedAdapter ReflexKind = "BOUNDED_ADAPTER_OPERATION"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ShadowPolicy struct {
|
||||||
|
Enabled bool
|
||||||
|
SampleRateMillis int64
|
||||||
|
ComparatorRef string
|
||||||
|
MaxShadowCostMicros *int64
|
||||||
|
EligibleErrorCostClasses []string
|
||||||
|
}
|
||||||
|
type RevalidationPolicy struct {
|
||||||
|
MaxAgeMillis *int64
|
||||||
|
RevalidateOnDependencyRevisionChange bool
|
||||||
|
RevalidateOnWorldVersionChange bool
|
||||||
|
RevalidateAfterFailureCount *int64
|
||||||
|
RevalidateAfterCorrectionCount *int64
|
||||||
|
SampleAuditRateMillis *int64
|
||||||
|
}
|
||||||
|
type Reflex struct {
|
||||||
|
ID ReflexID
|
||||||
|
PrincipalID string
|
||||||
|
SourceSkillRef SkillID
|
||||||
|
CreatedAt int64
|
||||||
|
}
|
||||||
|
type ReflexRevision struct {
|
||||||
|
ReflexID ReflexID
|
||||||
|
Revision int64
|
||||||
|
SourceSkillRevision int64
|
||||||
|
Kind ReflexKind
|
||||||
|
Applicability ApplicabilitySpec
|
||||||
|
ImplementationRef string
|
||||||
|
ImplementationVersion string
|
||||||
|
ArtifactDigest string
|
||||||
|
DependencyRefs []string
|
||||||
|
ValidationEvidenceRefs []SkillEvidenceRef
|
||||||
|
KnownFailureExperienceRefs []SkillEvidenceRef
|
||||||
|
Shadow ShadowPolicy
|
||||||
|
Revalidation RevalidationPolicy
|
||||||
|
LastValidatedAt int64
|
||||||
|
Lifecycle ReflexLifecycle
|
||||||
|
RecordedAt int64
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package capability
|
||||||
|
|
||||||
|
type SkillID string
|
||||||
|
type SkillRevision struct {
|
||||||
|
SkillID SkillID
|
||||||
|
Revision int64
|
||||||
|
Description string
|
||||||
|
Applicability ApplicabilitySpec
|
||||||
|
ImplementationRef string
|
||||||
|
ImplementationVersion string
|
||||||
|
DependencyRefs []string
|
||||||
|
SupportingExperienceRefs []SkillEvidenceRef
|
||||||
|
KnownFailureExperienceRefs []SkillEvidenceRef
|
||||||
|
ValidationEvidenceRefs []SkillEvidenceRef
|
||||||
|
QualityAssessmentRefs []string
|
||||||
|
EnvironmentVersionConstraints []string
|
||||||
|
LastValidatedAt int64
|
||||||
|
Lifecycle SkillLifecycleStatus
|
||||||
|
SupersedesRevision int64
|
||||||
|
RecordedAt int64
|
||||||
|
}
|
||||||
|
type ApplicabilitySpec struct {
|
||||||
|
RequiredContextBindings []string
|
||||||
|
PreferredContextBindings []string
|
||||||
|
ExcludedContextBindings []string
|
||||||
|
RequiredWorldKinds []string
|
||||||
|
VersionConstraints []string
|
||||||
|
InputConditions []string
|
||||||
|
MinimumEvidenceFreshness string
|
||||||
|
}
|
||||||
|
type Skill struct {
|
||||||
|
ID SkillID
|
||||||
|
PrincipalID string
|
||||||
|
Name string
|
||||||
|
CreatedAt int64
|
||||||
|
}
|
||||||
@@ -11,14 +11,24 @@ import (
|
|||||||
var ErrInvalidContextBudget = errors.New("context budget must be positive")
|
var ErrInvalidContextBudget = errors.New("context budget must be positive")
|
||||||
|
|
||||||
type ContextCandidate struct {
|
type ContextCandidate struct {
|
||||||
Excerpt ContextExcerpt
|
Excerpt ContextExcerpt
|
||||||
Relevance int
|
Relevance int
|
||||||
|
Lane string
|
||||||
|
ContextScopeRef string
|
||||||
|
FreshnessState string
|
||||||
|
Negative bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContextCompileInput struct {
|
type ContextCompileInput struct {
|
||||||
Candidates []ContextCandidate
|
Candidates []ContextCandidate
|
||||||
DataPolicy capability.DataPolicy
|
DataPolicy capability.DataPolicy
|
||||||
MaxBytes int
|
MaxBytes int
|
||||||
|
TaskRef string
|
||||||
|
FocusFrameRef string
|
||||||
|
ContextScopeRef string
|
||||||
|
FreshnessRequirement string
|
||||||
|
RiskClass string
|
||||||
|
TokenBudget int
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContextOmission struct {
|
type ContextOmission struct {
|
||||||
@@ -30,6 +40,24 @@ type ContextBundle struct {
|
|||||||
Excerpts []ContextExcerpt
|
Excerpts []ContextExcerpt
|
||||||
Omissions []ContextOmission
|
Omissions []ContextOmission
|
||||||
Bytes int
|
Bytes int
|
||||||
|
Trace ContextAssemblyTrace
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContextAssemblyTrace struct {
|
||||||
|
Included []ContextExcerptID
|
||||||
|
Excluded []ContextOmission
|
||||||
|
Coverage string
|
||||||
|
CompilerVersion string
|
||||||
|
}
|
||||||
|
|
||||||
|
type IterativeRetrievalRequest struct {
|
||||||
|
Query string
|
||||||
|
RemainingBytes int
|
||||||
|
Pass int
|
||||||
|
}
|
||||||
|
type IterativeRetrievalResponse struct {
|
||||||
|
Candidates []ContextCandidate
|
||||||
|
Exhausted bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompileContext deterministically selects permitted, relevant excerpts for a
|
// CompileContext deterministically selects permitted, relevant excerpts for a
|
||||||
@@ -54,6 +82,10 @@ func CompileContext(input ContextCompileInput) (ContextBundle, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
seen[excerpt.ID] = struct{}{}
|
seen[excerpt.ID] = struct{}{}
|
||||||
|
if input.ContextScopeRef != "" && candidate.ContextScopeRef != input.ContextScopeRef {
|
||||||
|
bundle.Omissions = append(bundle.Omissions, ContextOmission{ID: excerpt.ID, Reason: "context_scope"})
|
||||||
|
continue
|
||||||
|
}
|
||||||
reason := permittedContextReason(excerpt, input.DataPolicy)
|
reason := permittedContextReason(excerpt, input.DataPolicy)
|
||||||
if reason != "" {
|
if reason != "" {
|
||||||
bundle.Omissions = append(bundle.Omissions, ContextOmission{ID: excerpt.ID, Reason: reason})
|
bundle.Omissions = append(bundle.Omissions, ContextOmission{ID: excerpt.ID, Reason: reason})
|
||||||
@@ -70,7 +102,11 @@ func CompileContext(input ContextCompileInput) (ContextBundle, error) {
|
|||||||
}
|
}
|
||||||
bundle.Excerpts = append(bundle.Excerpts, excerpt)
|
bundle.Excerpts = append(bundle.Excerpts, excerpt)
|
||||||
bundle.Bytes += bytes
|
bundle.Bytes += bytes
|
||||||
|
bundle.Trace.Included = append(bundle.Trace.Included, excerpt.ID)
|
||||||
}
|
}
|
||||||
|
bundle.Trace.Excluded = append([]ContextOmission(nil), bundle.Omissions...)
|
||||||
|
bundle.Trace.CompilerVersion = "context-compiler-v2-additive"
|
||||||
|
bundle.Trace.Coverage = "BOUNDED"
|
||||||
return bundle, nil
|
return bundle, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package cognitive_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/capability"
|
||||||
|
"git.cin.su/m/Assistant/contracts/cognitive"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestContextCompilerV2TraceAndBudgetRemainDeterministic(t *testing.T) {
|
||||||
|
b, err := cognitive.CompileContext(cognitive.ContextCompileInput{MaxBytes: 5, DataPolicy: capability.DataPolicyLocalOnly, TaskRef: "task", FocusFrameRef: "frame", ContextScopeRef: "company-a", Candidates: []cognitive.ContextCandidate{{Excerpt: cognitive.ContextExcerpt{ID: "a", Text: "123", Sensitivity: cognitive.SensitivityPrivateAllowed}, ContextScopeRef: "company-a", Relevance: 10}, {Excerpt: cognitive.ContextExcerpt{ID: "b", Text: "123456", Sensitivity: cognitive.SensitivityPrivateAllowed}, ContextScopeRef: "company-b", Relevance: 100}}})
|
||||||
|
if err != nil || len(b.Excerpts) != 1 || len(b.Trace.Excluded) != 1 {
|
||||||
|
t.Fatalf("bundle=%#v err=%v", b, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.cin.su/m/Assistant/contracts/secrets"
|
||||||
|
"git.cin.su/m/Assistant/platform/ids"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SettingDefinitionID ids.StableID
|
||||||
|
type SettingAssignmentID ids.StableID
|
||||||
|
type ConfigurationRevision ids.Revision
|
||||||
|
type ValueType string
|
||||||
|
type ResolutionMode string
|
||||||
|
type SettingLifecycle string
|
||||||
|
type SettingSource string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ValueString ValueType = "STRING"
|
||||||
|
ValueInteger ValueType = "INTEGER"
|
||||||
|
ValueBoolean ValueType = "BOOLEAN"
|
||||||
|
ValueSecretRef ValueType = "SECRET_REF"
|
||||||
|
ResolutionMostSpecific ResolutionMode = "MOST_SPECIFIC_WINS"
|
||||||
|
ResolutionFirstHuman ResolutionMode = "FIRST_EXPLICIT_HUMAN_WINS"
|
||||||
|
ResolutionMergeList ResolutionMode = "MERGE_LIST"
|
||||||
|
SettingActive SettingLifecycle = "ACTIVE"
|
||||||
|
SettingDeprecated SettingLifecycle = "DEPRECATED"
|
||||||
|
SettingRetired SettingLifecycle = "RETIRED"
|
||||||
|
SourceHumanDirective SettingSource = "HUMAN_DIRECTIVE"
|
||||||
|
SourceMigrated SettingSource = "MIGRATED_CONFIG"
|
||||||
|
SourceSkillDefault SettingSource = "SKILL_DEFAULT"
|
||||||
|
SourceSystemDefault SettingSource = "SYSTEM_DEFAULT"
|
||||||
|
SourceGovernedChange SettingSource = "GOVERNED_CHANGE"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SettingDefinition struct {
|
||||||
|
ID SettingDefinitionID
|
||||||
|
OwnerNamespace string
|
||||||
|
StableKey string
|
||||||
|
Revision ConfigurationRevision
|
||||||
|
ValueType ValueType
|
||||||
|
DefaultValue string
|
||||||
|
Sensitivity string
|
||||||
|
Lifecycle SettingLifecycle
|
||||||
|
RecordedAtUnixMillis int64
|
||||||
|
}
|
||||||
|
type ScopeSelector struct {
|
||||||
|
PrincipalRef string
|
||||||
|
RequiredContextBindings []string
|
||||||
|
ActivityRef string
|
||||||
|
SkillRef string
|
||||||
|
TaskRef string
|
||||||
|
SessionRef string
|
||||||
|
TemporaryOverride bool
|
||||||
|
}
|
||||||
|
type SettingAssignment struct {
|
||||||
|
ID SettingAssignmentID
|
||||||
|
PrincipalID string
|
||||||
|
DefinitionRef string
|
||||||
|
DefinitionRevision ConfigurationRevision
|
||||||
|
Revision ConfigurationRevision
|
||||||
|
Selector ScopeSelector
|
||||||
|
TypedValue string
|
||||||
|
SecretRef *secrets.CredentialRef
|
||||||
|
EffectiveFromUnixMillis int64
|
||||||
|
EffectiveUntilUnixMillis *int64
|
||||||
|
Source SettingSource
|
||||||
|
SourceRef string
|
||||||
|
Lifecycle SettingLifecycle
|
||||||
|
RecordedAtUnixMillis int64
|
||||||
|
}
|
||||||
|
type EffectiveSetting struct {
|
||||||
|
DefinitionRef string
|
||||||
|
Value string
|
||||||
|
WinningAssignmentRef string
|
||||||
|
ResolutionTrace []string
|
||||||
|
}
|
||||||
|
type BootstrapConfig struct {
|
||||||
|
NodeIdentity string
|
||||||
|
ControlDatabaseLocator string
|
||||||
|
RootSecretResolverLocator string
|
||||||
|
RecoveryLocator string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d SettingDefinition) Validate() error {
|
||||||
|
if d.ID == "" || d.OwnerNamespace == "" || d.StableKey == "" || !ids.Revision(d.Revision).Valid() || d.ValueType == "" || d.Lifecycle == "" || d.RecordedAtUnixMillis < 1 {
|
||||||
|
return fmt.Errorf("invalid setting definition")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (a SettingAssignment) Validate() error {
|
||||||
|
if a.ID == "" || a.PrincipalID == "" || a.DefinitionRef == "" || !ids.Revision(a.Revision).Valid() || a.Source == "" || a.Lifecycle == "" || a.RecordedAtUnixMillis < 1 {
|
||||||
|
return fmt.Errorf("invalid setting assignment")
|
||||||
|
}
|
||||||
|
if a.SecretRef != nil && a.TypedValue != "" {
|
||||||
|
return fmt.Errorf("secret assignment must not contain typed value")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package epistemics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.cin.su/m/Assistant/contracts/world"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VolatilityMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
VolatilityImmutable VolatilityMode = "IMMUTABLE"
|
||||||
|
VolatilityVersionBound VolatilityMode = "VERSION_BOUND"
|
||||||
|
VolatilityVerySlow VolatilityMode = "VERY_SLOW"
|
||||||
|
VolatilitySlow VolatilityMode = "SLOW"
|
||||||
|
VolatilityMedium VolatilityMode = "MEDIUM"
|
||||||
|
VolatilityFast VolatilityMode = "FAST"
|
||||||
|
VolatilityEphemeral VolatilityMode = "EPHEMERAL"
|
||||||
|
VolatilityCustom VolatilityMode = "CUSTOM"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TemporalApplicability struct {
|
||||||
|
ObservedAtUnixMillis int64
|
||||||
|
ValidFromUnixMillis *int64
|
||||||
|
ValidUntilUnixMillis *int64
|
||||||
|
LastVerifiedAtUnixMillis *int64
|
||||||
|
Volatility VolatilitySpec
|
||||||
|
VersionBindings []world.VersionBinding
|
||||||
|
}
|
||||||
|
type VolatilitySpec struct {
|
||||||
|
Mode VolatilityMode
|
||||||
|
ExpectedChangeIntervalMillis *int64
|
||||||
|
RevalidateAfterMillis *int64
|
||||||
|
HardStaleAfterMillis *int64
|
||||||
|
InvalidateOnVersionChange bool
|
||||||
|
RevalidationPolicyRef string
|
||||||
|
}
|
||||||
|
type FreshnessAssessmentState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
FreshnessAssessmentCurrent FreshnessAssessmentState = "CURRENT"
|
||||||
|
FreshnessAssessmentAcceptable FreshnessAssessmentState = "ACCEPTABLE"
|
||||||
|
FreshnessAssessmentAging FreshnessAssessmentState = "AGING"
|
||||||
|
FreshnessAssessmentStale FreshnessAssessmentState = "STALE"
|
||||||
|
FreshnessAssessmentVersionMismatch FreshnessAssessmentState = "VERSION_MISMATCH"
|
||||||
|
FreshnessAssessmentHistoricalOnly FreshnessAssessmentState = "HISTORICAL_ONLY"
|
||||||
|
FreshnessAssessmentUnknown FreshnessAssessmentState = "UNKNOWN"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FreshnessAssessment struct {
|
||||||
|
SourceKnowledgeRef string
|
||||||
|
TaskRef string
|
||||||
|
State FreshnessAssessmentState
|
||||||
|
Reason string
|
||||||
|
AgeMillis int64
|
||||||
|
VersionMatchState string
|
||||||
|
RevalidationAttemptRef string
|
||||||
|
AssessedAtUnixMillis int64
|
||||||
|
}
|
||||||
|
type RevalidationRequest struct {
|
||||||
|
ID string
|
||||||
|
SourceKnowledgeRef string
|
||||||
|
TaskRef string
|
||||||
|
RequiredVersionRefs []world.SemanticReference
|
||||||
|
RequestedAtUnixMillis int64
|
||||||
|
}
|
||||||
|
type RevalidationResponse struct {
|
||||||
|
RequestID string
|
||||||
|
Assessment FreshnessAssessment
|
||||||
|
NewEvidenceRefs []EvidenceRef
|
||||||
|
CompletedAtUnixMillis int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v VolatilitySpec) Validate() error {
|
||||||
|
if v.Mode == "" {
|
||||||
|
return fmt.Errorf("volatility mode is required")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (t TemporalApplicability) Validate() error {
|
||||||
|
if t.ObservedAtUnixMillis < 1 {
|
||||||
|
return fmt.Errorf("observed time is required")
|
||||||
|
}
|
||||||
|
return t.Volatility.Validate()
|
||||||
|
}
|
||||||
|
func (a FreshnessAssessment) Validate() error {
|
||||||
|
if a.SourceKnowledgeRef == "" || a.TaskRef == "" || a.State == "" || a.AgeMillis < 0 || a.AssessedAtUnixMillis < 1 {
|
||||||
|
return fmt.Errorf("freshness assessment is incomplete")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package epistemics
|
package epistemics
|
||||||
|
|
||||||
|
import "git.cin.su/m/Assistant/platform/ids"
|
||||||
|
|
||||||
type BeliefState string
|
type BeliefState string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -9,19 +11,27 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Observation struct {
|
type Observation struct {
|
||||||
ID ObservationID
|
ID ObservationID
|
||||||
SourceSnapshot SourceSnapshotID
|
SourceSnapshot SourceSnapshotID
|
||||||
Excerpt SourceExcerptID
|
Excerpt SourceExcerptID
|
||||||
Text string
|
Text string
|
||||||
ObservedAt int64
|
ObservedAt int64
|
||||||
|
PrincipalID string
|
||||||
|
ContextScopeRef string
|
||||||
|
ObservationKind string
|
||||||
|
Payload string
|
||||||
|
ExtractorRef string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Claim struct {
|
type Claim struct {
|
||||||
ID ClaimID
|
ID ClaimID
|
||||||
Statement string
|
Statement string
|
||||||
ObservationID ObservationID
|
ObservationID ObservationID
|
||||||
CitationID CitationID
|
CitationID CitationID
|
||||||
Verification VerificationState
|
Verification VerificationState
|
||||||
|
PropositionID ids.ID
|
||||||
|
RevisedFrom *ClaimID
|
||||||
|
RecordedAtUnixMillis int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type Belief struct {
|
type Belief struct {
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ type HelpMethodKind string
|
|||||||
type OutcomeClass string
|
type OutcomeClass string
|
||||||
type ReflectionTriggerKind string
|
type ReflectionTriggerKind string
|
||||||
type ReflectionCandidateState string
|
type ReflectionCandidateState string
|
||||||
|
type PropositionKind string
|
||||||
|
type BeliefAssessmentState string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VerificationUnverified VerificationState = "UNVERIFIED"
|
VerificationUnverified VerificationState = "UNVERIFIED"
|
||||||
@@ -73,6 +75,12 @@ const (
|
|||||||
ReflectionCandidateEvaluating ReflectionCandidateState = "EVALUATING"
|
ReflectionCandidateEvaluating ReflectionCandidateState = "EVALUATING"
|
||||||
ReflectionCandidateSuperseded ReflectionCandidateState = "SUPERSEDED"
|
ReflectionCandidateSuperseded ReflectionCandidateState = "SUPERSEDED"
|
||||||
ReflectionCandidateResolved ReflectionCandidateState = "RESOLVED"
|
ReflectionCandidateResolved ReflectionCandidateState = "RESOLVED"
|
||||||
|
PropositionWorldFacet PropositionKind = "WORLD_FACET"
|
||||||
|
PropositionWorldRelation PropositionKind = "WORLD_RELATION"
|
||||||
|
PropositionOwnerDefined PropositionKind = "OWNER_DEFINED"
|
||||||
|
PropositionTextual PropositionKind = "TEXTUAL"
|
||||||
|
BeliefAssessmentCurrent BeliefAssessmentState = "CURRENT"
|
||||||
|
BeliefAssessmentSuperseded BeliefAssessmentState = "SUPERSEDED"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SystemExpectation records what Domovoy expected a meaningful help path to
|
// SystemExpectation records what Domovoy expected a meaningful help path to
|
||||||
@@ -114,6 +122,15 @@ type ExperienceRecord struct {
|
|||||||
VerificationEvidence []EvidenceRef
|
VerificationEvidence []EvidenceRef
|
||||||
ConfidenceMillis int64
|
ConfidenceMillis int64
|
||||||
RecordedAtUnixMillis int64
|
RecordedAtUnixMillis int64
|
||||||
|
ProblemStatement string
|
||||||
|
AttemptRef string
|
||||||
|
WhyAttempted string
|
||||||
|
ApplicabilityConditions []string
|
||||||
|
ContextScopeRef string
|
||||||
|
EpisodeRef string
|
||||||
|
GoalRef string
|
||||||
|
TaskRef string
|
||||||
|
WhySucceededOrFailed string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReflectionCandidate records that broader reflection may be warranted.
|
// ReflectionCandidate records that broader reflection may be warranted.
|
||||||
@@ -134,3 +151,34 @@ type ReflectionCandidate struct {
|
|||||||
ClaimedBy string
|
ClaimedBy string
|
||||||
ClaimExpiresAtUnixMillis int64
|
ClaimExpiresAtUnixMillis int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Proposition struct {
|
||||||
|
ID ids.ID
|
||||||
|
Kind PropositionKind
|
||||||
|
SubjectRef string
|
||||||
|
PredicateRef string
|
||||||
|
ObjectValue string
|
||||||
|
ObjectRef string
|
||||||
|
Qualifiers []string
|
||||||
|
TextFallback string
|
||||||
|
}
|
||||||
|
|
||||||
|
type BeliefAssessment struct {
|
||||||
|
ID ids.ID
|
||||||
|
ClaimID ClaimID
|
||||||
|
Revision ids.Revision
|
||||||
|
State BeliefAssessmentState
|
||||||
|
ConfidenceMillis int64
|
||||||
|
EvidenceRefs []EvidenceRef
|
||||||
|
AssessedAtUnixMillis int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type EpisodeID ids.ID
|
||||||
|
type Episode struct {
|
||||||
|
ID EpisodeID
|
||||||
|
PrincipalID string
|
||||||
|
ExperienceRefs []ExperienceRecordID
|
||||||
|
Summary string
|
||||||
|
Outcome OutcomeClass
|
||||||
|
RecordedAtUnixMillis int64
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package self
|
||||||
|
|
||||||
|
type BenchmarkCaseRef string
|
||||||
|
type PersonalBenchmark struct {
|
||||||
|
ID string
|
||||||
|
PrincipalID string
|
||||||
|
ApprovedCaseRefs []BenchmarkCaseRef
|
||||||
|
GoalProfile []string
|
||||||
|
PreferenceEvidenceRefs []SemanticReference
|
||||||
|
RecordedAt int64
|
||||||
|
}
|
||||||
|
type BenchmarkEvaluation struct {
|
||||||
|
CaseRef BenchmarkCaseRef
|
||||||
|
Path string
|
||||||
|
QualityMillis int64
|
||||||
|
ReliabilityMillis int64
|
||||||
|
LatencyMillis int64
|
||||||
|
CostMicros int64
|
||||||
|
CorrectionCount int64
|
||||||
|
EvidenceRefs []SemanticReference
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e BenchmarkEvaluation) Valid() bool {
|
||||||
|
return e.CaseRef != "" && len(e.EvidenceRefs) > 0 && e.QualityMillis >= 0 && e.ReliabilityMillis >= 0 && e.CorrectionCount >= 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package self
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type AssessmentID string
|
||||||
|
type LearningLedgerEntryID string
|
||||||
|
type AssessmentState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
AssessmentCandidate AssessmentState = "CANDIDATE"
|
||||||
|
AssessmentConfirmed AssessmentState = "CONFIRMED"
|
||||||
|
AssessmentMonitoring AssessmentState = "MONITORING"
|
||||||
|
AssessmentResolved AssessmentState = "RESOLVED"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CompetenceAssessment struct {
|
||||||
|
ID AssessmentID
|
||||||
|
PrincipalID string
|
||||||
|
SubjectRef SemanticReference
|
||||||
|
Revision uint64
|
||||||
|
ContextMatcher []string
|
||||||
|
QualityMillis int64
|
||||||
|
ReliabilityMillis int64
|
||||||
|
ConfidenceMillis int64
|
||||||
|
EvidenceRefs []SemanticReference
|
||||||
|
LastValidatedAt int64
|
||||||
|
AssessedAt int64
|
||||||
|
SupersedesRef *SemanticReference
|
||||||
|
}
|
||||||
|
type WeaknessPattern struct {
|
||||||
|
ID AssessmentID
|
||||||
|
PrincipalID string
|
||||||
|
Revision uint64
|
||||||
|
PatternKey string
|
||||||
|
ContextMatcher []string
|
||||||
|
FailureMode string
|
||||||
|
DetectionEvidenceRefs []SemanticReference
|
||||||
|
State AssessmentState
|
||||||
|
RecordedAt int64
|
||||||
|
}
|
||||||
|
type DependencyAssessment struct {
|
||||||
|
ID AssessmentID
|
||||||
|
SubjectRef SemanticReference
|
||||||
|
DependencyRef SemanticReference
|
||||||
|
ImpactClass string
|
||||||
|
CurrentEffect string
|
||||||
|
EvidenceRefs []SemanticReference
|
||||||
|
AssessedAt int64
|
||||||
|
}
|
||||||
|
type ImprovementNeed struct {
|
||||||
|
ID AssessmentID
|
||||||
|
PrincipalID string
|
||||||
|
SubjectRef SemanticReference
|
||||||
|
ProblemSummary string
|
||||||
|
EvidenceRefs []SemanticReference
|
||||||
|
ExpectedBenefit string
|
||||||
|
Priority int
|
||||||
|
State string
|
||||||
|
CreatedAt int64
|
||||||
|
}
|
||||||
|
type LearningLedgerEntry struct {
|
||||||
|
ID LearningLedgerEntryID
|
||||||
|
PrincipalID string
|
||||||
|
ImprovementNeedRef *SemanticReference
|
||||||
|
ObservedProblem string
|
||||||
|
EvidenceRefs []SemanticReference
|
||||||
|
Diagnosis string
|
||||||
|
Hypothesis string
|
||||||
|
ProposedChangeRef SemanticReference
|
||||||
|
ExpectedImprovement string
|
||||||
|
ActualEvaluationRefs []SemanticReference
|
||||||
|
DevelopmentGateRef *SemanticReference
|
||||||
|
BeforeVersionRefs []SemanticReference
|
||||||
|
AfterVersionRefs []SemanticReference
|
||||||
|
Decision string
|
||||||
|
SideEffects []string
|
||||||
|
RollbackRef *SemanticReference
|
||||||
|
RecordedAt int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a CompetenceAssessment) Validate() error {
|
||||||
|
if a.ID == "" || a.PrincipalID == "" || !a.SubjectRef.Valid() || a.Revision < 1 || a.ConfidenceMillis < 0 || a.ConfidenceMillis > 1000 || len(a.EvidenceRefs) == 0 || a.AssessedAt < 1 {
|
||||||
|
return fmt.Errorf("competence requires evidence")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (l LearningLedgerEntry) Validate() error {
|
||||||
|
if l.ID == "" || l.PrincipalID == "" || l.ObservedProblem == "" || len(l.EvidenceRefs) == 0 || l.Decision == "" || l.RecordedAt < 1 {
|
||||||
|
return fmt.Errorf("learning ledger entry is incomplete")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package work
|
||||||
|
|
||||||
|
import "git.cin.su/m/Assistant/contracts/world"
|
||||||
|
|
||||||
|
type FreshnessRequirementMode string
|
||||||
|
type FreshnessFallbackPolicy string
|
||||||
|
|
||||||
|
const (
|
||||||
|
FreshnessAny FreshnessRequirementMode = "ANY"
|
||||||
|
FreshnessPreferCurrent FreshnessRequirementMode = "PREFER_CURRENT"
|
||||||
|
FreshnessRequireCurrent FreshnessRequirementMode = "REQUIRE_CURRENT"
|
||||||
|
FreshnessRequireWithinAge FreshnessRequirementMode = "REQUIRE_WITHIN_AGE"
|
||||||
|
FreshnessRequireVersionMatch FreshnessRequirementMode = "REQUIRE_VERSION_MATCH"
|
||||||
|
FreshnessLiveRequired FreshnessRequirementMode = "LIVE_REQUIRED"
|
||||||
|
FallbackAllowStaleDisclosure FreshnessFallbackPolicy = "ALLOW_STALE_WITH_DISCLOSURE"
|
||||||
|
FallbackHypothesisOnly FreshnessFallbackPolicy = "USE_AS_HYPOTHESIS_ONLY"
|
||||||
|
FallbackWaitForSource FreshnessFallbackPolicy = "WAIT_FOR_SOURCE"
|
||||||
|
FallbackAskOwner FreshnessFallbackPolicy = "ASK_OWNER"
|
||||||
|
FallbackStopUnknown FreshnessFallbackPolicy = "STOP_WITH_UNKNOWN"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TaskFreshnessRequirement struct {
|
||||||
|
Mode FreshnessRequirementMode
|
||||||
|
MaximumAgeMillis *int64
|
||||||
|
RequiredVersionRefs []world.SemanticReference
|
||||||
|
RevalidationRequired bool
|
||||||
|
FallbackPolicy FreshnessFallbackPolicy
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
BEGIN;
|
||||||
|
SET ROLE configuration_role;
|
||||||
|
CREATE TABLE IF NOT EXISTS configuration.setting_definitions (setting_definition_id TEXT PRIMARY KEY, owner_namespace TEXT NOT NULL, stable_key TEXT NOT NULL, revision BIGINT NOT NULL CHECK(revision>0), value_type TEXT NOT NULL, default_value TEXT, sensitivity TEXT NOT NULL, lifecycle TEXT NOT NULL, recorded_at_unix_millis BIGINT NOT NULL);
|
||||||
|
CREATE TABLE IF NOT EXISTS configuration.setting_assignments (setting_assignment_id TEXT PRIMARY KEY, principal_id TEXT NOT NULL, definition_ref JSONB NOT NULL, revision BIGINT NOT NULL CHECK(revision>0), selector JSONB NOT NULL, typed_value TEXT, secret_ref TEXT, effective_from_unix_millis BIGINT NOT NULL, effective_until_unix_millis BIGINT, source TEXT NOT NULL, source_ref TEXT NOT NULL, lifecycle TEXT NOT NULL, recorded_at_unix_millis BIGINT NOT NULL);
|
||||||
|
GRANT SELECT, INSERT, UPDATE ON configuration.setting_definitions, configuration.setting_assignments TO configuration_role;
|
||||||
|
RESET ROLE;
|
||||||
|
COMMIT;
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
BEGIN;
|
||||||
|
SET ROLE self_role;
|
||||||
|
CREATE TABLE IF NOT EXISTS self.competence_assessments (assessment_id TEXT PRIMARY KEY, principal_id TEXT NOT NULL, subject_ref JSONB NOT NULL, revision BIGINT NOT NULL CHECK(revision>0), context_matcher JSONB NOT NULL, confidence_millis BIGINT NOT NULL, evidence_refs JSONB NOT NULL, assessed_at_unix_millis BIGINT NOT NULL);
|
||||||
|
CREATE TABLE IF NOT EXISTS self.learning_ledger (entry_id TEXT PRIMARY KEY, principal_id TEXT NOT NULL, observed_problem TEXT NOT NULL, evidence_refs JSONB NOT NULL, diagnosis TEXT NOT NULL, hypothesis TEXT NOT NULL, decision TEXT NOT NULL, recorded_at_unix_millis BIGINT NOT NULL);
|
||||||
|
GRANT SELECT, INSERT, UPDATE ON self.competence_assessments, self.learning_ledger TO self_role;
|
||||||
|
RESET ROLE;
|
||||||
|
COMMIT;
|
||||||
@@ -1 +1 @@
|
|||||||
{"task_file":"dev/tasks/GEN2-005-world-identity-resolution-and-version-environment-bindings.json","task_id":"GEN2-005","task_revision":1}
|
{"task_file":"dev/tasks/GEN2-016-intelligence-strategy-resource-cost-policy-and-personal-benchmark.json","task_id":"GEN2-016","task_revision":1}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/capability"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStrategyUsesRiskAndCostSignals(t *testing.T) {
|
||||||
|
if got := (capability.StrategyRequest{RequiredQuality: 400, CostBudgetMicros: 10}).Select().Path; got != capability.PathRule {
|
||||||
|
t.Fatal(got)
|
||||||
|
}
|
||||||
|
if got := (capability.StrategyRequest{RiskClass: "HIGH", CostOfError: 900}).Select(); got.Path != capability.PathStrongLocal || !got.Escalate {
|
||||||
|
t.Fatalf("%#v", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.cin.su/m/Assistant/contracts/capability"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ValidateReflexRevision(v capability.ReflexRevision) error {
|
||||||
|
if v.ReflexID == "" || v.SourceSkillRevision < 1 || v.Kind == "" || v.ImplementationRef == "" || v.Lifecycle == "" || v.RecordedAt < 1 {
|
||||||
|
return fmt.Errorf("invalid reflex revision")
|
||||||
|
}
|
||||||
|
if v.Lifecycle == capability.ReflexActive && len(v.ValidationEvidenceRefs) == 0 {
|
||||||
|
return fmt.Errorf("active reflex requires evidence")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func ReflexFallback(d capability.FastPathDecision) string {
|
||||||
|
if d.Decision == capability.FastPathApplied {
|
||||||
|
return "reflex"
|
||||||
|
}
|
||||||
|
return "skill->reasoning"
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/capability"
|
||||||
|
"git.cin.su/m/Assistant/modules/capability/domain"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReflexActiveRequiresEvidenceAndFallbacks(t *testing.T) {
|
||||||
|
v := capability.ReflexRevision{ReflexID: "r", SourceSkillRevision: 1, Kind: capability.ReflexRule, ImplementationRef: "rule", Lifecycle: capability.ReflexActive, RecordedAt: 1}
|
||||||
|
if domain.ValidateReflexRevision(v) == nil {
|
||||||
|
t.Fatal("active reflex without evidence")
|
||||||
|
}
|
||||||
|
v.ValidationEvidenceRefs = []capability.SkillEvidenceRef{"eval"}
|
||||||
|
if err := domain.ValidateReflexRevision(v); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if domain.ReflexFallback(capability.FastPathDecision{Decision: capability.FastPathEscalate}) != "skill->reasoning" {
|
||||||
|
t.Fatal("missing escalation")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.cin.su/m/Assistant/contracts/capability"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ValidateSkillRevision(value capability.SkillRevision) error {
|
||||||
|
if value.SkillID == "" || value.Revision < 1 || value.ImplementationRef == "" || value.Lifecycle == "" || value.RecordedAt < 1 {
|
||||||
|
return fmt.Errorf("invalid skill revision")
|
||||||
|
}
|
||||||
|
if value.Lifecycle == capability.SkillValidated && len(value.ValidationEvidenceRefs) == 0 {
|
||||||
|
return fmt.Errorf("validated skill requires evidence")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# configuration
|
||||||
|
|
||||||
|
Configuration owns typed, scoped, versioned settings. ENV is limited to
|
||||||
|
bootstrap primitives; secret values are never configuration values.
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"git.cin.su/m/Assistant/contracts/configuration"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Resolve(definition configuration.SettingDefinition, assignments []configuration.SettingAssignment, selector configuration.ScopeSelector) (configuration.EffectiveSetting,error){if err:=definition.Validate();err!=nil{return configuration.EffectiveSetting{},err}; var matches []configuration.SettingAssignment;for _,a:=range assignments{if err:=a.Validate();err!=nil{return configuration.EffectiveSetting{},err};if a.DefinitionRef==string(definition.ID)&&a.Lifecycle==configuration.SettingActive&&a.Selector.PrincipalRef==selector.PrincipalRef&&a.Selector.SkillRef==selector.SkillRef{matches=append(matches,a)}};if len(matches)==0{return configuration.EffectiveSetting{DefinitionRef:string(definition.ID),Value:definition.DefaultValue,ResolutionTrace:[]string{"system-default"}},nil};sort.SliceStable(matches,func(i,j int)bool{return specificity(matches[i].Selector)>specificity(matches[j].Selector)});if len(matches)>1&&specificity(matches[0].Selector)==specificity(matches[1].Selector){return configuration.EffectiveSetting{},fmt.Errorf("configuration conflict")};return configuration.EffectiveSetting{DefinitionRef:string(definition.ID),Value:matches[0].TypedValue,WinningAssignmentRef:string(matches[0].ID),ResolutionTrace:[]string{"specificity-selected"}},nil}
|
||||||
|
func specificity(s configuration.ScopeSelector)int{return len(s.RequiredContextBindings)+boolInt(s.SkillRef!="")+boolInt(s.TaskRef!="")+boolInt(s.SessionRef!="")+boolInt(s.TemporaryOverride)}
|
||||||
|
func boolInt(v bool)int{if v{return 1};return 0}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package domain_test
|
||||||
|
import("testing"; "git.cin.su/m/Assistant/contracts/configuration"; "git.cin.su/m/Assistant/modules/configuration/domain")
|
||||||
|
func TestConfigurationResolvesCompanyAndSkillScope(t *testing.T){d:=configuration.SettingDefinition{ID:"x",OwnerNamespace:"capability",StableKey:"endpoint",Revision:1,ValueType:configuration.ValueString,Lifecycle:configuration.SettingActive,RecordedAtUnixMillis:1};a:=configuration.SettingAssignment{ID:"a",PrincipalID:"company-a",DefinitionRef:"x",Revision:1,Selector:configuration.ScopeSelector{PrincipalRef:"company-a",SkillRef:"skill"},TypedValue:"a-value",Source:configuration.SourceHumanDirective,Lifecycle:configuration.SettingActive,RecordedAtUnixMillis:1};got,err:=domain.Resolve(d,[]configuration.SettingAssignment{a},configuration.ScopeSelector{PrincipalRef:"company-a",SkillRef:"skill"});if err!=nil||got.Value!="a-value"{t.Fatalf("got %#v err=%v",got,err)}}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/epistemics"
|
||||||
|
"git.cin.su/m/Assistant/platform/ids"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BuildEpisode(experiences []epistemics.ExperienceRecord, summary string, at int64) (epistemics.Episode, error) {
|
||||||
|
if len(experiences) == 0 || strings.TrimSpace(summary) == "" || at < 1 {
|
||||||
|
return epistemics.Episode{}, ErrInvalidExperience
|
||||||
|
}
|
||||||
|
refs := make([]epistemics.ExperienceRecordID, 0, len(experiences))
|
||||||
|
outcome := epistemics.OutcomeUnknown
|
||||||
|
for _, e := range experiences {
|
||||||
|
if _, err := NewExperienceRecord(e); err != nil {
|
||||||
|
return epistemics.Episode{}, err
|
||||||
|
}
|
||||||
|
refs = append(refs, e.ID)
|
||||||
|
if e.ActualOutcome != epistemics.OutcomeSuccess {
|
||||||
|
outcome = e.ActualOutcome
|
||||||
|
}
|
||||||
|
}
|
||||||
|
id, err := ids.New()
|
||||||
|
if err != nil {
|
||||||
|
return epistemics.Episode{}, err
|
||||||
|
}
|
||||||
|
return epistemics.Episode{ID: epistemics.EpisodeID(id), ExperienceRefs: refs, Summary: summary, Outcome: outcome, RecordedAtUnixMillis: at}, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/epistemics"
|
||||||
|
"git.cin.su/m/Assistant/modules/epistemics/domain"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEpisodeIsRebuildableFromExperience(t *testing.T) {
|
||||||
|
e := epistemics.ExperienceRecord{ID: "e", SourceKind: epistemics.ExperienceSourceInteraction, OriginalIntentID: "i", SourceUtteranceID: "u", HelpMethod: epistemics.HelpMethodFallback, ExpectedOutcome: epistemics.OutcomeSuccess, ActualOutcome: epistemics.OutcomeFailed, RecordedAtUnixMillis: 1}
|
||||||
|
ep, err := domain.BuildEpisode([]epistemics.ExperienceRecord{e}, "failed attempt", 1)
|
||||||
|
if err != nil || len(ep.ExperienceRefs) != 1 || ep.Outcome != epistemics.OutcomeFailed {
|
||||||
|
t.Fatalf("episode=%#v err=%v", ep, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import "git.cin.su/m/Assistant/contracts/epistemics"
|
||||||
|
|
||||||
|
// AssessFreshness receives the Work-owned requirement as primitive policy
|
||||||
|
// inputs, keeping the Epistemics owner independent of Work package types.
|
||||||
|
func AssessFreshness(applicability epistemics.TemporalApplicability, mode string, maximumAgeMillis *int64, nowMillis int64) epistemics.FreshnessAssessment {
|
||||||
|
age := nowMillis - applicability.ObservedAtUnixMillis
|
||||||
|
if age < 0 {
|
||||||
|
age = 0
|
||||||
|
}
|
||||||
|
state := epistemics.FreshnessAssessmentCurrent
|
||||||
|
reason := "observation is within applicability window"
|
||||||
|
if applicability.ValidUntilUnixMillis != nil && nowMillis > *applicability.ValidUntilUnixMillis {
|
||||||
|
state, reason = epistemics.FreshnessAssessmentStale, "valid-until elapsed"
|
||||||
|
}
|
||||||
|
if applicability.Volatility.HardStaleAfterMillis != nil && age > *applicability.Volatility.HardStaleAfterMillis {
|
||||||
|
state, reason = epistemics.FreshnessAssessmentStale, "hard volatility window elapsed"
|
||||||
|
}
|
||||||
|
if applicability.Volatility.RevalidateAfterMillis != nil && age > *applicability.Volatility.RevalidateAfterMillis && state == epistemics.FreshnessAssessmentCurrent {
|
||||||
|
state, reason = epistemics.FreshnessAssessmentAging, "revalidation window elapsed"
|
||||||
|
}
|
||||||
|
if maximumAgeMillis != nil && age > *maximumAgeMillis {
|
||||||
|
state, reason = epistemics.FreshnessAssessmentStale, "task maximum age exceeded"
|
||||||
|
}
|
||||||
|
if mode == "LIVE_REQUIRED" {
|
||||||
|
state, reason = epistemics.FreshnessAssessmentHistoricalOnly, "live source required"
|
||||||
|
}
|
||||||
|
return epistemics.FreshnessAssessment{SourceKnowledgeRef: "knowledge", TaskRef: "task", State: state, Reason: reason, AgeMillis: age, AssessedAtUnixMillis: nowMillis}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/epistemics"
|
||||||
|
"git.cin.su/m/Assistant/modules/epistemics/domain"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFreshnessIsTaskRelative(t *testing.T) {
|
||||||
|
hard := int64(100)
|
||||||
|
app := epistemics.TemporalApplicability{ObservedAtUnixMillis: 1, Volatility: epistemics.VolatilitySpec{Mode: epistemics.VolatilityVersionBound, HardStaleAfterMillis: &hard}}
|
||||||
|
current := domain.AssessFreshness(app, "ANY", nil, 50)
|
||||||
|
historical := domain.AssessFreshness(app, "LIVE_REQUIRED", nil, 50)
|
||||||
|
if current.State != epistemics.FreshnessAssessmentCurrent || historical.State != epistemics.FreshnessAssessmentHistoricalOnly {
|
||||||
|
t.Fatalf("got %v and %v", current.State, historical.State)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"git.cin.su/m/Assistant/contracts/epistemics"
|
||||||
|
"git.cin.su/m/Assistant/platform/ids"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrInvalidKnowledge = errors.New("invalid epistemic knowledge record")
|
||||||
|
|
||||||
|
func ValidateProposition(value epistemics.Proposition) error {
|
||||||
|
if value.ID == "" || value.Kind == "" || strings.TrimSpace(value.SubjectRef) == "" || (value.ObjectValue == "" && value.ObjectRef == "" && value.TextFallback == "") {
|
||||||
|
return ErrInvalidKnowledge
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateBeliefAssessment(value epistemics.BeliefAssessment) error {
|
||||||
|
if value.ID == "" || value.ClaimID == "" || !value.Revision.Valid() || value.State == "" || value.ConfidenceMillis < 0 || value.ConfidenceMillis > 1000 || value.AssessedAtUnixMillis < 1 {
|
||||||
|
return ErrInvalidKnowledge
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBeliefAssessment(claim epistemics.ClaimID, confidence int64, state epistemics.BeliefAssessmentState, evidence []epistemics.EvidenceRef, at int64) (epistemics.BeliefAssessment, error) {
|
||||||
|
id, err := ids.New()
|
||||||
|
if err != nil {
|
||||||
|
return epistemics.BeliefAssessment{}, err
|
||||||
|
}
|
||||||
|
value := epistemics.BeliefAssessment{ID: id, ClaimID: claim, Revision: ids.InitialRevision, State: state, ConfidenceMillis: confidence, EvidenceRefs: append([]epistemics.EvidenceRef(nil), evidence...), AssessedAtUnixMillis: at}
|
||||||
|
if err := ValidateBeliefAssessment(value); err != nil {
|
||||||
|
return epistemics.BeliefAssessment{}, err
|
||||||
|
}
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/epistemics"
|
||||||
|
"git.cin.su/m/Assistant/modules/epistemics/domain"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestKnowledgeV2SeparatesPropositionAndReassessableBelief(t *testing.T) {
|
||||||
|
p := epistemics.Proposition{ID: "p", Kind: epistemics.PropositionWorldFacet, SubjectRef: "world:database:a", ObjectValue: "1.6.28"}
|
||||||
|
if err := domain.ValidateProposition(p); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
a, err := domain.NewBeliefAssessment("claim:a", 800, epistemics.BeliefAssessmentCurrent, []epistemics.EvidenceRef{"observation:a"}, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
a.Revision++
|
||||||
|
if err := domain.ValidateBeliefAssessment(a); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import "git.cin.su/m/Assistant/contracts/interaction"
|
||||||
|
|
||||||
|
type ContextProjection struct {
|
||||||
|
Text string
|
||||||
|
Source string
|
||||||
|
UsedPersonalMemoryFallback bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildGen2Context is a read-side projection over canonical utterance history.
|
||||||
|
// PersonalMemory remains a compatibility fallback and is never written here.
|
||||||
|
func BuildGen2Context(history []interaction.HumanUtterance) ContextProjection {
|
||||||
|
text := CompilePersonalMemory(history).ContextText()
|
||||||
|
if text != "" {
|
||||||
|
return ContextProjection{Text: text, Source: "retrieval:interaction-utterances"}
|
||||||
|
}
|
||||||
|
return ContextProjection{Text: text, Source: "personal-memory-v1-fallback", UsedPersonalMemoryFallback: true}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/interaction"
|
||||||
|
"git.cin.su/m/Assistant/modules/interaction/domain"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGen2ContextUsesRetrievalProjectionAndKeepsV1Fallback(t *testing.T) {
|
||||||
|
got := domain.BuildGen2Context([]interaction.HumanUtterance{{ID: "u", Content: "Я сейчас в Москве", ReceivedAtUnixMillis: 1}})
|
||||||
|
if got.Source != "retrieval:interaction-utterances" || got.UsedPersonalMemoryFallback {
|
||||||
|
t.Fatalf("got %#v", got)
|
||||||
|
}
|
||||||
|
empty := domain.BuildGen2Context(nil)
|
||||||
|
if !empty.UsedPersonalMemoryFallback {
|
||||||
|
t.Fatalf("fallback missing: %#v", empty)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
selfcontract "git.cin.su/m/Assistant/contracts/self"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBenchmarkRequiresEvidenceAndDoesNotPromoteAlone(t *testing.T) {
|
||||||
|
e := selfcontract.BenchmarkEvaluation{CaseRef: "case", QualityMillis: 900}
|
||||||
|
if e.Valid() {
|
||||||
|
t.Fatal("benchmark without evidence accepted")
|
||||||
|
}
|
||||||
|
e.EvidenceRefs = []selfcontract.SemanticReference{{OwnerNamespace: "epistemics", SemanticKind: "evaluation", StableID: "e"}}
|
||||||
|
if !e.Valid() {
|
||||||
|
t.Fatal("evidence-backed evaluation rejected")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/contracts/self"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ValidateCompetence(v self.CompetenceAssessment) error { return v.Validate() }
|
||||||
|
func ValidateLearning(v self.LearningLedgerEntry) error { return v.Validate() }
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
selfcontract "git.cin.su/m/Assistant/contracts/self"
|
||||||
|
"git.cin.su/m/Assistant/modules/self/domain"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCompetenceCannotBeSelfDeclaredWithoutEvidence(t *testing.T) {
|
||||||
|
v := selfcontract.CompetenceAssessment{ID: "a", PrincipalID: "p", SubjectRef: selfcontract.SemanticReference{OwnerNamespace: "capability", SemanticKind: "skill", StableID: "s"}, Revision: 1, ConfidenceMillis: 1000, AssessedAt: 1}
|
||||||
|
if domain.ValidateCompetence(v) == nil {
|
||||||
|
t.Fatal("unsupported competence accepted")
|
||||||
|
}
|
||||||
|
v.EvidenceRefs = []selfcontract.SemanticReference{{OwnerNamespace: "epistemics", SemanticKind: "evaluation", StableID: "e"}}
|
||||||
|
if err := domain.ValidateCompetence(v); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package secrets
|
||||||
|
|
||||||
|
import "git.cin.su/m/Assistant/contracts/configuration"
|
||||||
|
|
||||||
|
func ValidateBootstrap(value configuration.BootstrapConfig) bool {
|
||||||
|
return value.NodeIdentity != "" && value.ControlDatabaseLocator != "" && value.RootSecretResolverLocator != ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package retrieval
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
|
type Lane string
|
||||||
|
|
||||||
|
const (
|
||||||
|
LaneSemantic Lane = "SEMANTIC"
|
||||||
|
LaneEntity Lane = "ENTITY"
|
||||||
|
LaneTemporal Lane = "TEMPORAL"
|
||||||
|
LaneGoal Lane = "GOAL"
|
||||||
|
LanePositiveExperience Lane = "POSITIVE_EXPERIENCE"
|
||||||
|
LaneNegativeExperience Lane = "NEGATIVE_EXPERIENCE"
|
||||||
|
LaneContradiction Lane = "CONTRADICTION"
|
||||||
|
LaneSkill Lane = "SKILL"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RetrievalDocument is disposable read-side projection data. SourceRef and
|
||||||
|
// Owner preserve provenance; this type never becomes canonical meaning.
|
||||||
|
type RetrievalDocument struct {
|
||||||
|
ID string
|
||||||
|
SourceRef string
|
||||||
|
Owner string
|
||||||
|
PrincipalID string
|
||||||
|
ContextScopeRef string
|
||||||
|
VersionRef string
|
||||||
|
Lane Lane
|
||||||
|
Text string
|
||||||
|
Relevance int
|
||||||
|
Freshness int
|
||||||
|
Confidence int
|
||||||
|
Salience int
|
||||||
|
Cost int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query struct {
|
||||||
|
PrincipalID string
|
||||||
|
ContextScopeRef string
|
||||||
|
VersionRef string
|
||||||
|
Lanes []Lane
|
||||||
|
Limit int
|
||||||
|
}
|
||||||
|
|
||||||
|
func FilterAndRank(documents []RetrievalDocument, query Query) []RetrievalDocument {
|
||||||
|
filtered := make([]RetrievalDocument, 0, len(documents))
|
||||||
|
for _, doc := range documents {
|
||||||
|
if doc.PrincipalID != query.PrincipalID || (query.ContextScopeRef != "" && doc.ContextScopeRef != query.ContextScopeRef) || (query.VersionRef != "" && doc.VersionRef != query.VersionRef) || !containsLane(query.Lanes, doc.Lane) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
filtered = append(filtered, doc)
|
||||||
|
}
|
||||||
|
sort.SliceStable(filtered, func(i, j int) bool {
|
||||||
|
left := filtered[i].Relevance + filtered[i].Freshness + filtered[i].Confidence + filtered[i].Salience - filtered[i].Cost
|
||||||
|
right := filtered[j].Relevance + filtered[j].Freshness + filtered[j].Confidence + filtered[j].Salience - filtered[j].Cost
|
||||||
|
if left != right {
|
||||||
|
return left > right
|
||||||
|
}
|
||||||
|
return filtered[i].ID < filtered[j].ID
|
||||||
|
})
|
||||||
|
if query.Limit > 0 && len(filtered) > query.Limit {
|
||||||
|
filtered = filtered[:query.Limit]
|
||||||
|
}
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsLane(lanes []Lane, lane Lane) bool {
|
||||||
|
if len(lanes) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, v := range lanes {
|
||||||
|
if v == lane {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProjectionBuilder interface {
|
||||||
|
Build() ([]RetrievalDocument, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Rebuild(builders ...ProjectionBuilder) ([]RetrievalDocument, error) {
|
||||||
|
var result []RetrievalDocument
|
||||||
|
for _, builder := range builders {
|
||||||
|
docs, err := builder.Build()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, docs...)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package retrieval_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cin.su/m/Assistant/runtime/retrieval"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestScopeAndVersionFilterBeforeRanking(t *testing.T) {
|
||||||
|
docs := []retrieval.RetrievalDocument{{ID: "wrong-company", PrincipalID: "a", ContextScopeRef: "b", VersionRef: "v", Lane: retrieval.LaneSemantic, Relevance: 100}, {ID: "right", PrincipalID: "a", ContextScopeRef: "a", VersionRef: "v", Lane: retrieval.LaneNegativeExperience, Relevance: 1}, {ID: "wrong-version", PrincipalID: "a", ContextScopeRef: "a", VersionRef: "old", Lane: retrieval.LaneSemantic, Relevance: 100}}
|
||||||
|
got := retrieval.FilterAndRank(docs, retrieval.Query{PrincipalID: "a", ContextScopeRef: "a", VersionRef: "v", Lanes: []retrieval.Lane{retrieval.LaneSemantic, retrieval.LaneNegativeExperience}, Limit: 10})
|
||||||
|
if len(got) != 1 || got[0].ID != "right" {
|
||||||
|
t.Fatalf("got %#v", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user