This commit is contained in:
@@ -98,6 +98,10 @@ func (r *CapabilityRepository) SaveBinding(ctx context.Context, binding capabili
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tx.Exec(ctx, `INSERT INTO capability.cognitive_binding_revision_heads (binding_id,revision) VALUES ($1,$2) ON CONFLICT DO NOTHING`, binding.ID, binding.Revision)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
@@ -157,13 +161,12 @@ func (r *CapabilityRepository) SaveCognitiveBinding(ctx context.Context, value c
|
||||
}
|
||||
|
||||
func (r *CapabilityRepository) LoadCognitiveCandidates(ctx context.Context, capabilityID capability.CapabilityID, owner identity.PrincipalID) ([]capability.ResolvedCognitiveBinding, error) {
|
||||
rows, err := r.pool.Query(ctx, `WITH latest_bindings AS (
|
||||
SELECT DISTINCT ON (binding_id) * FROM capability.cognitive_bindings ORDER BY binding_id,revision DESC
|
||||
) SELECT
|
||||
rows, err := r.pool.Query(ctx, `SELECT
|
||||
b.binding_id,b.revision,b.capability_id,b.owner_principal_id,b.provider_instance_id,b.provider_revision,b.model_descriptor_id,b.model_revision,b.data_policy,b.qualification,b.activation,b.health,b.limit_policy_ref,
|
||||
p.provider_instance_id,p.revision,p.provider_kind,p.endpoint_ref,COALESCE(p.credential_ref,''),p.enabled,p.qualification,COALESCE(ph.health,p.health),GREATEST(p.observed_at_unix_millis,COALESCE(ph.observed_at_unix_millis,0)),
|
||||
m.model_descriptor_id,m.revision,m.provider_instance_id,m.provider_model_id,m.fingerprint,m.max_context_bytes,m.modalities,m.capabilities,m.qualification,COALESCE(ma.health,m.health),GREATEST(m.observed_at_unix_millis,COALESCE(ma.observed_at_unix_millis,0))
|
||||
FROM latest_bindings b
|
||||
FROM capability.cognitive_binding_revision_heads bh
|
||||
JOIN capability.cognitive_bindings b ON b.binding_id=bh.binding_id AND b.revision=bh.revision
|
||||
JOIN capability.cognitive_provider_instances p ON p.provider_instance_id=b.provider_instance_id AND p.revision=b.provider_revision
|
||||
JOIN capability.cognitive_model_descriptors m ON m.model_descriptor_id=b.model_descriptor_id AND m.revision=b.model_revision
|
||||
LEFT JOIN capability.cognitive_provider_health ph ON ph.provider_instance_id=p.provider_instance_id
|
||||
@@ -257,6 +260,35 @@ func (r *CapabilityRepository) SaveEvaluatedCapability(ctx context.Context, valu
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CapabilityRepository) SaveCognitiveCanaryPromotion(ctx context.Context, value capability.CognitiveCanaryPromotion) error {
|
||||
tx, err := r.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = tx.Rollback(ctx) }()
|
||||
p, m, b, e := value.Provider, value.Model, value.Binding, value.Evaluation
|
||||
if _, err = tx.Exec(ctx, `INSERT INTO capability.cognitive_provider_instances (provider_instance_id,revision,provider_kind,endpoint_ref,credential_ref,enabled,qualification,health,observed_at_unix_millis) VALUES ($1,$2,$3,$4,NULLIF($5,''),$6,$7,$8,$9) ON CONFLICT DO NOTHING`, p.ID, p.Revision, p.Kind, p.EndpointRef, p.CredentialRef, p.Enabled, p.Qualification, p.Health, p.ObservedAtUnixMillis); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = tx.Exec(ctx, `INSERT INTO capability.cognitive_model_descriptors (model_descriptor_id,revision,provider_instance_id,provider_model_id,fingerprint,max_context_bytes,modalities,capabilities,qualification,health,observed_at_unix_millis) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11) ON CONFLICT DO NOTHING`, m.ID, m.Revision, m.ProviderInstanceID, m.ProviderModelID, m.Fingerprint, m.MaxContextBytes, m.Modalities, m.Capabilities, m.Qualification, m.Health, m.ObservedAtUnixMillis); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = tx.Exec(ctx, `INSERT INTO capability.cognitive_bindings (binding_id,revision,capability_id,owner_principal_id,provider_instance_id,provider_revision,model_descriptor_id,model_revision,data_policy,qualification,activation,health,limit_policy_ref) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13) ON CONFLICT DO NOTHING`, b.ID, b.Revision, b.CapabilityID, b.OwnerPrincipalID, b.ProviderInstanceID, b.ProviderRevision, b.ModelDescriptorID, b.ModelRevision, b.DataPolicy, b.Qualification, b.Activation, b.Health, b.LimitPolicyRef); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = tx.Exec(ctx, `INSERT INTO capability.cognitive_evaluated_capabilities (evaluation_id,binding_id,binding_revision,capability_id,result,quality_score_millis,critical_failure_millis,benchmark_version,artifact_id,observed_at_unix_millis) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10) ON CONFLICT DO NOTHING`, e.ID, e.BindingID, e.BindingRevision, e.CapabilityID, e.Result, e.QualityScoreMillis, e.CriticalFailureMillis, e.BenchmarkVersion, e.ArtifactID, e.ObservedAtUnixMillis); err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := tx.Exec(ctx, `UPDATE capability.cognitive_binding_revision_heads SET revision=$1,updated_at=CURRENT_TIMESTAMP WHERE binding_id=$2 AND revision=$3`, b.Revision, b.ID, value.ExpectedBindingRevision)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if result.RowsAffected() != 1 {
|
||||
return ErrCapabilityBindingConflict
|
||||
}
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
|
||||
func (r *CapabilityRepository) SavePerformanceEvidence(ctx context.Context, value capability.PerformanceEvidence) error {
|
||||
_, err := r.pool.Exec(ctx, `INSERT INTO capability.cognitive_performance_evidence (evidence_id,binding_id,binding_revision,model_descriptor_id,model_revision,hardware_profile,runtime,quantization,context_units,thinking_enabled,generation_tps_millis,prompt_tps_millis,ttft_micros,latency_micros,memory_bytes,reliability_millis,benchmark_version,artifact_id,observed_at_unix_millis) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19) ON CONFLICT DO NOTHING`, value.ID, value.BindingID, value.BindingRevision, value.ModelDescriptorID, value.ModelRevision, value.HardwareProfile, value.Runtime, value.Quantization, value.ContextUnits, value.ThinkingEnabled, value.GenerationTPSMillis, value.PromptTPSMillis, value.TTFTMicros, value.LatencyMicros, value.MemoryBytes, value.ReliabilityMillis, value.BenchmarkVersion, value.ArtifactID, value.ObservedAtUnixMillis)
|
||||
return err
|
||||
|
||||
@@ -277,6 +277,45 @@ func main() {
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
})
|
||||
mux.HandleFunc("POST /v1/creator/cognitive-canary", func(w http.ResponseWriter, r *http.Request) {
|
||||
session, ok := authenticateCreator(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var request capability.CognitiveCanaryPromotionRequest
|
||||
decoder := json.NewDecoder(io.LimitReader(r.Body, 16<<10))
|
||||
decoder.DisallowUnknownFields()
|
||||
if err := decoder.Decode(&request); err != nil {
|
||||
http.Error(w, "invalid canary promotion", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
request.RequestedByPrincipalID = session.PrincipalID
|
||||
request.CapabilityID = "creator-advisory"
|
||||
candidates, err := capabilityRepository.LoadCognitiveCandidates(r.Context(), request.CapabilityID, session.PrincipalID)
|
||||
if err != nil {
|
||||
http.Error(w, "cognitive registry unavailable", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
var current capability.ResolvedCognitiveBinding
|
||||
for _, candidate := range candidates {
|
||||
if candidate.Binding.ID == request.BindingID && candidate.Binding.Revision == request.ExpectedBindingRevision {
|
||||
current = candidate
|
||||
break
|
||||
}
|
||||
}
|
||||
promotion, err := capabilitydomain.BuildCanaryPromotion(request, current)
|
||||
if err != nil {
|
||||
http.Error(w, "canary promotion precondition failed", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
if err = capabilityRepository.SaveCognitiveCanaryPromotion(r.Context(), promotion); err != nil {
|
||||
http.Error(w, "canary promotion conflict", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
_ = json.NewEncoder(w).Encode(promotion)
|
||||
})
|
||||
mux.HandleFunc("POST /v1/cognitive-registry/performance-evidence", func(w http.ResponseWriter, r *http.Request) {
|
||||
var value capability.PerformanceEvidence
|
||||
decoder := json.NewDecoder(io.LimitReader(r.Body, 64<<10))
|
||||
|
||||
@@ -183,6 +183,29 @@ type CognitiveDiscoveryRegistration struct {
|
||||
ModelAvailability []ModelOperationalObservation
|
||||
}
|
||||
|
||||
type CognitiveCanaryPromotionRequest struct {
|
||||
PromotionID ids.ID
|
||||
RequestedByPrincipalID identity.PrincipalID
|
||||
CapabilityID CapabilityID
|
||||
BindingID CapabilityBindingID
|
||||
ExpectedBindingRevision int64
|
||||
ProviderInstanceID ProviderInstanceID
|
||||
ExpectedProviderRevision int64
|
||||
ModelDescriptorID ModelDescriptorID
|
||||
ExpectedModelRevision int64
|
||||
EvaluationID EvaluationID
|
||||
ObservedAtUnixMillis int64
|
||||
}
|
||||
|
||||
type CognitiveCanaryPromotion struct {
|
||||
PromotionID ids.ID
|
||||
ExpectedBindingRevision int64
|
||||
Provider ProviderInstance
|
||||
Model ModelDescriptor
|
||||
Binding CognitiveBinding
|
||||
Evaluation EvaluatedCapability
|
||||
}
|
||||
|
||||
// CognitiveDiscoverySnapshot is provider-neutral observed inventory submitted
|
||||
// to the Capability owner. The owner assigns immutable revisions and always
|
||||
// registers discovered bindings as DISCOVERED/INACTIVE.
|
||||
|
||||
@@ -221,6 +221,11 @@ CREATE TABLE IF NOT EXISTS capability.cognitive_binding_heads (
|
||||
capability_id TEXT NOT NULL, owner_principal_id TEXT NOT NULL, binding_id TEXT NOT NULL,
|
||||
revision BIGINT NOT NULL, PRIMARY KEY (capability_id, owner_principal_id), CHECK (revision > 0)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS capability.cognitive_binding_revision_heads (
|
||||
binding_id TEXT PRIMARY KEY,
|
||||
revision BIGINT NOT NULL CHECK (revision > 0),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS capability.cognitive_usage_observations (
|
||||
observation_id TEXT PRIMARY KEY, request_id TEXT NOT NULL, binding_id TEXT NOT NULL,
|
||||
binding_revision BIGINT NOT NULL, provider_instance_id TEXT NOT NULL, model_descriptor_id TEXT NOT NULL,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
BEGIN;
|
||||
SET ROLE capability_role;
|
||||
CREATE TABLE IF NOT EXISTS capability.cognitive_binding_revision_heads (
|
||||
binding_id TEXT PRIMARY KEY,
|
||||
revision BIGINT NOT NULL CHECK (revision > 0),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
INSERT INTO capability.cognitive_binding_revision_heads (binding_id,revision)
|
||||
SELECT DISTINCT ON (binding_id) binding_id,revision
|
||||
FROM capability.cognitive_bindings
|
||||
ORDER BY binding_id,recorded_at DESC
|
||||
ON CONFLICT DO NOTHING;
|
||||
RESET ROLE;
|
||||
COMMIT;
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"task_file": "dev/tasks/DEV-000057-local-cognitive-qualification.json",
|
||||
"task_id": "DEV-000057",
|
||||
"task_file": "dev/tasks/DEV-000058-local-cognitive-canary.json",
|
||||
"task_id": "DEV-000058",
|
||||
"task_revision": 1
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"task_id": "DEV-000058",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "ADR-0008",
|
||||
"base_repo_revision": "ac5c6cbd30d6cdd588d392e62180df105cff3829",
|
||||
"risk_tier": "E",
|
||||
"intent": "Add an authenticated, append-only and evidence-gated Capability lifecycle transition for one exact local CPU binding revision, promote it to CANARY with CAS semantics, and prove bounded advisory invocation without granting model output any authority.",
|
||||
"requirement_ids": ["INV-OWN-001", "INV-EPI-001", "ADR-0006", "ADR-0008", "LOCAL-COGNITIVE-CANARY-STAGE-1"],
|
||||
"allowed_change_scope": {
|
||||
"modules": ["capability"],
|
||||
"paths": ["contracts/capability/**", "modules/capability/**", "adapters/postgres/**", "database/migrations/**", "database/bootstrap/**", "cmd/core-runtime/**", "tests/cognitive_registry/**", "tests/cognitive_router/**", "tests/cognitive_canary/**", "docs/evidence/**", "docs/PROJECT_STATUS.md", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000058-local-cognitive-canary.json"]
|
||||
},
|
||||
"forbidden_change_scope": {
|
||||
"paths": ["architecture/**", "contracts/identity/**", "contracts/authority/**", "modules/identity/**", "modules/authority/**", "modules/situation/**", "modules/work/**", "modules/continuity/**", "modules/commit/**", "deploy/**", "security/**", "ci/**", ".gitea/**", "cmd/devctl/**", "cmd/cognitive-worker/**", "cmd/creator-web/**"]
|
||||
},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies":0,"new_canonical_owners":0,"new_privileges":0,"new_third_party_dependencies":0,"new_provider_adapters":0},
|
||||
"contracts": {"consume":["CreatorSession","Capability Cognitive Registry","EvaluatedCapability","ADR-0008"],"may_change":["contracts.capability cognitive lifecycle transition"]},
|
||||
"semantic_owner": "capability",
|
||||
"canonical_state": ["append-only validated ProviderInstance revision", "append-only validated ModelDescriptor revision", "append-only canary CognitiveBinding revision", "per-binding current revision head", "evidence reference copied to exact promoted binding revision"],
|
||||
"state_transitions": ["DISCOVERED/INACTIVE to VALIDATED/CANARY for one exact binding lineage only", "no ACTIVE transition"],
|
||||
"side_effects_and_privileges": ["authenticated Creator-directed owner-local Capability mutation", "bounded local CPU advisory smoke after successful canary", "no external mutation", "no OpenAI request", "no Commit or Executor privilege"],
|
||||
"persistence_and_migrations": ["Capability-owned binding revision head table and deterministic backfill", "append-only existing registry/evaluation tables", "no cross-owner relation", "no event"],
|
||||
"failure_retry_restart": ["expected-revision CAS", "stale promotion fails conflict", "same PromotionID is idempotent", "no automatic inference retry", "rollback appends an INACTIVE revision in a later explicit transition rather than deleting history"],
|
||||
"assumptions": ["the Creator's explicit continuation authorizes canary for the recommended exact CPU Qwen2.5-3B binding", "GPU qwen3:8b remains inactive fallback candidate", "docker-test remains prohibited"],
|
||||
"acceptance_scenarios": ["unauthenticated promotion denied", "unsupported evidence denied", "stale revision denied", "exact supported CPU revision becomes CANARY", "all other bindings remain INACTIVE", "router selects canary only when AllowCanary=true", "LLM output remains advisory and non-canonical"],
|
||||
"required_tests": ["domain transition", "repository CAS", "authenticated endpoint", "router head selection", "migration and DB ownership", "production canary smoke", "go test ./...", "go vet ./...", "architecture sentinel", "exact diff scope"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_ARCHITECTURE_GAP", "BLOCKED_BY_SPEC_GAP", "BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_CONFLICT"]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
# Assistant project status
|
||||
|
||||
Audit date: 2026-08-17. Active implementation: DEV-000057 revision 1.
|
||||
Audit date: 2026-08-17. Active implementation: DEV-000058 revision 1.
|
||||
|
||||
## Current milestone
|
||||
|
||||
@@ -11,6 +11,7 @@ Audit date: 2026-08-17. Active implementation: DEV-000057 revision 1.
|
||||
- The current milestone integrates one normally available local CPU provider and one opportunistic local Ollama/GPU provider through typed discovery, health and routing boundaries.
|
||||
- Discovery never activates a provider, model or binding. Until a later benchmark and explicit promotion task, all discovered bindings remain `INACTIVE` and production remains fully LLM-free.
|
||||
- DEV-000057 executed a bounded synthetic qualification corpus against all 11 current local model revisions. Four exact binding revisions demonstrated the minimum advisory threshold; seven remain unsupported. Qualification evidence does not change lifecycle or activation.
|
||||
- DEV-000058 promoted the exact CPU `Qwen2.5-3B-Instruct-Q4_K_M` lineage to `VALIDATED/CANARY` through an authenticated, evidence-gated, append-only CAS transition. Ordinary routing still excludes it; only an explicit `AllowCanary` request can select it. All other current bindings remain `INACTIVE`.
|
||||
|
||||
## Delivered
|
||||
|
||||
@@ -30,7 +31,7 @@ Audit date: 2026-08-17. Active implementation: DEV-000057 revision 1.
|
||||
|
||||
## Remaining work requiring a new task decision
|
||||
|
||||
1. **Cognitive promotion:** DEV-000057 records revision-bound qualification evidence. A separate explicit promotion task must decide whether any supported exact revision may move through `EVALUATING → VALIDATED → CANARY`; no binding is currently active.
|
||||
1. **Cognitive canary observation:** collect bounded usage/reliability evidence for the exact CPU canary revision before any separate `ACTIVE` decision. GPU candidates remain inactive.
|
||||
2. **Product breadth:** notification delivery is the only accepted real external operation. Any additional operation needs its own proposal, authority model, idempotency/reconciliation semantics and Capability binding.
|
||||
3. **Artifact and Epistemics product behavior:** their ownership boundaries exist, but no product task has yet specified durable user-facing workflows for them.
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"artifact_id": "local-cpu-canary-promotion-2026-08-17-v1",
|
||||
"promotion_id": "promotion-cpu-qwen25-3b-canary-v1",
|
||||
"provider_instance_id": "local-cpu-primary",
|
||||
"provider_revision": 2478733237506203521,
|
||||
"provider_model_id": "Qwen2.5-3B-Instruct-Q4_K_M",
|
||||
"model_descriptor_id": "model-d44e5f49f22f866e182060a8",
|
||||
"model_revision": 4433750841304261136,
|
||||
"binding_id": "binding-9e5e9779cd10b907c3695374",
|
||||
"binding_revision": 2865230063392044815,
|
||||
"qualification": "VALIDATED",
|
||||
"activation": "CANARY",
|
||||
"evaluation_artifact_id": "local-cognitive-qualification-2026-08-17-v1",
|
||||
"runtime_revision": "9b11d17d58810e7d01b22c95ee3d73298c7e2bc1",
|
||||
"ordinary_resolve": "NOT_FOUND",
|
||||
"allow_canary_resolve": "SELECTED",
|
||||
"other_current_bindings": {"INACTIVE": 11, "CANARY": 0, "ACTIVE": 0}
|
||||
}
|
||||
@@ -39,6 +39,29 @@ func BuildDiscoveryRegistration(snapshot capability.CognitiveDiscoverySnapshot)
|
||||
return registration, nil
|
||||
}
|
||||
|
||||
func BuildCanaryPromotion(request capability.CognitiveCanaryPromotionRequest, current capability.ResolvedCognitiveBinding) (capability.CognitiveCanaryPromotion, error) {
|
||||
if request.PromotionID == "" || request.RequestedByPrincipalID == "" || request.CapabilityID == "" || request.BindingID == "" || request.ExpectedBindingRevision < 1 || request.ProviderInstanceID == "" || request.ExpectedProviderRevision < 1 || request.ModelDescriptorID == "" || request.ExpectedModelRevision < 1 || request.EvaluationID == "" || request.ObservedAtUnixMillis < 1 || current.Evaluation == nil {
|
||||
return capability.CognitiveCanaryPromotion{}, ErrInvalidCognitiveRegistryRecord
|
||||
}
|
||||
if current.Binding.ID != request.BindingID || current.Binding.Revision != request.ExpectedBindingRevision || current.Binding.OwnerPrincipalID != request.RequestedByPrincipalID || current.Binding.CapabilityID != request.CapabilityID || current.Provider.ID != request.ProviderInstanceID || current.Provider.Revision != request.ExpectedProviderRevision || current.Model.ID != request.ModelDescriptorID || current.Model.Revision != request.ExpectedModelRevision || current.Evaluation.ID != request.EvaluationID || current.Evaluation.Result != capability.EvaluationSupported || current.Evaluation.QualityScoreMillis == nil || *current.Evaluation.QualityScoreMillis < 750 || current.Evaluation.CriticalFailureMillis == nil || *current.Evaluation.CriticalFailureMillis != 0 || current.Provider.Health != capability.HealthAvailable || current.Model.Health != capability.HealthAvailable || current.Binding.Activation != capability.ActivationInactive {
|
||||
return capability.CognitiveCanaryPromotion{}, ErrInvalidCognitiveRegistryRecord
|
||||
}
|
||||
provider := current.Provider
|
||||
provider.Revision = stableRevision(fmt.Sprint(provider.Revision), string(request.PromotionID), string(capability.QualificationValidated))
|
||||
provider.Qualification, provider.Health, provider.ObservedAtUnixMillis = capability.QualificationValidated, capability.HealthAvailable, request.ObservedAtUnixMillis
|
||||
model := current.Model
|
||||
model.Revision = stableRevision(fmt.Sprint(model.Revision), string(request.PromotionID), string(capability.QualificationValidated))
|
||||
model.Qualification, model.Health, model.ObservedAtUnixMillis = capability.QualificationValidated, capability.HealthAvailable, request.ObservedAtUnixMillis
|
||||
binding := current.Binding
|
||||
binding.Revision = stableRevision(fmt.Sprint(binding.Revision), fmt.Sprint(provider.Revision), fmt.Sprint(model.Revision), string(request.PromotionID), string(capability.ActivationCanary))
|
||||
binding.ProviderRevision, binding.ModelRevision = provider.Revision, model.Revision
|
||||
binding.Qualification, binding.Activation, binding.Health = capability.QualificationValidated, capability.ActivationCanary, capability.HealthAvailable
|
||||
evaluation := *current.Evaluation
|
||||
evaluation.ID = capability.EvaluationID(stableID("evaluation", string(request.PromotionID), string(binding.ID), fmt.Sprint(binding.Revision)))
|
||||
evaluation.BindingRevision = binding.Revision
|
||||
return capability.CognitiveCanaryPromotion{PromotionID: request.PromotionID, ExpectedBindingRevision: request.ExpectedBindingRevision, Provider: provider, Model: model, Binding: binding, Evaluation: evaluation}, nil
|
||||
}
|
||||
|
||||
func stableID(kind string, parts ...string) string {
|
||||
hash := sha256.New()
|
||||
_, _ = hash.Write([]byte(kind))
|
||||
|
||||
@@ -18,6 +18,8 @@ type Repository interface {
|
||||
SaveModelDescriptor(context.Context, capability.ModelDescriptor) error
|
||||
SaveCognitiveBinding(context.Context, capability.CognitiveBinding) error
|
||||
LoadCognitiveCandidates(context.Context, capability.CapabilityID, identity.PrincipalID) ([]capability.ResolvedCognitiveBinding, error)
|
||||
LoadCognitiveCandidate(context.Context, capability.CapabilityBindingID, int64) (capability.ResolvedCognitiveBinding, error)
|
||||
SaveCognitiveCanaryPromotion(context.Context, capability.CognitiveCanaryPromotion) error
|
||||
SaveCognitiveUsageObservation(context.Context, capability.CognitiveUsageObservation) error
|
||||
SaveCognitiveDiscovery(context.Context, capability.CognitiveDiscoveryRegistration) error
|
||||
SaveEvaluatedCapability(context.Context, capability.EvaluatedCapability) error
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package cognitive_canary_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/capability"
|
||||
capabilitydomain "git.cin.su/m/Assistant/modules/capability/domain"
|
||||
)
|
||||
|
||||
func TestSupportedExactRevisionPromotesToCanary(t *testing.T) {
|
||||
quality, critical := int64(1000), int64(0)
|
||||
current := capability.ResolvedCognitiveBinding{
|
||||
Binding: capability.CognitiveBinding{ID: "binding-1", Revision: 11, CapabilityID: "creator-advisory", OwnerPrincipalID: "creator", ProviderInstanceID: "provider-1", ProviderRevision: 12, ModelDescriptorID: "model-1", ModelRevision: 13, DataPolicy: capability.DataPolicyLocalOnly, Qualification: capability.QualificationDiscovered, Activation: capability.ActivationInactive, Health: capability.HealthUnknown, LimitPolicyRef: "limits"},
|
||||
Provider: capability.ProviderInstance{ID: "provider-1", Revision: 12, Kind: "local", EndpointRef: "endpoint", Enabled: true, Qualification: capability.QualificationDiscovered, Health: capability.HealthAvailable, ObservedAtUnixMillis: 1},
|
||||
Model: capability.ModelDescriptor{ID: "model-1", Revision: 13, ProviderInstanceID: "provider-1", ProviderModelID: "snapshot", Fingerprint: "digest", MaxContextBytes: 4096, Modalities: []capability.ModelModality{capability.ModalityText}, Capabilities: []capability.ModelCapability{capability.CapabilityAdvisory}, Qualification: capability.QualificationDiscovered, Health: capability.HealthAvailable, ObservedAtUnixMillis: 1},
|
||||
Evaluation: &capability.EvaluatedCapability{ID: "eval-1", BindingID: "binding-1", BindingRevision: 11, CapabilityID: "creator-advisory", Result: capability.EvaluationSupported, QualityScoreMillis: &quality, CriticalFailureMillis: &critical, BenchmarkVersion: "v1", ArtifactID: "artifact-1", ObservedAtUnixMillis: 1},
|
||||
}
|
||||
request := capability.CognitiveCanaryPromotionRequest{PromotionID: "promotion-1", RequestedByPrincipalID: "creator", CapabilityID: "creator-advisory", BindingID: "binding-1", ExpectedBindingRevision: 11, ProviderInstanceID: "provider-1", ExpectedProviderRevision: 12, ModelDescriptorID: "model-1", ExpectedModelRevision: 13, EvaluationID: "eval-1", ObservedAtUnixMillis: 2}
|
||||
promotion, err := capabilitydomain.BuildCanaryPromotion(request, current)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if promotion.Binding.Activation != capability.ActivationCanary || promotion.Binding.Qualification != capability.QualificationValidated || promotion.Provider.Qualification != capability.QualificationValidated || promotion.Model.Qualification != capability.QualificationValidated {
|
||||
t.Fatalf("invalid promotion: %+v", promotion)
|
||||
}
|
||||
if promotion.Binding.Revision == current.Binding.Revision || promotion.Evaluation.BindingRevision != promotion.Binding.Revision {
|
||||
t.Fatal("promotion is not append-only and evidence-bound")
|
||||
}
|
||||
current.Evaluation.Result = capability.EvaluationUnsupported
|
||||
if _, err = capabilitydomain.BuildCanaryPromotion(request, current); err == nil {
|
||||
t.Fatal("unsupported evaluation promoted")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user