Compare commits

..
Author SHA1 Message Date
m 21239cf3cc DEV-000068 allow armed reminder completion
CI / test (push) Successful in 18s
CI / test (pull_request) Successful in 17s
2026-08-17 19:20:28 +03:00
m 75857a2036 DEV-000068 normalize Epistemics evidence arrays
CI / test (push) Successful in 21s
Merge DEV-000068 Epistemics empty array normalization
2026-08-17 16:14:44 +00:00
m 9a9307af89 DEV-000068 normalize epistemics evidence arrays
CI / test (push) Successful in 17s
CI / test (pull_request) Successful in 16s
2026-08-17 19:14:01 +03:00
m ff66e8dc5c DEV-000068 learning write diagnostics
CI / test (push) Successful in 27s
Merge DEV-000068 learning diagnostics
2026-08-17 16:08:56 +00:00
m a862a07ae1 DEV-000068 add learning write diagnostics
CI / test (push) Successful in 33s
CI / test (pull_request) Successful in 26s
2026-08-17 19:08:14 +03:00
m 4d63c1bea4 DEV-000068 support strong Postgres credentials
CI / test (push) Successful in 16s
Merge DEV-000068 strong Postgres credential support
2026-08-17 15:59:02 +00:00
m 91c38de167 DEV-000068 support strong postgres credentials
CI / test (push) Successful in 17s
CI / test (pull_request) Successful in 16s
2026-08-17 18:58:18 +03:00
m 926afc82b5 DEV-000068 production status and dev bootstrap compatibility
CI / test (push) Successful in 21s
Merge DEV-000068 production status follow-up
2026-08-17 15:49:29 +00:00
m 4a066d71f4 DEV-000068 finalize production learning status
CI / test (push) Successful in 38s
CI / test (pull_request) Successful in 29s
2026-08-17 18:47:55 +03:00
m 7fc611ed08 Merge DEV-000068 runtime experience reflection loop v1
CI / test (push) Successful in 17s
DEV-000068 promoted
2026-08-17 15:36:30 +00:00
15 changed files with 85 additions and 23 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ import (
type AuthorityRepository struct{ pool *pgxpool.Pool }
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 {
return nil, e
}
+1 -2
View File
@@ -19,8 +19,7 @@ var ErrCapabilityImplementationNotFound = errors.New("capability implementation
type CapabilityRepository struct{ pool *pgxpool.Pool }
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 := pgxpool.New(ctx, dsn)
pool, err := openPool(ctx, config)
if err != nil {
return nil, err
}
+1 -1
View File
@@ -23,7 +23,7 @@ var (
type CommitRepository struct{ pool *pgxpool.Pool }
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 {
return nil, e
}
+23 -7
View File
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"strconv"
"git.cin.su/m/Assistant/contracts/authority"
"git.cin.su/m/Assistant/contracts/continuity"
@@ -29,9 +30,25 @@ var (
type ContinuityConfig struct{ Host, Port, Database, User, Password string }
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) {
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 := pgxpool.New(ctx, dsn)
pool, err := openPool(ctx, config)
if err != nil {
return nil, err
}
@@ -317,11 +334,10 @@ func (r *ContinuityRepository) ApplyHumanResponse(ctx context.Context, response
if tag.RowsAffected() != 1 {
return ErrProspectiveStateConflict
}
if response.TargetAttentionID == "" {
return ErrAttentionNotFound
}
if err = markAttentionResponded(ctx, tx, response, continuity.AttentionResolved); err != nil {
return err
if response.TargetAttentionID != "" {
if err = markAttentionResponded(ctx, tx, response, continuity.AttentionResolved); err != nil {
return err
}
}
case continuity.ResponseSnooze:
tag, err := tx.Exec(ctx, `UPDATE continuity.prospective_items SET state=$1, trigger_at_unix_millis=$2, revision=revision+1
+1 -2
View File
@@ -11,8 +11,7 @@ import (
type EpistemicsRepository struct{ pool *pgxpool.Pool }
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 := pgxpool.New(ctx, dsn)
pool, err := openPool(ctx, config)
if err != nil {
return nil, err
}
+1 -1
View File
@@ -11,7 +11,7 @@ import (
type IdentityRepository struct{ pool *pgxpool.Pool }
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 {
return nil, err
}
+1 -2
View File
@@ -2,7 +2,6 @@ package postgres
import (
"context"
"fmt"
"git.cin.su/m/Assistant/contracts/interaction"
"github.com/jackc/pgx/v5/pgxpool"
@@ -11,7 +10,7 @@ import (
type InteractionRepository struct{ pool *pgxpool.Pool }
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
}
func (r *InteractionRepository) Close() { r.pool.Close() }
+1 -3
View File
@@ -2,7 +2,6 @@ package postgres
import (
"context"
"fmt"
"strings"
"git.cin.su/m/Assistant/contracts/identity"
@@ -13,8 +12,7 @@ import (
type SituationRepository struct{ pool *pgxpool.Pool }
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 := pgxpool.New(ctx, dsn)
pool, err := openPool(ctx, config)
if err != nil {
return nil, err
}
+1 -2
View File
@@ -11,8 +11,7 @@ import (
type WorkRepository struct{ pool *pgxpool.Pool }
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 := pgxpool.New(ctx, dsn)
pool, err := openPool(ctx, config)
if err != nil {
return nil, err
}
+17 -2
View File
@@ -2,6 +2,7 @@ package main
import (
"context"
"log"
"strings"
"time"
@@ -85,7 +86,12 @@ func (r learningRecorder) recordReminderResponse(ctx context.Context, input remi
RecordedAtUnixMillis: input.At.UnixMilli(),
}
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
}
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) {
value, err := epistemicsdomain.NewExperienceRecord(value)
if err != nil {
log.Printf("learning experience invalid: %v", err)
return epistemics.ExperienceRecord{}, false
}
if err := r.epistemics.SaveExperienceRecord(ctx, value); err != nil {
log.Printf("learning experience unavailable: %v", err)
return epistemics.ExperienceRecord{}, false
}
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
}
@@ -214,6 +226,7 @@ func (r learningRecorder) updateReminderSkill(ctx context.Context, experience ep
}
profile, err := r.capability.LoadSkillProfile(ctx, reminderResponseSkillID)
if err != nil {
log.Printf("learning skill profile unavailable: %v", err)
return
}
next, err := capabilitydomain.ObserveSkillOutcome(profile, capability.SkillOutcomeObservation{
@@ -223,9 +236,11 @@ func (r learningRecorder) updateReminderSkill(ctx context.Context, experience ep
ObservedAtUnixMillis: experience.RecordedAtUnixMillis,
})
if err != nil {
log.Printf("learning skill observation invalid: %v", err)
return
}
if err := r.capability.SaveSkillProfile(ctx, next); err != nil {
log.Printf("learning skill profile save unavailable: %v", err)
return
}
}
+3
View File
@@ -201,16 +201,19 @@ func main() {
}
experiences, err := epistemicsRepository.RecentExperienceRecords(r.Context(), limit)
if err != nil {
log.Printf("learning recent experiences unavailable: %v", err)
http.Error(w, "learning experience unavailable", http.StatusServiceUnavailable)
return
}
reflections, err := epistemicsRepository.RecentReflectionCandidates(r.Context(), limit)
if err != nil {
log.Printf("learning recent reflections unavailable: %v", err)
http.Error(w, "learning reflection unavailable", http.StatusServiceUnavailable)
return
}
skills, err := capabilityRepository.RecentSkillProfiles(r.Context(), limit)
if err != nil {
log.Printf("learning recent skills unavailable: %v", err)
http.Error(w, "learning skills unavailable", http.StatusServiceUnavailable)
return
}
+3
View File
@@ -12,6 +12,7 @@ services:
SITUATION_DB_PASSWORD: ${SITUATION_DB_PASSWORD:-assistant_situation_dev_only}
WORK_DB_PASSWORD: ${WORK_DB_PASSWORD:-assistant_work_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}
ports: ["15432:5432"]
volumes:
@@ -50,6 +51,8 @@ services:
WORK_POSTGRES_PASSWORD: ${WORK_DB_PASSWORD:-assistant_work_dev_only}
CAPABILITY_POSTGRES_USER: capability_role
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"]
depends_on:
postgres: { condition: service_healthy }
@@ -31,6 +31,7 @@
"cmd/core-runtime/**",
"cmd/creator-web/**",
"cmd/continuity-runtime/**",
"deploy/docker-compose.dev.yml",
"deploy/docker-compose.prod.yml",
"deploy/images/002_owner_passwords.sh",
"deploy/windows/**",
+18
View File
@@ -44,6 +44,24 @@ Audit date: 2026-08-17. Active implementation: DEV-000067 revision 1.
- `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`
## 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`
- `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`
+12
View File
@@ -25,6 +25,9 @@ func NewSystemExpectation(value epistemics.SystemExpectation) (epistemics.System
value.RecordedAtUnixMillis < 1 {
return epistemics.SystemExpectation{}, ErrInvalidExpectation
}
if value.EvidenceBasis == nil {
value.EvidenceBasis = []epistemics.EvidenceRef{}
}
return value, nil
}
@@ -41,6 +44,12 @@ func NewExperienceRecord(value epistemics.ExperienceRecord) (epistemics.Experien
value.ConfidenceMillis < 0 || value.ConfidenceMillis > 1000 || value.RecordedAtUnixMillis < 1 {
return epistemics.ExperienceRecord{}, ErrInvalidExperience
}
if value.ContextRefs == nil {
value.ContextRefs = []epistemics.ContextRef{}
}
if value.VerificationEvidence == nil {
value.VerificationEvidence = []epistemics.EvidenceRef{}
}
return value, nil
}
@@ -81,6 +90,9 @@ func ValidateReflectionCandidate(value epistemics.ReflectionCandidate) error {
value.RecordedAtUnixMillis < 1 || value.Revision < 1 {
return ErrInvalidReflectionCandidate
}
if value.EvidenceRefs == nil {
value.EvidenceRefs = []epistemics.EvidenceRef{}
}
return nil
}