Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a065382512 | ||
|
|
8a8e571905 |
@@ -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
|
||||||
@@ -134,3 +142,24 @@ 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
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,48 @@ import (
|
|||||||
// a reference only; it does not expose another owner's storage.
|
// a reference only; it does not expose another owner's storage.
|
||||||
type SemanticReference = ids.SemanticRef
|
type SemanticReference = ids.SemanticRef
|
||||||
|
|
||||||
|
// VersionBinding is a typed applicability constraint. Absence of VersionRef
|
||||||
|
// means unknown, never an implicit "latest".
|
||||||
|
type VersionMatchMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
VersionExact VersionMatchMode = "EXACT"
|
||||||
|
VersionCompatibleFamily VersionMatchMode = "COMPATIBLE_FAMILY"
|
||||||
|
VersionAtOrBefore VersionMatchMode = "AT_OR_BEFORE"
|
||||||
|
VersionUnknown VersionMatchMode = "UNKNOWN"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VersionBinding struct {
|
||||||
|
SubjectRef SemanticReference
|
||||||
|
VersionRef SemanticReference
|
||||||
|
MatchMode VersionMatchMode
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnvironmentReference struct {
|
||||||
|
EnvironmentRef SemanticReference
|
||||||
|
VersionRef *SemanticReference
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b VersionBinding) Validate() error {
|
||||||
|
if !b.SubjectRef.Valid() || !b.VersionRef.Valid() {
|
||||||
|
return fmt.Errorf("version binding references are invalid")
|
||||||
|
}
|
||||||
|
if b.MatchMode != VersionExact && b.MatchMode != VersionCompatibleFamily && b.MatchMode != VersionAtOrBefore && b.MatchMode != VersionUnknown {
|
||||||
|
return fmt.Errorf("version binding match mode is invalid")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r EnvironmentReference) Validate() error {
|
||||||
|
if !r.EnvironmentRef.Valid() {
|
||||||
|
return fmt.Errorf("environment reference is invalid")
|
||||||
|
}
|
||||||
|
if r.VersionRef != nil && !r.VersionRef.Valid() {
|
||||||
|
return fmt.Errorf("environment version reference is invalid")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type PrincipalRealm string
|
type PrincipalRealm string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"task_file":"dev/tasks/GEN2-004-replace-project-centric-focus-with-contextscope-focusframe-focusstack.json","task_id":"GEN2-004","task_revision":1}
|
{"task_file":"dev/tasks/GEN2-006-normalize-epistemics-evidence-propositions-claims-and-belief-assessments.json","task_id":"GEN2-006","task_revision":1}
|
||||||
@@ -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,30 @@
|
|||||||
|
package domain_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.cin.su/m/Assistant/contracts/world"
|
||||||
|
"git.cin.su/m/Assistant/modules/world/domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestResolveCandidatesDoesNotAutoMergeAmbiguousPeopleOrSystems(t *testing.T) {
|
||||||
|
decision, candidates := domain.ResolveCandidates([]world.IdentityResolutionCandidate{
|
||||||
|
{ObjectRef: world.SemanticReference{OwnerNamespace: "world", SemanticKind: "person", StableID: "ivan-telegram"}, Confidence: 800},
|
||||||
|
{ObjectRef: world.SemanticReference{OwnerNamespace: "world", SemanticKind: "person", StableID: "ivan-crm"}, Confidence: 800},
|
||||||
|
}, 700)
|
||||||
|
if decision != world.ResolutionUnresolved || len(candidates) != 2 {
|
||||||
|
t.Fatalf("ambiguous result = %s, %#v", decision, candidates)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersionAndEnvironmentReferencesAreTyped(t *testing.T) {
|
||||||
|
version := world.SemanticReference{OwnerNamespace: "world", SemanticKind: "version", StableID: "unf-3"}
|
||||||
|
binding := world.VersionBinding{SubjectRef: world.SemanticReference{OwnerNamespace: "world", SemanticKind: "database", StableID: "company-a-unf"}, VersionRef: version, MatchMode: world.VersionExact}
|
||||||
|
if err := binding.Validate(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
environment := world.EnvironmentReference{EnvironmentRef: world.SemanticReference{OwnerNamespace: "world", SemanticKind: "environment", StableID: "company-a-prod"}, VersionRef: &version}
|
||||||
|
if err := environment.Validate(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package domain
|
|||||||
|
|
||||||
import "git.cin.su/m/Assistant/contracts/world"
|
import "git.cin.su/m/Assistant/contracts/world"
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
func ValidateObject(value world.WorldObject) error { return value.Validate() }
|
func ValidateObject(value world.WorldObject) error { return value.Validate() }
|
||||||
|
|
||||||
func ValidateKindDefinition(value world.WorldObjectKindDefinition) error { return value.Validate() }
|
func ValidateKindDefinition(value world.WorldObjectKindDefinition) error { return value.Validate() }
|
||||||
@@ -15,3 +17,18 @@ func ValidateRelationDefinition(value world.RelationDefinition) error { return v
|
|||||||
func ValidateResolution(value world.IdentityResolutionDecisionRecord) error { return value.Validate() }
|
func ValidateResolution(value world.IdentityResolutionDecisionRecord) error { return value.Validate() }
|
||||||
|
|
||||||
func ValidateLineage(value world.WorldLineage) error { return value.Validate() }
|
func ValidateLineage(value world.WorldLineage) error { return value.Validate() }
|
||||||
|
|
||||||
|
// ResolveCandidates deliberately refuses to merge an ambiguous result. A
|
||||||
|
// caller may persist the returned UNRESOLVED decision and later re-evaluate it
|
||||||
|
// with additional evidence.
|
||||||
|
func ResolveCandidates(candidates []world.IdentityResolutionCandidate, minimumConfidence int64) (world.ResolutionDecision, []world.IdentityResolutionCandidate) {
|
||||||
|
ordered := append([]world.IdentityResolutionCandidate(nil), candidates...)
|
||||||
|
sort.SliceStable(ordered, func(i, j int) bool { return ordered[i].Confidence > ordered[j].Confidence })
|
||||||
|
if len(ordered) == 0 || ordered[0].Confidence < minimumConfidence {
|
||||||
|
return world.ResolutionUnresolved, ordered
|
||||||
|
}
|
||||||
|
if len(ordered) > 1 && ordered[0].Confidence == ordered[1].Confidence {
|
||||||
|
return world.ResolutionUnresolved, ordered
|
||||||
|
}
|
||||||
|
return world.ResolutionSame, ordered[:1]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user