Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a862a07ae1 | ||
|
|
4d63c1bea4 | ||
|
|
91c38de167 | ||
|
|
926afc82b5 | ||
|
|
4a066d71f4 | ||
|
|
7fc611ed08 |
@@ -11,7 +11,7 @@ import (
|
|||||||
type AuthorityRepository struct{ pool *pgxpool.Pool }
|
type AuthorityRepository struct{ pool *pgxpool.Pool }
|
||||||
|
|
||||||
func OpenAuthority(ctx context.Context, c ContinuityConfig) (*AuthorityRepository, error) {
|
func OpenAuthority(ctx context.Context, c ContinuityConfig) (*AuthorityRepository, error) {
|
||||||
p, e := pgxpool.New(ctx, fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", c.Host, c.Port, c.Database, c.User, c.Password))
|
p, e := openPool(ctx, c)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ var ErrCapabilityImplementationNotFound = errors.New("capability implementation
|
|||||||
type CapabilityRepository struct{ pool *pgxpool.Pool }
|
type CapabilityRepository struct{ pool *pgxpool.Pool }
|
||||||
|
|
||||||
func OpenCapability(ctx context.Context, config ContinuityConfig) (*CapabilityRepository, error) {
|
func OpenCapability(ctx context.Context, config ContinuityConfig) (*CapabilityRepository, error) {
|
||||||
dsn := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password)
|
pool, err := openPool(ctx, config)
|
||||||
pool, err := pgxpool.New(ctx, dsn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ var (
|
|||||||
type CommitRepository struct{ pool *pgxpool.Pool }
|
type CommitRepository struct{ pool *pgxpool.Pool }
|
||||||
|
|
||||||
func OpenCommit(ctx context.Context, c ContinuityConfig) (*CommitRepository, error) {
|
func OpenCommit(ctx context.Context, c ContinuityConfig) (*CommitRepository, error) {
|
||||||
p, e := pgxpool.New(ctx, fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", c.Host, c.Port, c.Database, c.User, c.Password))
|
p, e := openPool(ctx, c)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"git.cin.su/m/Assistant/contracts/authority"
|
"git.cin.su/m/Assistant/contracts/authority"
|
||||||
"git.cin.su/m/Assistant/contracts/continuity"
|
"git.cin.su/m/Assistant/contracts/continuity"
|
||||||
@@ -29,9 +30,25 @@ var (
|
|||||||
type ContinuityConfig struct{ Host, Port, Database, User, Password string }
|
type ContinuityConfig struct{ Host, Port, Database, User, Password string }
|
||||||
type ContinuityRepository struct{ pool *pgxpool.Pool }
|
type ContinuityRepository struct{ pool *pgxpool.Pool }
|
||||||
|
|
||||||
|
func openPool(ctx context.Context, config ContinuityConfig) (*pgxpool.Pool, error) {
|
||||||
|
poolConfig, err := pgxpool.ParseConfig("")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
port, err := strconv.ParseUint(config.Port, 10, 16)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid postgres port: %w", err)
|
||||||
|
}
|
||||||
|
poolConfig.ConnConfig.Host = config.Host
|
||||||
|
poolConfig.ConnConfig.Port = uint16(port)
|
||||||
|
poolConfig.ConnConfig.Database = config.Database
|
||||||
|
poolConfig.ConnConfig.User = config.User
|
||||||
|
poolConfig.ConnConfig.Password = config.Password
|
||||||
|
return pgxpool.NewWithConfig(ctx, poolConfig)
|
||||||
|
}
|
||||||
|
|
||||||
func OpenContinuity(ctx context.Context, config ContinuityConfig) (*ContinuityRepository, error) {
|
func OpenContinuity(ctx context.Context, config ContinuityConfig) (*ContinuityRepository, error) {
|
||||||
dsn := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password)
|
pool, err := openPool(ctx, config)
|
||||||
pool, err := pgxpool.New(ctx, dsn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ import (
|
|||||||
type EpistemicsRepository struct{ pool *pgxpool.Pool }
|
type EpistemicsRepository struct{ pool *pgxpool.Pool }
|
||||||
|
|
||||||
func OpenEpistemics(ctx context.Context, config ContinuityConfig) (*EpistemicsRepository, error) {
|
func OpenEpistemics(ctx context.Context, config ContinuityConfig) (*EpistemicsRepository, error) {
|
||||||
dsn := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password)
|
pool, err := openPool(ctx, config)
|
||||||
pool, err := pgxpool.New(ctx, dsn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
type IdentityRepository struct{ pool *pgxpool.Pool }
|
type IdentityRepository struct{ pool *pgxpool.Pool }
|
||||||
|
|
||||||
func OpenIdentity(ctx context.Context, config ContinuityConfig) (*IdentityRepository, error) {
|
func OpenIdentity(ctx context.Context, config ContinuityConfig) (*IdentityRepository, error) {
|
||||||
pool, err := pgxpool.New(ctx, fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password))
|
pool, err := openPool(ctx, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package postgres
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.cin.su/m/Assistant/contracts/interaction"
|
"git.cin.su/m/Assistant/contracts/interaction"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
@@ -11,7 +10,7 @@ import (
|
|||||||
type InteractionRepository struct{ pool *pgxpool.Pool }
|
type InteractionRepository struct{ pool *pgxpool.Pool }
|
||||||
|
|
||||||
func OpenInteraction(ctx context.Context, c ContinuityConfig) (*InteractionRepository, error) {
|
func OpenInteraction(ctx context.Context, c ContinuityConfig) (*InteractionRepository, error) {
|
||||||
p, e := pgxpool.New(ctx, fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", c.Host, c.Port, c.Database, c.User, c.Password))
|
p, e := openPool(ctx, c)
|
||||||
return &InteractionRepository{p}, e
|
return &InteractionRepository{p}, e
|
||||||
}
|
}
|
||||||
func (r *InteractionRepository) Close() { r.pool.Close() }
|
func (r *InteractionRepository) Close() { r.pool.Close() }
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package postgres
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.cin.su/m/Assistant/contracts/identity"
|
"git.cin.su/m/Assistant/contracts/identity"
|
||||||
@@ -13,8 +12,7 @@ import (
|
|||||||
type SituationRepository struct{ pool *pgxpool.Pool }
|
type SituationRepository struct{ pool *pgxpool.Pool }
|
||||||
|
|
||||||
func OpenSituation(ctx context.Context, config ContinuityConfig) (*SituationRepository, error) {
|
func OpenSituation(ctx context.Context, config ContinuityConfig) (*SituationRepository, error) {
|
||||||
dsn := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password)
|
pool, err := openPool(ctx, config)
|
||||||
pool, err := pgxpool.New(ctx, dsn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ import (
|
|||||||
type WorkRepository struct{ pool *pgxpool.Pool }
|
type WorkRepository struct{ pool *pgxpool.Pool }
|
||||||
|
|
||||||
func OpenWork(ctx context.Context, config ContinuityConfig) (*WorkRepository, error) {
|
func OpenWork(ctx context.Context, config ContinuityConfig) (*WorkRepository, error) {
|
||||||
dsn := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password)
|
pool, err := openPool(ctx, config)
|
||||||
pool, err := pgxpool.New(ctx, dsn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -85,7 +86,12 @@ func (r learningRecorder) recordReminderResponse(ctx context.Context, input remi
|
|||||||
RecordedAtUnixMillis: input.At.UnixMilli(),
|
RecordedAtUnixMillis: input.At.UnixMilli(),
|
||||||
}
|
}
|
||||||
expectation, err := epistemicsdomain.NewSystemExpectation(expectation)
|
expectation, err := epistemicsdomain.NewSystemExpectation(expectation)
|
||||||
if err != nil || r.epistemics.SaveSystemExpectation(ctx, expectation) != nil {
|
if err != nil {
|
||||||
|
log.Printf("learning reminder expectation invalid: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := r.epistemics.SaveSystemExpectation(ctx, expectation); err != nil {
|
||||||
|
log.Printf("learning reminder expectation unavailable: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
actual, confidence := outcomeForHumanResponse(input.Result.Response)
|
actual, confidence := outcomeForHumanResponse(input.Result.Response)
|
||||||
@@ -197,13 +203,19 @@ func (r learningRecorder) recordCapabilityUse(ctx context.Context, input capabil
|
|||||||
func (r learningRecorder) saveExperienceAndReflection(ctx context.Context, value epistemics.ExperienceRecord) (epistemics.ExperienceRecord, bool) {
|
func (r learningRecorder) saveExperienceAndReflection(ctx context.Context, value epistemics.ExperienceRecord) (epistemics.ExperienceRecord, bool) {
|
||||||
value, err := epistemicsdomain.NewExperienceRecord(value)
|
value, err := epistemicsdomain.NewExperienceRecord(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("learning experience invalid: %v", err)
|
||||||
return epistemics.ExperienceRecord{}, false
|
return epistemics.ExperienceRecord{}, false
|
||||||
}
|
}
|
||||||
if err := r.epistemics.SaveExperienceRecord(ctx, value); err != nil {
|
if err := r.epistemics.SaveExperienceRecord(ctx, value); err != nil {
|
||||||
|
log.Printf("learning experience unavailable: %v", err)
|
||||||
return epistemics.ExperienceRecord{}, false
|
return epistemics.ExperienceRecord{}, false
|
||||||
}
|
}
|
||||||
if candidate, ok, err := epistemicsdomain.ReflectionForExperience(value); err == nil && ok {
|
if candidate, ok, err := epistemicsdomain.ReflectionForExperience(value); err == nil && ok {
|
||||||
_ = r.epistemics.SaveReflectionCandidate(ctx, candidate)
|
if err := r.epistemics.SaveReflectionCandidate(ctx, candidate); err != nil {
|
||||||
|
log.Printf("learning reflection unavailable: %v", err)
|
||||||
|
}
|
||||||
|
} else if err != nil {
|
||||||
|
log.Printf("learning reflection invalid: %v", err)
|
||||||
}
|
}
|
||||||
return value, true
|
return value, true
|
||||||
}
|
}
|
||||||
@@ -214,6 +226,7 @@ func (r learningRecorder) updateReminderSkill(ctx context.Context, experience ep
|
|||||||
}
|
}
|
||||||
profile, err := r.capability.LoadSkillProfile(ctx, reminderResponseSkillID)
|
profile, err := r.capability.LoadSkillProfile(ctx, reminderResponseSkillID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("learning skill profile unavailable: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
next, err := capabilitydomain.ObserveSkillOutcome(profile, capability.SkillOutcomeObservation{
|
next, err := capabilitydomain.ObserveSkillOutcome(profile, capability.SkillOutcomeObservation{
|
||||||
@@ -223,9 +236,11 @@ func (r learningRecorder) updateReminderSkill(ctx context.Context, experience ep
|
|||||||
ObservedAtUnixMillis: experience.RecordedAtUnixMillis,
|
ObservedAtUnixMillis: experience.RecordedAtUnixMillis,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("learning skill observation invalid: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := r.capability.SaveSkillProfile(ctx, next); err != nil {
|
if err := r.capability.SaveSkillProfile(ctx, next); err != nil {
|
||||||
|
log.Printf("learning skill profile save unavailable: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,16 +201,19 @@ func main() {
|
|||||||
}
|
}
|
||||||
experiences, err := epistemicsRepository.RecentExperienceRecords(r.Context(), limit)
|
experiences, err := epistemicsRepository.RecentExperienceRecords(r.Context(), limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("learning recent experiences unavailable: %v", err)
|
||||||
http.Error(w, "learning experience unavailable", http.StatusServiceUnavailable)
|
http.Error(w, "learning experience unavailable", http.StatusServiceUnavailable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
reflections, err := epistemicsRepository.RecentReflectionCandidates(r.Context(), limit)
|
reflections, err := epistemicsRepository.RecentReflectionCandidates(r.Context(), limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("learning recent reflections unavailable: %v", err)
|
||||||
http.Error(w, "learning reflection unavailable", http.StatusServiceUnavailable)
|
http.Error(w, "learning reflection unavailable", http.StatusServiceUnavailable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
skills, err := capabilityRepository.RecentSkillProfiles(r.Context(), limit)
|
skills, err := capabilityRepository.RecentSkillProfiles(r.Context(), limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("learning recent skills unavailable: %v", err)
|
||||||
http.Error(w, "learning skills unavailable", http.StatusServiceUnavailable)
|
http.Error(w, "learning skills unavailable", http.StatusServiceUnavailable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ services:
|
|||||||
SITUATION_DB_PASSWORD: ${SITUATION_DB_PASSWORD:-assistant_situation_dev_only}
|
SITUATION_DB_PASSWORD: ${SITUATION_DB_PASSWORD:-assistant_situation_dev_only}
|
||||||
WORK_DB_PASSWORD: ${WORK_DB_PASSWORD:-assistant_work_dev_only}
|
WORK_DB_PASSWORD: ${WORK_DB_PASSWORD:-assistant_work_dev_only}
|
||||||
CAPABILITY_DB_PASSWORD: ${CAPABILITY_DB_PASSWORD:-assistant_capability_dev_only}
|
CAPABILITY_DB_PASSWORD: ${CAPABILITY_DB_PASSWORD:-assistant_capability_dev_only}
|
||||||
|
EPISTEMICS_DB_PASSWORD: ${EPISTEMICS_DB_PASSWORD:-assistant_epistemics_dev_only}
|
||||||
COMMIT_DB_PASSWORD: ${COMMIT_DB_PASSWORD:-assistant_commit_dev_only}
|
COMMIT_DB_PASSWORD: ${COMMIT_DB_PASSWORD:-assistant_commit_dev_only}
|
||||||
ports: ["15432:5432"]
|
ports: ["15432:5432"]
|
||||||
volumes:
|
volumes:
|
||||||
@@ -50,6 +51,8 @@ services:
|
|||||||
WORK_POSTGRES_PASSWORD: ${WORK_DB_PASSWORD:-assistant_work_dev_only}
|
WORK_POSTGRES_PASSWORD: ${WORK_DB_PASSWORD:-assistant_work_dev_only}
|
||||||
CAPABILITY_POSTGRES_USER: capability_role
|
CAPABILITY_POSTGRES_USER: capability_role
|
||||||
CAPABILITY_POSTGRES_PASSWORD: ${CAPABILITY_DB_PASSWORD:-assistant_capability_dev_only}
|
CAPABILITY_POSTGRES_PASSWORD: ${CAPABILITY_DB_PASSWORD:-assistant_capability_dev_only}
|
||||||
|
EPISTEMICS_POSTGRES_USER: epistemics_role
|
||||||
|
EPISTEMICS_POSTGRES_PASSWORD: ${EPISTEMICS_DB_PASSWORD:-assistant_epistemics_dev_only}
|
||||||
ports: ["19080:8080"]
|
ports: ["19080:8080"]
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres: { condition: service_healthy }
|
postgres: { condition: service_healthy }
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
"cmd/core-runtime/**",
|
"cmd/core-runtime/**",
|
||||||
"cmd/creator-web/**",
|
"cmd/creator-web/**",
|
||||||
"cmd/continuity-runtime/**",
|
"cmd/continuity-runtime/**",
|
||||||
|
"deploy/docker-compose.dev.yml",
|
||||||
"deploy/docker-compose.prod.yml",
|
"deploy/docker-compose.prod.yml",
|
||||||
"deploy/images/002_owner_passwords.sh",
|
"deploy/images/002_owner_passwords.sh",
|
||||||
"deploy/windows/**",
|
"deploy/windows/**",
|
||||||
|
|||||||
@@ -44,6 +44,24 @@ Audit date: 2026-08-17. Active implementation: DEV-000067 revision 1.
|
|||||||
|
|
||||||
- `DEV_000065_STATUS = COMPLETED`
|
- `DEV_000065_STATUS = COMPLETED`
|
||||||
- `LAST_COMPLETED = ADR-0014 accepted; Continuity-owned AttentionItem contract and persistence; due reminder scanner; Commit internal prospective notification endpoint; human-facing Chat / Today / History surface; relative reminder parsing for "через N минут"; deterministic due-delivery regression tests; notification binding origin corrected to assistant.cin.su revision 2`
|
- `LAST_COMPLETED = ADR-0014 accepted; Continuity-owned AttentionItem contract and persistence; due reminder scanner; Commit internal prospective notification endpoint; human-facing Chat / Today / History surface; relative reminder parsing for "через N минут"; deterministic due-delivery regression tests; notification binding origin corrected to assistant.cin.su revision 2`
|
||||||
|
## DEV-000068 checkpoint
|
||||||
|
|
||||||
|
- `DEV_000068_STATUS = COMPLETED`
|
||||||
|
- `LAST_COMPLETED = Runtime Experience + Reflection Loop V1: production runtime now records meaningful ExperienceRecords, deterministic ReflectionCandidates and SkillProfile evidence from /chat, reminder response, correction, capability and fast-path-decline outcomes`
|
||||||
|
- `RUNTIME_EXPERIENCE_LOOP = ACTIVE for production interactions; no LearningManager and no automatic self-modification`
|
||||||
|
- `REFLECTION_STATUS = deterministic candidate generation only; candidates cannot mutate skills, Authority, source code, deployment or canonical lifecycle`
|
||||||
|
- `SKILL_EVIDENCE_STATUS = skill-obvious-reminder-response-v1 accumulates positive/correction/failure evidence from COMPLETE/SNOOZE/CANCEL target-resolution outcomes`
|
||||||
|
- `FAST_PATH_STATUS = uncertain/unsupported continuation can decline and return to clarification/fallback instead of guessed mutation`
|
||||||
|
- `OPERATOR_INSPECTION = Creator Console exposes recent ExperienceRecords, ReflectionCandidates and SkillProfile status through authenticated proxy`
|
||||||
|
- `HUMAN_CHAT_URL = https://assistant.cin.su/chat`
|
||||||
|
- `ACTIVE_COGNITIVE_BINDINGS = none; CPU CANARY unchanged`
|
||||||
|
- `OPENAI_REAL_CREDENTIAL = not required / not activated`
|
||||||
|
- `TESTS_PASS = go test ./...; go vet ./...; go run ./cmd/devctl preflight -active dev/ACTIVE_TASK.json; go run ./cmd/devctl check-architecture; go run ./cmd/devctl check-diff -active dev/ACTIVE_TASK.json; tests/cognitive_advisory/cognitive_worker_env_policy_test.ps1; tests/owner_acl/verify.ps1 -DockerContext docker-prod -PostgresContainer assistant-postgres-1; production artifact confirmation; production health`
|
||||||
|
- `LIVE_ACCEPTANCE = PASS: reminder completion produced positive ExperienceRecord and SkillProfile evidence; explicit correction produced USER_CORRECTED ExperienceRecord and ReflectionCandidate; unsupported/uncertain continuation produced fast-path decline/fallback evidence without guessed mutation; /chat reachable and human-facing replies did not expose learning IDs`
|
||||||
|
- `PRODUCTION_STATUS = healthy`
|
||||||
|
- `PRODUCTION_REVISION = runtime artifact 7fc611ed0898012707fb45841a7a86818144e776`
|
||||||
|
- `NEXT_RECOMMENDED_REVISION = DEV-000069 only after separate approval; no next milestone started automatically`
|
||||||
|
|
||||||
- `ADR_STATUS = ADR-0014 accepted`
|
- `ADR_STATUS = ADR-0014 accepted`
|
||||||
- `OWNERSHIP_STATUS = no new owner; AttentionItem belongs to Continuity; notification delivery remains Commit/Capability/receiver path`
|
- `OWNERSHIP_STATUS = no new owner; AttentionItem belongs to Continuity; notification delivery remains Commit/Capability/receiver path`
|
||||||
- `REMINDER_LIFECYCLE_STATUS = ARMED -> TRIGGERED -> REVALIDATING -> DELIVERED implemented for due scanner`
|
- `REMINDER_LIFECYCLE_STATUS = ARMED -> TRIGGERED -> REVALIDATING -> DELIVERED implemented for due scanner`
|
||||||
|
|||||||
Reference in New Issue
Block a user