Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa01e8e99b | ||
|
|
1113ced623 | ||
|
|
f3ff430812 | ||
|
|
2ec53e40cf | ||
|
|
18fbc7f105 | ||
|
|
a0dce634f3 |
@@ -228,6 +228,25 @@ func (r *ContinuityRepository) MarkAttentionDelivered(ctx context.Context, id co
|
||||
return item, err
|
||||
}
|
||||
|
||||
func (r *ContinuityRepository) MarkAttentionFailed(ctx context.Context, id continuity.AttentionItemID, revision continuity.AttentionRevision, intentID continuity.CommittedActionIntentID, authorizedID continuity.CommittedAuthorizedActionID, attemptID continuity.CommittedActionAttemptID, outcome string) (continuity.AttentionItem, error) {
|
||||
var item continuity.AttentionItem
|
||||
err := r.pool.QueryRow(ctx, `UPDATE continuity.attention_items
|
||||
SET state=$1, revision=revision+1, action_intent_id=$2, authorized_action_id=$3,
|
||||
action_attempt_id=$4, delivery_outcome=$5
|
||||
WHERE attention_item_id=$6 AND state=$7 AND revision=$8
|
||||
RETURNING attention_item_id,owner_principal_id,scope_id,source_kind,source_prospective_item_id,level,state,summary,due_at_unix_millis,
|
||||
created_at_unix_millis,delivered_at_unix_millis,action_intent_id,authorized_action_id,action_attempt_id,delivery_outcome,revision`,
|
||||
continuity.AttentionFailed, intentID, authorizedID, attemptID, outcome,
|
||||
id, continuity.AttentionDelivering, revision).Scan(
|
||||
&item.ID, &item.OwnerPrincipalID, &item.ScopeID, &item.SourceKind, &item.SourceProspectiveID, &item.Level, &item.State,
|
||||
&item.Summary, &item.DueAtUnixMillis, &item.CreatedAtUnixMillis, &item.DeliveredAtUnixMillis, &item.ActionIntentID,
|
||||
&item.AuthorizedActionID, &item.ActionAttemptID, &item.DeliveryOutcome, &item.Revision)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return continuity.AttentionItem{}, ErrAttentionRevisionConflict
|
||||
}
|
||||
return item, err
|
||||
}
|
||||
|
||||
// SatisfyDelivered owns both the Prospective CAS and its idempotency receipt in
|
||||
// one Continuity-local transaction. It never reaches Commit storage.
|
||||
func (r *ContinuityRepository) SatisfyDelivered(ctx context.Context, command continuity.SatisfyDeliveredCommand) (continuity.ActionReceipt, error) {
|
||||
|
||||
@@ -21,6 +21,7 @@ type dueReminderRepository interface {
|
||||
PendingAttention(context.Context, int) ([]continuity.AttentionItem, error)
|
||||
MarkAttentionDelivering(context.Context, continuity.AttentionItemID, continuity.AttentionRevision) (continuity.AttentionItem, error)
|
||||
MarkAttentionDelivered(context.Context, continuity.AttentionItemID, continuity.AttentionRevision, continuity.CommittedActionIntentID, continuity.CommittedAuthorizedActionID, continuity.CommittedActionAttemptID, string, int64) (continuity.AttentionItem, error)
|
||||
MarkAttentionFailed(context.Context, continuity.AttentionItemID, continuity.AttentionRevision, continuity.CommittedActionIntentID, continuity.CommittedAuthorizedActionID, continuity.CommittedActionAttemptID, string) (continuity.AttentionItem, error)
|
||||
Load(context.Context, continuity.ProspectiveItemID) (continuity.ProspectiveItem, error)
|
||||
}
|
||||
|
||||
@@ -170,6 +171,17 @@ func (w dueReminderWorker) deliverPending(ctx context.Context, now time.Time) er
|
||||
log.Printf("attention %s notification unavailable: %v", attention.ID, err)
|
||||
continue
|
||||
}
|
||||
if result.State != commitcontract.ActionSucceeded {
|
||||
_, err = w.repository.MarkAttentionFailed(ctx, delivering.ID, delivering.Revision,
|
||||
continuity.CommittedActionIntentID(result.ActionIntentID),
|
||||
continuity.CommittedAuthorizedActionID(result.AuthorizedActionID),
|
||||
continuity.CommittedActionAttemptID(result.ActionAttemptID),
|
||||
string(result.State))
|
||||
if err != nil {
|
||||
log.Printf("attention %s delivery failure outcome not persisted: %v", attention.ID, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
_, err = w.repository.MarkAttentionDelivered(ctx, delivering.ID, delivering.Revision,
|
||||
continuity.CommittedActionIntentID(result.ActionIntentID),
|
||||
continuity.CommittedAuthorizedActionID(result.AuthorizedActionID),
|
||||
|
||||
@@ -62,6 +62,18 @@ func (r *memoryDueRepo) MarkAttentionDelivered(_ context.Context, id continuity.
|
||||
return r.attention, nil
|
||||
}
|
||||
|
||||
func (r *memoryDueRepo) MarkAttentionFailed(_ context.Context, id continuity.AttentionItemID, revision continuity.AttentionRevision, intentID continuity.CommittedActionIntentID, authorizedID continuity.CommittedAuthorizedActionID, attemptID continuity.CommittedActionAttemptID, outcome string) (continuity.AttentionItem, error) {
|
||||
if r.attention.ID == id && r.attention.Revision == revision {
|
||||
r.attention.State = continuity.AttentionFailed
|
||||
r.attention.Revision++
|
||||
r.attention.ActionIntentID = intentID
|
||||
r.attention.AuthorizedActionID = authorizedID
|
||||
r.attention.ActionAttemptID = attemptID
|
||||
r.attention.DeliveryOutcome = outcome
|
||||
}
|
||||
return r.attention, nil
|
||||
}
|
||||
|
||||
func (r *memoryDueRepo) Load(context.Context, continuity.ProspectiveItemID) (continuity.ProspectiveItem, error) {
|
||||
return r.item, nil
|
||||
}
|
||||
@@ -73,6 +85,13 @@ func (n *fakeDueNotifier) NotifyDue(context.Context, continuity.ProspectiveItem)
|
||||
return dueNotificationResponse{ActionIntentID: "intent", AuthorizedActionID: "authorized", ActionAttemptID: "attempt", State: commitcontract.ActionSucceeded}, nil
|
||||
}
|
||||
|
||||
type unknownDueNotifier struct{ calls int }
|
||||
|
||||
func (n *unknownDueNotifier) NotifyDue(context.Context, continuity.ProspectiveItem) (dueNotificationResponse, error) {
|
||||
n.calls++
|
||||
return dueNotificationResponse{ActionIntentID: "intent", AuthorizedActionID: "authorized", ActionAttemptID: "attempt", State: commitcontract.ActionUnknownOutcome}, nil
|
||||
}
|
||||
|
||||
func TestDueReminderProducesAttentionAndNotificationOnce(t *testing.T) {
|
||||
repo := &memoryDueRepo{item: continuity.ProspectiveItem{ID: "prospective", OwnerPrincipalID: identity.PrincipalID("owner"), ScopeID: authority.ScopeID("scope"), Summary: "проверить уведомление", TriggerAtUnixMillis: 10, State: continuity.ProspectiveArmed, Revision: 1}}
|
||||
notifier := &fakeDueNotifier{}
|
||||
@@ -90,3 +109,17 @@ func TestDueReminderProducesAttentionAndNotificationOnce(t *testing.T) {
|
||||
t.Fatal("delivery evidence was not persisted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDueReminderUnknownOutcomeDoesNotMarkAttentionDelivered(t *testing.T) {
|
||||
repo := &memoryDueRepo{item: continuity.ProspectiveItem{ID: "prospective", OwnerPrincipalID: identity.PrincipalID("owner"), ScopeID: authority.ScopeID("scope"), Summary: "проверить уведомление", TriggerAtUnixMillis: 10, State: continuity.ProspectiveArmed, Revision: 1}}
|
||||
notifier := &unknownDueNotifier{}
|
||||
now := time.UnixMilli(20)
|
||||
worker := dueReminderWorker{repository: repo, commit: notifier, now: func() time.Time { return now }, newID: func() (ids.ID, error) { return ids.ID("attention"), nil }, limit: 10}
|
||||
worker.process(context.Background())
|
||||
if repo.attention.State != continuity.AttentionFailed {
|
||||
t.Fatalf("unknown outcome must not be delivered, got %s", repo.attention.State)
|
||||
}
|
||||
if repo.attention.DeliveryOutcome != string(commitcontract.ActionUnknownOutcome) {
|
||||
t.Fatalf("missing unknown outcome evidence: %#v", repo.attention)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/capability"
|
||||
"git.cin.su/m/Assistant/contracts/cognitive"
|
||||
"git.cin.su/m/Assistant/contracts/continuity"
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
"git.cin.su/m/Assistant/contracts/interaction"
|
||||
)
|
||||
@@ -127,3 +128,44 @@ func TestChatMessageReturnsHumanCapabilityMetadata(t *testing.T) {
|
||||
t.Fatalf("unexpected browser response: %#v", response)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChatAttentionQuestionUsesContinuityToday(t *testing.T) {
|
||||
core := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/v1/creator/sessions/current":
|
||||
_ = json.NewEncoder(w).Encode(identity.CreatorSession{ActorID: "actor-1", PrincipalID: "principal-1"})
|
||||
case r.Method == http.MethodPost && r.URL.Path == "/v1/creator/chat/messages":
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
_ = json.NewEncoder(w).Encode(interaction.ChatMessageResponse{ConversationID: "conversation-1", UtteranceID: "utterance-1", SpeechAct: interaction.SpeechActQuestion, FallbackText: "Сейчас в фокусе: УПО."})
|
||||
default:
|
||||
t.Fatalf("unexpected core route %s %s", r.Method, r.URL.Path)
|
||||
}
|
||||
}))
|
||||
defer core.Close()
|
||||
continuityRuntime := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet || r.URL.Path != "/v1/creator/today" {
|
||||
t.Fatalf("unexpected continuity route %s %s", r.Method, r.URL.Path)
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(continuity.TodayResult{Items: []continuity.TodayItem{{Title: "проверить уведомление", HumanState: "доставлено", DeliveryState: "уведомление отправлено"}}})
|
||||
}))
|
||||
defer continuityRuntime.Close()
|
||||
handler, err := newHandler(core.URL, continuityRuntime.URL, "http://commit", core.Client(), "http://cognitive")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
request := httptest.NewRequest(http.MethodPost, "/api/chat/messages", strings.NewReader(`{"message":"Что сейчас требует моего внимания?"}`))
|
||||
request.Header.Set("Authorization", "Bearer session-token")
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
if recorder.Code != http.StatusOK {
|
||||
t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
var response browserChatResponse
|
||||
if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(response.ReplyText, "проверить уведомление") || strings.Contains(response.ReplyText, "УПО") {
|
||||
t.Fatalf("attention reply did not use canonical today: %#v", response)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/capability"
|
||||
"git.cin.su/m/Assistant/contracts/cognitive"
|
||||
"git.cin.su/m/Assistant/contracts/continuity"
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
"git.cin.su/m/Assistant/contracts/interaction"
|
||||
"git.cin.su/m/Assistant/contracts/situation"
|
||||
@@ -323,6 +324,15 @@ func (g *gateway) handleChatMessage(w http.ResponseWriter, r *http.Request) {
|
||||
if saved.PlanningReply != "" {
|
||||
reply = saved.PlanningReply
|
||||
}
|
||||
if asksAttention(browserRequest.Message) {
|
||||
var today continuity.TodayResult
|
||||
status, err = g.getTrustedJSON(r, g.continuity, "/v1/creator/today", "", authorization, &today)
|
||||
if err == nil && status == http.StatusOK {
|
||||
reply = renderTodayReply(today)
|
||||
cognition = "not_requested"
|
||||
saved.NeedsCognition = false
|
||||
}
|
||||
}
|
||||
if saved.NeedsCognition && !saved.WorkPlanned && saved.Clarification != interaction.ClarificationRequired {
|
||||
cognition = "unavailable"
|
||||
requestID, idErr := ids.New()
|
||||
@@ -346,6 +356,45 @@ func (g *gateway) handleChatMessage(w http.ResponseWriter, r *http.Request) {
|
||||
_ = json.NewEncoder(w).Encode(browserChatResponse{ConversationID: string(saved.ConversationID), UtteranceID: string(saved.UtteranceID), SpeechAct: string(saved.SpeechAct), ReplyText: reply, Cognition: cognition, ActiveFocus: saved.ActiveProjectName, ProjectProvenance: string(saved.ProjectProvenance), Clarification: string(saved.Clarification), WorkPlanned: saved.WorkPlanned, CapabilityStatus: string(saved.CapabilityStatus), CapabilityKind: string(saved.CapabilityKind), ReminderScheduled: saved.Reminder != nil})
|
||||
}
|
||||
|
||||
func asksAttention(message string) bool {
|
||||
lower := strings.ToLower(message)
|
||||
return strings.Contains(lower, "требует моего внимания") || strings.Contains(lower, "требует внимания") || strings.Contains(lower, "что сейчас важно")
|
||||
}
|
||||
|
||||
func renderTodayReply(today continuity.TodayResult) string {
|
||||
if len(today.Items) == 0 {
|
||||
return "Сейчас ничего срочного не требует внимания."
|
||||
}
|
||||
limit := len(today.Items)
|
||||
if limit > 5 {
|
||||
limit = 5
|
||||
}
|
||||
var builder strings.Builder
|
||||
builder.WriteString("Сейчас требует внимания:\n")
|
||||
for index := 0; index < limit; index++ {
|
||||
item := today.Items[index]
|
||||
title := strings.TrimSpace(item.Title)
|
||||
if title == "" {
|
||||
title = "событие Домового"
|
||||
}
|
||||
state := strings.TrimSpace(item.HumanState)
|
||||
if state == "" {
|
||||
state = "ожидает внимания"
|
||||
}
|
||||
builder.WriteString("- ")
|
||||
builder.WriteString(title)
|
||||
builder.WriteString(" — ")
|
||||
builder.WriteString(state)
|
||||
if item.DeliveryState != "" {
|
||||
builder.WriteString(" (")
|
||||
builder.WriteString(item.DeliveryState)
|
||||
builder.WriteString(")")
|
||||
}
|
||||
builder.WriteString("\n")
|
||||
}
|
||||
return strings.TrimSpace(builder.String())
|
||||
}
|
||||
|
||||
func validAdvisoryResponse(response cognitive.GatewayAdvisoryResponse, request cognitive.GatewayAdvisoryRequest) bool {
|
||||
if response.Version != cognitive.CreatorAdvisoryV1 || response.RequestID != request.RequestID || len(response.ReferencedExcerptIDs) != 0 {
|
||||
return false
|
||||
|
||||
@@ -532,6 +532,20 @@ ON CONFLICT DO NOTHING;
|
||||
INSERT INTO capability.capability_implementation_heads(implementation_id, revision, capability_kind, owner_principal_id)
|
||||
VALUES ('internal-reminder-scheduler-v1', 1, 'SCHEDULE_REMINDER', 'domovoy-creator-principal')
|
||||
ON CONFLICT (implementation_id) DO NOTHING;
|
||||
INSERT INTO capability.notification_bindings (
|
||||
binding_id, capability_id, owner_principal_id, revision, state, https_origin,
|
||||
delivery_path, receipt_path, protocol, secret_ref, verified_at_unix_millis, health
|
||||
)
|
||||
VALUES (
|
||||
'domovoy-notification-binding', 'prospective-notification-delivery', 'domovoy-creator-principal',
|
||||
2, 'ACTIVE', 'https://assistant.cin.su', '/delivery/v1/deliveries', '/delivery/v1/receipts',
|
||||
'IDEMPOTENT_RECEIPT_V1', 'domovoy-notification-write-v1', 1, 'AVAILABLE'
|
||||
)
|
||||
ON CONFLICT DO NOTHING;
|
||||
INSERT INTO capability.notification_binding_heads(capability_id, owner_principal_id, binding_id, revision)
|
||||
VALUES ('prospective-notification-delivery', 'domovoy-creator-principal', 'domovoy-notification-binding', 2)
|
||||
ON CONFLICT (capability_id, owner_principal_id) DO UPDATE SET binding_id=EXCLUDED.binding_id, revision=EXCLUDED.revision
|
||||
WHERE capability.notification_binding_heads.revision < EXCLUDED.revision;
|
||||
RESET ROLE;
|
||||
|
||||
SET ROLE continuity_role;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
BEGIN;
|
||||
|
||||
SET ROLE capability_role;
|
||||
|
||||
INSERT INTO capability.notification_bindings (
|
||||
binding_id, capability_id, owner_principal_id, revision, state, https_origin,
|
||||
delivery_path, receipt_path, protocol, secret_ref, verified_at_unix_millis, health
|
||||
)
|
||||
VALUES (
|
||||
'domovoy-notification-binding',
|
||||
'prospective-notification-delivery',
|
||||
'domovoy-creator-principal',
|
||||
2,
|
||||
'ACTIVE',
|
||||
'https://assistant.cin.su',
|
||||
'/delivery/v1/deliveries',
|
||||
'/delivery/v1/receipts',
|
||||
'IDEMPOTENT_RECEIPT_V1',
|
||||
'domovoy-notification-write-v1',
|
||||
FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::bigint,
|
||||
'AVAILABLE'
|
||||
)
|
||||
ON CONFLICT (binding_id, revision) DO UPDATE SET
|
||||
https_origin = EXCLUDED.https_origin,
|
||||
verified_at_unix_millis = EXCLUDED.verified_at_unix_millis,
|
||||
health = EXCLUDED.health;
|
||||
|
||||
INSERT INTO capability.notification_binding_heads (
|
||||
capability_id, owner_principal_id, binding_id, revision
|
||||
)
|
||||
VALUES (
|
||||
'prospective-notification-delivery',
|
||||
'domovoy-creator-principal',
|
||||
'domovoy-notification-binding',
|
||||
2
|
||||
)
|
||||
ON CONFLICT (capability_id, owner_principal_id) DO UPDATE SET
|
||||
binding_id = EXCLUDED.binding_id,
|
||||
revision = EXCLUDED.revision
|
||||
WHERE capability.notification_binding_heads.revision < EXCLUDED.revision;
|
||||
|
||||
RESET ROLE;
|
||||
COMMIT;
|
||||
@@ -4,19 +4,22 @@ Audit date: 2026-08-17. Active implementation: DEV-000065 revision 1.
|
||||
|
||||
## DEV-000065 checkpoint
|
||||
|
||||
- `DEV_000065_STATUS = IN_PROGRESS`
|
||||
- `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`
|
||||
- `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`
|
||||
- `ADR_STATUS = ADR-0014 accepted`
|
||||
- `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_DELIVERY_STATUS = implemented through Commit deliver-prospective-notification-v1 path; production live verification pending`
|
||||
- `REMINDER_DELIVERY_STATUS = PASS: production live delayed reminder delivered through Commit deliver-prospective-notification-v1 and immutable receiver receipt`
|
||||
- `ATTENTION_STATUS = typed AttentionItem PENDING -> DELIVERING -> DELIVERED foundation implemented`
|
||||
- `HUMAN_SURFACE_STATUS = /chat remains primary; Today/Attention and History added; Operator Console preserved at /`
|
||||
- `AUTHORITY_STATUS = external notification still requires Commit authorization, current Creator authority context, and active Capability notification binding`
|
||||
- `LLM_FREE_STATUS = deterministic reminder firing does not require cognitive model; LLM-free env policy regression PASS`
|
||||
- `TESTS_PASS_SO_FAR = 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`
|
||||
- `PRODUCTION_STATUS = pending deploy/live acceptance`
|
||||
- `NEXT_STEP = apply migration, deploy affected services, run owner ACL and live delayed reminder acceptance, then promote if PASS`
|
||||
- `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 live delayed reminder acceptance; production /chat attention and capability-gap acceptance`
|
||||
- `LIVE_ACCEPTANCE = PASS: "Напомни мне через 3 минуты проверить уведомление." persisted ARMED reminder, transitioned to DELIVERED, generated AttentionItem, delivered notification through Commit, persisted SUCCEEDED attempt and receiver receipt, duplicate counts action_attempts=1 attention_items=1; "Отправь Ивану письмо." returned readable capability gap; "Что сейчас требует моего внимания?" answered from canonical Today with cognition=not_requested`
|
||||
- `PRODUCTION_STATUS = healthy`
|
||||
- `PRODUCTION_REVISION = origin/main 1113ced623896f1498d606653d71f36c361e9bb0; creator-web deployed at 1113ced623896f1498d606653d71f36c361e9bb0; continuity-runtime deployed at 2ec53e40cf19c609193c1aa74955573cac7abfe1; core-runtime/commit-runtime deployed at a0dce634f3c6efec0481f730c9dcc12797749ec4`
|
||||
- `KNOWN_LIMITATION = one early DEV-000065 live probe occurred before notification binding origin revision 2 and produced UNKNOWN_OUTCOME; later regression prevents UNKNOWN_OUTCOME from being marked as delivered`
|
||||
- `NEXT_STEP = Human response operations for attention/reminders: Done/Snooze/Cancel semantic commands, if separately approved`
|
||||
|
||||
## DEV-000064 checkpoint
|
||||
|
||||
|
||||
@@ -15,5 +15,6 @@ type Repository interface {
|
||||
PendingAttention(context.Context, int) ([]continuity.AttentionItem, error)
|
||||
MarkAttentionDelivering(context.Context, continuity.AttentionItemID, continuity.AttentionRevision) (continuity.AttentionItem, error)
|
||||
MarkAttentionDelivered(context.Context, continuity.AttentionItemID, continuity.AttentionRevision, continuity.CommittedActionIntentID, continuity.CommittedAuthorizedActionID, continuity.CommittedActionAttemptID, string, int64) (continuity.AttentionItem, error)
|
||||
MarkAttentionFailed(context.Context, continuity.AttentionItemID, continuity.AttentionRevision, continuity.CommittedActionIntentID, continuity.CommittedAuthorizedActionID, continuity.CommittedActionAttemptID, string) (continuity.AttentionItem, error)
|
||||
AttentionByOwner(context.Context, identity.PrincipalID, int) ([]continuity.AttentionItem, error)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user