Compare commits

..
Author SHA1 Message Date
m 29b20bc5b0 DEV-000066 record production acceptance status
CI / test (push) Successful in 16s
CI / test (pull_request) Successful in 15s
2026-08-17 17:43:43 +03:00
m 071adb5ecb Promote DEV-000066 response candidate ordering
CI / test (push) Successful in 16s
DEV-000066 response candidate ordering follow-up
2026-08-17 14:38:15 +00:00
m 465a90b25d DEV-000066 prefer recent response candidates
CI / test (push) Successful in 16s
CI / test (pull_request) Successful in 16s
2026-08-17 17:37:20 +03:00
m 95d6ad2d6a Promote DEV-000066 response candidate window
CI / test (push) Successful in 19s
DEV-000066 response candidate window follow-up
2026-08-17 14:33:57 +00:00
m 1e554f6758 DEV-000066 widen response candidate resolution
CI / test (push) Successful in 16s
CI / test (pull_request) Successful in 16s
2026-08-17 17:33:05 +03:00
m 1c7d512710 Promote DEV-000066 prospective response summary resolution
CI / test (push) Successful in 16s
DEV-000066 prospective response summary resolution follow-up
2026-08-17 14:21:41 +00:00
5 changed files with 23 additions and 6 deletions
+2 -2
View File
@@ -214,7 +214,7 @@ func (r *ContinuityRepository) AttentionByOwner(ctx context.Context, owner ident
}
func (r *ContinuityRepository) ResponseCandidates(ctx context.Context, owner identity.PrincipalID, limit int) ([]continuitydomain.ResponseCandidate, error) {
if owner == "" || limit < 1 || limit > 10 {
if owner == "" || limit < 1 || limit > 50 {
return nil, fmt.Errorf("invalid response candidate query")
}
rows, err := r.pool.Query(ctx, `SELECT
@@ -227,7 +227,7 @@ func (r *ContinuityRepository) ResponseCandidates(ctx context.Context, owner ide
WHERE p.owner_principal_id=$1
AND (a.attention_item_id IS NULL OR a.state IN ($3,$4,$5))
AND p.state IN ($6,$7)
ORDER BY COALESCE(a.delivered_at_unix_millis,0) DESC, p.trigger_at_unix_millis DESC, p.prospective_item_id DESC
ORDER BY p.recorded_at DESC, COALESCE(a.delivered_at_unix_millis,0) DESC, p.prospective_item_id DESC
LIMIT $8`,
owner, continuity.AttentionSourceProspectiveReminder, continuity.AttentionDelivered, continuity.AttentionPending,
continuity.AttentionFailed, continuity.ProspectiveDelivered, continuity.ProspectiveArmed, limit)
+1 -1
View File
@@ -42,7 +42,7 @@ func registerCreatorResponseRoute(mux *http.ServeMux, identityClient creatorIden
http.Error(w, "human response unavailable", http.StatusServiceUnavailable)
return
}
candidates, err := repository.ResponseCandidates(r.Context(), session.PrincipalID, 3)
candidates, err := repository.ResponseCandidates(r.Context(), session.PrincipalID, 20)
if err != nil {
http.Error(w, "response candidates unavailable", http.StatusInternalServerError)
return
+4 -3
View File
@@ -4,7 +4,7 @@ Audit date: 2026-08-17. Active implementation: DEV-000066 revision 1.
## DEV-000066 checkpoint
- `DEV_000066_STATUS = IMPLEMENTED_NOT_PROMOTED`
- `DEV_000066_STATUS = PRODUCTION_ACTIVE`
- `LAST_COMPLETED = ADR-0015 accepted; Continuity-owned HumanResponse contract foundation; ResponseTargetResolution semantics; append-only human_responses migration; Attention response projection fields; deterministic COMPLETE/SNOOZE/CANCEL/DISMISS interpretation; Creator Web response buttons over ordinary /chat; ActiveProjectFocus leak regression under Interaction semantics`
- `ADR_STATUS = ADR-0015 accepted`
- `OWNERSHIP_STATUS = no new owner; HumanResponse and response target resolution belong to Continuity; Interaction remains utterance/original-intent owner`
@@ -14,8 +14,9 @@ Audit date: 2026-08-17. Active implementation: DEV-000066 revision 1.
- `AUTHORITY_STATUS = no new external mutation authority; human reported completion is not verified world truth`
- `LLM_FREE_STATUS = obvious response operations are deterministic and do not require cognitive model`
- `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`
- `LIVE_ACCEPTANCE = pending production deployment`
- `PRODUCTION_STATUS = pending promotion/deployment`
- `LIVE_ACCEPTANCE = PASS: external /chat created real reminders; SNOOZE after delivery re-armed the same ProspectiveItem and redelivered once without duplicate AttentionItem; COMPLETE after delivery closed Attention as USER_REPORTED_COMPLETE; CANCEL before delivery suppressed ProspectiveItem and produced no AttentionItem after due window; stale UPO ActiveProjectFocus cleared`
- `PRODUCTION_STATUS = healthy`
- `PRODUCTION_REVISION = 071adb5ecbf31325678a557c371c512c486d8274`
- `ACTIVE_COGNITIVE_BINDINGS = none; CPU CANARY unchanged`
- `OPENAI_REAL_CREDENTIAL = not required / not activated`
@@ -153,6 +153,9 @@ func candidateSummary(candidates []ResponseCandidate) string {
parts := make([]string, 0, len(candidates))
for _, candidate := range candidates {
text := strings.TrimSpace(candidate.Attention.Summary)
if text == "" {
text = strings.TrimSpace(candidate.Prospective.Summary)
}
if text == "" {
text = "ожидание"
}
@@ -53,6 +53,19 @@ func TestInterpretHumanResponseResolvesArmedProspectiveByNaturalSummaryReference
}
}
func TestInterpretHumanResponseResolvesSummaryReferenceBeyondFirstThreeCandidates(t *testing.T) {
candidates := []ResponseCandidate{
responseCandidate("a1", "p1", "первое ожидание"),
responseCandidate("a2", "p2", "второе ожидание"),
responseCandidate("a3", "p3", "третье ожидание"),
{Prospective: continuity.ProspectiveItem{ID: "p4", OwnerPrincipalID: "principal-1", ScopeID: "scope-1", Summary: "встретить курьера", State: continuity.ProspectiveArmed, Revision: 1}},
}
result := interpretResponseForTest(t, "Отмени встретить курьера", candidates)
if !result.Handled || result.Response.ResolutionState != continuity.ResponseResolved || result.Response.TargetProspectiveID != "p4" {
t.Fatalf("expected target resolution beyond first three candidates, got %#v", result)
}
}
func TestInterpretHumanResponseAmbiguousTargetAsksClarificationWithoutResolvedMutation(t *testing.T) {
result := interpretResponseForTest(t, "Готово", []ResponseCandidate{responseCandidate("a1", "p1", "первое"), responseCandidate("a2", "p2", "второе")})
if !result.Handled || result.Response.ResolutionState != continuity.ResponseAmbiguous || result.Response.Outcome != continuity.ResponseOutcomeClarificationNeeded || !strings.Contains(result.Reply, "несколько") {