Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7ad996cae | ||
|
|
a065382512 |
@@ -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
|
||||
|
||||
import "git.cin.su/m/Assistant/platform/ids"
|
||||
|
||||
type BeliefState string
|
||||
|
||||
const (
|
||||
@@ -9,19 +11,27 @@ const (
|
||||
)
|
||||
|
||||
type Observation struct {
|
||||
ID ObservationID
|
||||
SourceSnapshot SourceSnapshotID
|
||||
Excerpt SourceExcerptID
|
||||
Text string
|
||||
ObservedAt int64
|
||||
ID ObservationID
|
||||
SourceSnapshot SourceSnapshotID
|
||||
Excerpt SourceExcerptID
|
||||
Text string
|
||||
ObservedAt int64
|
||||
PrincipalID string
|
||||
ContextScopeRef string
|
||||
ObservationKind string
|
||||
Payload string
|
||||
ExtractorRef string
|
||||
}
|
||||
|
||||
type Claim struct {
|
||||
ID ClaimID
|
||||
Statement string
|
||||
ObservationID ObservationID
|
||||
CitationID CitationID
|
||||
Verification VerificationState
|
||||
ID ClaimID
|
||||
Statement string
|
||||
ObservationID ObservationID
|
||||
CitationID CitationID
|
||||
Verification VerificationState
|
||||
PropositionID ids.ID
|
||||
RevisedFrom *ClaimID
|
||||
RecordedAtUnixMillis int64
|
||||
}
|
||||
|
||||
type Belief struct {
|
||||
|
||||
@@ -24,6 +24,8 @@ type HelpMethodKind string
|
||||
type OutcomeClass string
|
||||
type ReflectionTriggerKind string
|
||||
type ReflectionCandidateState string
|
||||
type PropositionKind string
|
||||
type BeliefAssessmentState string
|
||||
|
||||
const (
|
||||
VerificationUnverified VerificationState = "UNVERIFIED"
|
||||
@@ -73,6 +75,12 @@ const (
|
||||
ReflectionCandidateEvaluating ReflectionCandidateState = "EVALUATING"
|
||||
ReflectionCandidateSuperseded ReflectionCandidateState = "SUPERSEDED"
|
||||
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
|
||||
@@ -134,3 +142,24 @@ type ReflectionCandidate struct {
|
||||
ClaimedBy string
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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-007-general-freshness-volatility-temporal-applicability-and-revalidation.json","task_id":"GEN2-007","task_revision":1}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user