Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3ddb45fe5 | ||
|
|
6061eb5c13 | ||
|
|
0e46a64702 | ||
|
|
0609561dfe | ||
|
|
1b88a35b82 | ||
|
|
be01b6b883 | ||
|
|
deaddbca12 | ||
|
|
b20611590a | ||
|
|
d4972afd11 | ||
|
|
60e8292c1d |
@@ -298,12 +298,21 @@ func fallbackEligible(reason cognitive.FinishReason) bool {
|
||||
}
|
||||
|
||||
func (g cognitiveGateway) provider(selected capability.ResolvedCognitiveBinding) advisoryProvider {
|
||||
var byStableID advisoryProvider
|
||||
for _, registration := range g.providers[selected.Provider.Kind] {
|
||||
if registration.EndpointRef == selected.Provider.EndpointRef && registration.CredentialRef == selected.Provider.CredentialRef {
|
||||
return registration.Provider
|
||||
}
|
||||
// Capability revisions can legitimately retain an older credential
|
||||
// reference while the protected runtime has rotated or reloaded the
|
||||
// current credential. ProviderInstanceID is the stable owner identity;
|
||||
// use it after exact metadata matching so stale non-secret metadata does
|
||||
// not force an unnecessary builtin fallback.
|
||||
if byStableID == nil && registration.ProviderInstanceID == selected.Provider.ID && registration.Kind == selected.Provider.Kind {
|
||||
byStableID = registration.Provider
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return byStableID
|
||||
}
|
||||
|
||||
func writeGatewayResponse(w http.ResponseWriter, response cognitive.GatewayAdvisoryResponse) {
|
||||
|
||||
@@ -88,6 +88,19 @@ func TestActiveRegistryBindingReachesProviderAdapter(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestProviderUsesStableInstanceWhenCredentialMetadataIsStale(t *testing.T) {
|
||||
provider := &stubAdvisoryProvider{}
|
||||
gateway := cognitiveGateway{providers: map[capability.ProviderKind][]providerRegistration{
|
||||
"provider-kind-1": {{ProviderInstanceID: "provider-1", Kind: "provider-kind-1", EndpointRef: "current-endpoint", CredentialRef: "current-credential", Provider: provider}},
|
||||
}}
|
||||
selected := gatewaySelection()
|
||||
selected.Provider.EndpointRef = "old-endpoint"
|
||||
selected.Provider.CredentialRef = ""
|
||||
if got := gateway.provider(selected); got != provider {
|
||||
t.Fatalf("stable provider identity was not used for stale metadata")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryFlagIsForwardedToCapabilityResolver(t *testing.T) {
|
||||
registry := ®istryStub{err: errors.New("stop after resolve")}
|
||||
gateway := cognitiveGateway{resolver: registry, providers: map[capability.ProviderKind][]providerRegistration{}, now: time.Now, allowCanary: true}
|
||||
|
||||
@@ -169,6 +169,7 @@ func main() {
|
||||
mux.HandleFunc("POST /v1/task-evaluations/execute", gateway.taskEvaluationHandler)
|
||||
discovery := discoveryService{resolver: resolver, providers: discoveries, owner: identity.PrincipalID(envOr("COGNITIVE_OWNER_PRINCIPAL_ID", "domovoy-creator-principal")), now: time.Now}
|
||||
mux.HandleFunc("POST /v1/provider-discovery/{provider}", discovery.handler)
|
||||
mux.Handle("POST /v1/provider-discovery/{provider}/qualify", modelQualificationHandler(discoveries, string(envOr("COGNITIVE_OWNER_PRINCIPAL_ID", "domovoy-creator-principal"))))
|
||||
mux.HandleFunc("GET /v1/provider-discovery/status", discovery.statusHandler)
|
||||
refreshProviderDiscoveries(resolver, discovery)
|
||||
log.Printf("cognitive-worker listening on %s", addr)
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"slices"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.cin.su/m/Assistant/adapters/models"
|
||||
"git.cin.su/m/Assistant/contracts/authority"
|
||||
"git.cin.su/m/Assistant/contracts/capability"
|
||||
"git.cin.su/m/Assistant/contracts/cognitive"
|
||||
"git.cin.su/m/Assistant/contracts/identity"
|
||||
)
|
||||
|
||||
type modelQualificationRequest struct {
|
||||
Prompt string `json:"prompt"`
|
||||
MaxOutputBytes int `json:"max_output_bytes"`
|
||||
ModelIDs []capability.ProviderModelID `json:"model_ids,omitempty"`
|
||||
}
|
||||
|
||||
type modelQualificationResult struct {
|
||||
ProviderModelID capability.ProviderModelID `json:"provider_model_id"`
|
||||
Status string `json:"status"`
|
||||
FinishReason cognitive.FinishReason `json:"finish_reason,omitempty"`
|
||||
LatencyMillis int64 `json:"latency_millis"`
|
||||
OutputObserved bool `json:"output_observed"`
|
||||
QualityAssessed bool `json:"quality_assessed"`
|
||||
Category capability.ModelRatingCategory `json:"category"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type modelQualificationResponse struct {
|
||||
Provider capability.ProviderInstanceID `json:"provider"`
|
||||
ObservedAtUnixMillis int64 `json:"observed_at_unix_millis"`
|
||||
Results []modelQualificationResult `json:"results"`
|
||||
}
|
||||
|
||||
func modelQualificationHandler(providers map[string]providerRegistration, owner string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
name := r.PathValue("provider")
|
||||
registration, ok := providers[name]
|
||||
if !ok || registration.Discovery == nil || registration.Provider == nil {
|
||||
http.Error(w, "provider qualification not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
var request modelQualificationRequest
|
||||
if !decodeJSON(w, r, 16<<10, &request) || request.Prompt == "" {
|
||||
return
|
||||
}
|
||||
if request.MaxOutputBytes < 1 {
|
||||
request.MaxOutputBytes = 512
|
||||
}
|
||||
if request.MaxOutputBytes > 4096 {
|
||||
http.Error(w, "max_output_bytes exceeds qualification bound", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
modelsFound, probe := registration.Discovery.Discover(r.Context())
|
||||
if probe.Health != capability.HealthAvailable || len(modelsFound) == 0 {
|
||||
http.Error(w, "provider unavailable for qualification", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
if len(request.ModelIDs) > 0 {
|
||||
modelsFound = slices.DeleteFunc(modelsFound, func(model models.DiscoveredModel) bool {
|
||||
return !slices.Contains(request.ModelIDs, model.ProviderModelID)
|
||||
})
|
||||
}
|
||||
if len(modelsFound) == 0 {
|
||||
http.Error(w, "requested model not discovered", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if len(modelsFound) > 16 {
|
||||
modelsFound = modelsFound[:16]
|
||||
}
|
||||
results := qualifyModels(r.Context(), registration, owner, request.Prompt, request.MaxOutputBytes, modelsFound)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = jsonEncode(w, modelQualificationResponse{Provider: registration.ProviderInstanceID, ObservedAtUnixMillis: time.Now().UnixMilli(), Results: results})
|
||||
})
|
||||
}
|
||||
|
||||
func qualifyModels(ctx context.Context, registration providerRegistration, owner, prompt string, maxOutputBytes int, discovered []models.DiscoveredModel) []modelQualificationResult {
|
||||
results := make([]modelQualificationResult, len(discovered))
|
||||
var wg sync.WaitGroup
|
||||
for index, model := range discovered {
|
||||
wg.Add(1)
|
||||
go func(index int, model models.DiscoveredModel) {
|
||||
defer wg.Done()
|
||||
started := time.Now()
|
||||
request := cognitive.AdvisoryRequest{Version: cognitive.CreatorAdvisoryV1, RequestID: cognitive.RequestID(fmt.Sprintf("qualification:%s:%d", model.ProviderModelID, started.UnixNano())), ActorID: identity.ActorID("qualification-runtime"), PrincipalID: identity.PrincipalID(owner), ScopeID: authority.ScopeID("qualification-scope"), Message: prompt, Locale: "en-US", MaxOutputBytes: maxOutputBytes, ProviderBindingID: "qualification-binding-v1", ProviderBindingRevision: 1, ProviderInstanceID: registration.ProviderInstanceID, ModelDescriptorID: capability.ModelDescriptorID("qualification-" + string(model.ProviderModelID)), ProviderModelID: model.ProviderModelID}
|
||||
response, err := registration.Provider.Advise(ctx, request)
|
||||
result := modelQualificationResult{ProviderModelID: model.ProviderModelID, LatencyMillis: time.Since(started).Milliseconds(), QualityAssessed: false, Category: capability.ModelRatingUnrated}
|
||||
if err != nil {
|
||||
result.Status = "UNAVAILABLE"
|
||||
result.Error = err.Error()
|
||||
results[index] = result
|
||||
return
|
||||
}
|
||||
result.FinishReason = response.FinishReason
|
||||
result.OutputObserved = response.AdvisoryText != ""
|
||||
if response.FinishReason == cognitive.FinishCompleted && result.OutputObserved {
|
||||
result.Status = "REACHABLE"
|
||||
} else {
|
||||
result.Status = "RESPONDED_WITHOUT_QUALIFICATION"
|
||||
}
|
||||
results[index] = result
|
||||
}(index, model)
|
||||
}
|
||||
wg.Wait()
|
||||
return results
|
||||
}
|
||||
|
||||
func jsonEncode(w http.ResponseWriter, value any) error {
|
||||
return json.NewEncoder(w).Encode(value)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.cin.su/m/Assistant/adapters/models"
|
||||
"git.cin.su/m/Assistant/contracts/capability"
|
||||
"git.cin.su/m/Assistant/contracts/cognitive"
|
||||
)
|
||||
|
||||
type qualificationProvider struct{}
|
||||
|
||||
func (qualificationProvider) Probe(context.Context) models.ProviderProbe {
|
||||
return models.ProviderProbe{Health: capability.HealthAvailable}
|
||||
}
|
||||
func (qualificationProvider) Discover(context.Context) ([]models.DiscoveredModel, models.ProviderProbe) {
|
||||
return []models.DiscoveredModel{{ProviderModelID: "model-a"}, {ProviderModelID: "model-b"}}, models.ProviderProbe{Health: capability.HealthAvailable}
|
||||
}
|
||||
func (qualificationProvider) Advise(_ context.Context, request cognitive.AdvisoryRequest) (cognitive.AdvisoryResponse, error) {
|
||||
if err := models.ValidateAdvisoryRequest(request); err != nil {
|
||||
return cognitive.AdvisoryResponse{}, err
|
||||
}
|
||||
return cognitive.AdvisoryResponse{Version: request.Version, RequestID: request.RequestID, AdvisoryText: "reachable", FinishReason: cognitive.FinishCompleted}, nil
|
||||
}
|
||||
|
||||
func TestModelQualificationUsesDiscoveredModelsAndLeavesQualityUnrated(t *testing.T) {
|
||||
provider := qualificationProvider{}
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("POST /v1/provider-discovery/{provider}/qualify", modelQualificationHandler(map[string]providerRegistration{"gpu": {ProviderInstanceID: "gpu", Provider: provider, Discovery: provider}}, "owner"))
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
request := httptest.NewRequest(http.MethodPost, server.URL+"/v1/provider-discovery/gpu/qualify", strings.NewReader(`{"prompt":"ready","max_output_bytes":128}`))
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
response := httptest.NewRecorder()
|
||||
mux.ServeHTTP(response, request)
|
||||
if response.Code != http.StatusOK {
|
||||
t.Fatalf("qualification status=%d body=%s", response.Code, response.Body.String())
|
||||
}
|
||||
if !strings.Contains(response.Body.String(), `"status":"REACHABLE"`) || !strings.Contains(response.Body.String(), `"category":"UNRATED"`) || strings.Contains(response.Body.String(), `"quality_assessed":true`) {
|
||||
t.Fatalf("qualification overclaimed quality: %s", response.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestModelQualificationRejectsUnboundedOutput(t *testing.T) {
|
||||
provider := qualificationProvider{}
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("POST /v1/provider-discovery/{provider}/qualify", modelQualificationHandler(map[string]providerRegistration{"cpu": {ProviderInstanceID: "cpu", Provider: provider, Discovery: provider}}, "owner"))
|
||||
request := httptest.NewRequest(http.MethodPost, "/v1/provider-discovery/cpu/qualify", strings.NewReader(`{"prompt":"ready","max_output_bytes":8192}`))
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
response := httptest.NewRecorder()
|
||||
mux.ServeHTTP(response, request)
|
||||
if response.Code != http.StatusBadRequest {
|
||||
t.Fatalf("unbounded qualification status=%d", response.Code)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"task_file": "dev/tasks/DEV-000234-orchestration-snapshot-replan.json",
|
||||
"task_id": "DEV-000234",
|
||||
"task_file": "dev/tasks/DEV-000239-stable-provider-resolution.json",
|
||||
"task_id": "DEV-000239",
|
||||
"task_revision": 1
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"task_id": "DEV-000235",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "ADR-0018",
|
||||
"base_repo_revision": "60e8292c1df947b887079413b3b35ce8b4212086",
|
||||
"risk_tier": "E",
|
||||
"intent": "Add a bounded provider-neutral model qualification probe that discovers actual model IDs, invokes them in parallel, records reachability and latency, and never overclaims quality or hardware superiority.",
|
||||
"requirement_ids": ["model fleet/failover", "dynamic model discovery", "quality separated from reachability", "parallel qualification"],
|
||||
"allowed_change_scope": {"modules": ["cognitive-worker", "capability-observation"], "paths": ["cmd/cognitive-worker/main.go", "cmd/cognitive-worker/model_qualification.go", "cmd/cognitive-worker/model_qualification_test.go", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000235-model-qualification-probe.json", "docs/PROJECT_STATUS.md"]},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "LLM-local/**", "modules/work/secrets/**"]},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 0, "new_third_party_dependencies": 0, "new_database_owner_roles": 0},
|
||||
"contracts": {"consume": ["OpenAI-compatible LocalProvider discovery/advisory adapter", "Capability model rating categories"], "may_change": ["internal bounded provider qualification route"]},
|
||||
"semantic_owner": "Capability cognitive runtime observation",
|
||||
"canonical_state": ["none; probe response is an operational observation and does not promote a binding"],
|
||||
"state_transitions": ["DISCOVERED model -> bounded probe -> REACHABLE/UNAVAILABLE/RESPONDED_WITHOUT_QUALIFICATION", "quality remains UNRATED until independent task tests"],
|
||||
"side_effects_and_privileges": ["read-only provider model discovery and bounded chat invocation; no external mutation, secret exposure, activation, promotion or routing priority"],
|
||||
"persistence_and_migrations": ["none; existing discovery/observation and promotion flows remain unchanged"],
|
||||
"failure_retry_restart": ["each probe has provider adapter timeout; one model failure does not cancel sibling probes; rerun is bounded and idempotent in effect"],
|
||||
"assumptions": ["provider credentials are resolved inside cognitive-worker protected runtime", "additional task-specific tests can be added later without changing the primary probe"],
|
||||
"acceptance_scenarios": ["actual discovered model IDs are used instead of static placeholders", "models are probed in parallel", "successful reachability reports latency", "quality is explicitly UNRATED", "GPU presence does not alter category or promotion", "output bound and model selection are constrained"],
|
||||
"required_tests": ["go test ./cmd/cognitive-worker/... ./modules/capability/domain ./adapters/models/...", "go vet ./cmd/cognitive-worker/... ./modules/capability/domain ./adapters/models/...", "preflight", "check-diff", "check-architecture", "independent", "git diff --check", "CI", "production health smoke"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"task_id": "DEV-000236",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "ADR-0018",
|
||||
"risk_tier": "E",
|
||||
"base_repo_revision": "b20611590a075e3574efddbdba6e1ace312d11a8",
|
||||
"intent": "Make the bounded model qualification invocation satisfy the canonical advisory contract and keep a regression test for the required locale.",
|
||||
"requirement_ids": ["model qualification smoke", "advisory contract"],
|
||||
"allowed_change_scope": {"modules": ["cognitive-worker"], "paths": ["cmd/cognitive-worker/model_qualification.go", "cmd/cognitive-worker/model_qualification_test.go", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000236-qualification-locale-fix.json"]},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "LLM-local/**", "modules/work/secrets/**", "contracts/**"]},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 0, "new_third_party_dependencies": 0, "new_database_owner_roles": 0},
|
||||
"contracts": {"consume": ["Creator advisory request validation"], "may_change": []},
|
||||
"semantic_owner": "Cognitive worker qualification observation",
|
||||
"canonical_state": ["none; qualification remains an operational observation"],
|
||||
"state_transitions": ["invalid advisory invocation -> valid bounded invocation"],
|
||||
"side_effects_and_privileges": ["read-only bounded provider invocation; no promotion or routing mutation"],
|
||||
"persistence_and_migrations": ["none"],
|
||||
"failure_retry_restart": ["one bounded probe failure remains isolated"],
|
||||
"assumptions": ["provider credentials remain protected inside cognitive-worker"],
|
||||
"acceptance_scenarios": ["live qualification invocation passes advisory validation", "quality remains UNRATED"],
|
||||
"required_tests": ["go test ./cmd/cognitive-worker/...", "go vet ./cmd/cognitive-worker/...", "preflight", "check-diff", "check-architecture", "independent", "git diff --check", "CI", "production health smoke"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"task_id": "DEV-000237",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "ADR-0018",
|
||||
"base_repo_revision": "be01b6b883c2ce6e9bb47bc851505fe222c46d14",
|
||||
"risk_tier": "E",
|
||||
"intent": "Record current authenticated quick acceptance for the five creator-console sections without mutating production state.",
|
||||
"requirement_ids": ["WP-800", "WP-804", "authenticated UI quick acceptance"],
|
||||
"allowed_change_scope": {"modules": ["creator-web", "evidence"], "paths": ["docs/evidence/authenticated-ui-section-smoke-2026-08-23-v1.json", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000237-ui-authenticated-section-smoke.json"]},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "LLM-local/**", "modules/work/secrets/**", "contracts/**"]},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 0, "new_third_party_dependencies": 0, "new_database_owner_roles": 0},
|
||||
"contracts": {"consume": ["authenticated creator-console UI"], "may_change": []},
|
||||
"semantic_owner": "Creator-web acceptance evidence",
|
||||
"canonical_state": ["evidence only; no runtime state mutation"],
|
||||
"state_transitions": ["unverified current section -> observed authenticated quick acceptance"],
|
||||
"side_effects_and_privileges": ["read-only browser inspection; no mutation"],
|
||||
"persistence_and_migrations": ["evidence artifact only"],
|
||||
"failure_retry_restart": ["recheck is idempotent and does not change product state"],
|
||||
"assumptions": ["the authenticated browser session belongs to the authorized creator"],
|
||||
"acceptance_scenarios": ["five admin sections load authenticated", "no visible section error is present", "full mobile/accessibility/chaos acceptance remains explicitly unclaimed"],
|
||||
"required_tests": ["go test ./cmd/creator-web/...", "go vet ./cmd/creator-web/...", "go run ./cmd/devctl preflight -active dev/ACTIVE_TASK.json", "go run ./cmd/devctl check-diff -active dev/ACTIVE_TASK.json", "go run ./cmd/devctl check-architecture", "git diff --check", "independent", "CI", "production health smoke"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"task_id": "DEV-000238",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "ADR-0018",
|
||||
"base_repo_revision": "0609561dfefb6dce302f56d50bb56bd5a222fb64",
|
||||
"risk_tier": "E",
|
||||
"intent": "Record a bounded live proof that the advisory gateway keeps a local lifeboat path when the normal model route cannot be used.",
|
||||
"requirement_ids": ["Agent Execution local recovery", "model fleet fallback", "false completion prevention"],
|
||||
"allowed_change_scope": {"modules": ["evidence"], "paths": ["docs/evidence/local-fallback-gateway-live-2026-08-23-v1.json", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000238-local-fallback-evidence.json"]},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "LLM-local/**", "modules/work/secrets/**", "contracts/**"]},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 0, "new_third_party_dependencies": 0, "new_database_owner_roles": 0},
|
||||
"contracts": {"consume": ["creator advisory gateway", "durable cognitive usage observation"], "may_change": []},
|
||||
"semantic_owner": "Evidence only",
|
||||
"canonical_state": ["no runtime state mutation; read-only evidence capture"],
|
||||
"state_transitions": ["normal route unavailable or not eligible -> builtin local lifeboat response"],
|
||||
"side_effects_and_privileges": ["bounded local advisory request; no external egress and no secret exposure"],
|
||||
"persistence_and_migrations": ["existing cognitive usage observation only"],
|
||||
"failure_retry_restart": ["live request is bounded and idempotent in effect"],
|
||||
"assumptions": ["the production database observation is the authoritative route attribution"],
|
||||
"acceptance_scenarios": ["local response is COMPLETED", "usage evidence identifies builtin-local-lifeboat-v1", "no claim of external bridge or multi-model failover"],
|
||||
"required_tests": ["go test ./cmd/core-runtime/...", "go vet ./cmd/core-runtime/...", "go run ./cmd/devctl preflight -active dev/ACTIVE_TASK.json", "go run ./cmd/devctl check-diff -active dev/ACTIVE_TASK.json", "go run ./cmd/devctl check-architecture", "git diff --check", "independent", "CI", "production health smoke"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"task_id": "DEV-000239",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "ADR-0018",
|
||||
"base_repo_revision": "6061eb5c13e46cec1e60fc104b022394f0d94dee",
|
||||
"risk_tier": "E",
|
||||
"intent": "Resolve a registered provider by its stable instance identity when a persisted Capability revision contains stale non-secret endpoint credential metadata, while preserving exact metadata matching first.",
|
||||
"requirement_ids": ["model fleet/failover", "credential rotation compatibility", "local fallback attribution"],
|
||||
"allowed_change_scope": {"modules": ["cognitive-worker"], "paths": ["cmd/cognitive-worker/gateway.go", "cmd/cognitive-worker/gateway_registry_test.go", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000239-stable-provider-resolution.json"]},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "LLM-local/**", "modules/work/secrets/**", "contracts/**"]},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 0, "new_third_party_dependencies": 0, "new_database_owner_roles": 0},
|
||||
"contracts": {"consume": ["Capability ResolvedCognitiveBinding", "protected provider registration"], "may_change": ["internal provider lookup fallback order"]},
|
||||
"semantic_owner": "Cognitive worker provider adapter boundary",
|
||||
"canonical_state": ["no new durable state"],
|
||||
"state_transitions": ["exact provider metadata match -> stable provider identity match -> no provider"],
|
||||
"side_effects_and_privileges": ["provider lookup only; secret values remain in protected runtime"],
|
||||
"persistence_and_migrations": ["none"],
|
||||
"failure_retry_restart": ["missing provider remains explicit and uses existing builtin fallback"],
|
||||
"assumptions": ["ProviderInstanceID is the stable Capability-owned provider identity"],
|
||||
"acceptance_scenarios": ["stale credential metadata still reaches current registered adapter", "exact metadata match retains priority", "no provider remains nil"],
|
||||
"required_tests": ["go test ./cmd/cognitive-worker/...", "go vet ./cmd/cognitive-worker/...", "go run ./cmd/devctl preflight -active dev/ACTIVE_TASK.json", "go run ./cmd/devctl check-diff -active dev/ACTIVE_TASK.json", "go run ./cmd/devctl check-architecture", "git diff --check", "independent", "CI", "production health smoke"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
|
||||
}
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
- `COMPLETION_MATRIX = docs/evidence/audit-completion-matrix-2026-08-23-v3.json`; all seven objective areas are mapped to current repository/production proof, with external bridge, GPU promotion/quality and deep-acceptance gaps explicit.
|
||||
|
||||
- `ACTIVE_TASK = dev/tasks/DEV-000234-orchestration-snapshot-replan.json revision 1`; orchestration waves now persist their GoalID/search snapshot in immutable Work Graph revisions, and verified graph completion returns the next durable search decision. Dispatch-intent discovery/materialization remains an explicit planner hand-off rather than fabricated authority.
|
||||
- `ACTIVE_TASK = dev/tasks/DEV-000235-model-qualification-probe.json revision 1`; cognitive-worker now exposes a bounded provider-neutral qualification probe that discovers actual model IDs, invokes them in parallel, reports reachability/latency and keeps quality `UNRATED` until independent task tests. Hardware presence does not grant promotion or priority.
|
||||
- `LINEAGE_DECISION = docs/GOVERNANCE_LINEAGE_DECISION_2026-08-22.md`; historical packets remain provenance and are not current authority.
|
||||
- `REGISTRY_STATUS = YAML and JSON semantic mirrors agree`
|
||||
- `PRODUCTION_DOMAIN = docker.cin.su`; shared docker-test is not used for this project.
|
||||
- `NEXT_WORK = connect the returned replan decision to capability/agent-intent discovery and automatic next-wave materialization; then add bounded stale-wave recovery and continue remaining audit gaps.`
|
||||
- `NEXT_WORK = use qualification evidence in the provider-neutral Capability rating/selection loop, then continue authenticated UI acceptance, reflection recovery and governed self-development gaps.`
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"evidence_id": "authenticated-ui-section-smoke-2026-08-23-v1",
|
||||
"observed_at": "2026-08-23",
|
||||
"source": "current authenticated in-app browser session against https://assistant.cin.su/admin",
|
||||
"production_revision_checked": "be01b6b883c2ce6e9bb47bc851505fe222c46d14",
|
||||
"authenticated": true,
|
||||
"sections": {
|
||||
"overview": {"loaded": true, "expected_regions": ["Сводка состояния", "Подтвердить исполнение"], "visible_error_count": 0},
|
||||
"diagnostics": {"loaded": true, "expected_regions": ["Диагностика кабинета", "Спросить Домового"], "visible_error_count": 0},
|
||||
"operations": {"loaded": true, "expected_regions": ["Реестр ожиданий", "Модели и fallback", "Агентская работа", "Журнал действий"], "visible_error_count": 0},
|
||||
"learning": {"loaded": true, "expected_regions": ["Опыт и reflection", "Experience", "Reflection", "Skills"], "visible_error_count": 0},
|
||||
"settings": {"loaded": true, "expected_regions": ["Настройки рабочего кабинета"], "visible_error_count": 0}
|
||||
},
|
||||
"mutations_performed": false,
|
||||
"secrets_exposed": false,
|
||||
"status": "AUTHENTICATED_QUICK_SECTION_SMOKE_PASS",
|
||||
"not_proven": ["full mobile and accessibility acceptance", "offline/session-expiry acceptance", "delegation-specific mutation", "external bridge availability"]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"evidence_id": "local-fallback-gateway-live-2026-08-23-v1",
|
||||
"observed_at": "2026-08-23",
|
||||
"production_revision": "0609561dfefb6dce302f56d50bb56bd5a222fb64",
|
||||
"request": {"surface": "internal cognitive-worker advisory gateway", "data_policy": "LOCAL_ONLY", "max_output_bytes": 128, "prompt_class": "bounded readiness response"},
|
||||
"http_result": {"status": 200, "finish_reason": "COMPLETED", "output_observed": true, "output_content": "готов"},
|
||||
"durable_usage_observation": {"provider_instance_id": "builtin-local-lifeboat-v1", "model_descriptor_id": "builtin-local-model-v1", "result_class": "COMPLETED", "failure_type": null, "latency_millis": 665},
|
||||
"status": "LOCAL_FALLBACK_LIVE_PASS",
|
||||
"proves": ["local lifeboat path can answer when normal route is not eligible", "completion is durably attributed to the local fallback"],
|
||||
"does_not_prove": ["external Agent Execution bridge", "multi-model failover between validated provider bindings", "GPU quality or promotion", "long-running recovery"],
|
||||
"secrets_exposed": false
|
||||
}
|
||||
Reference in New Issue
Block a user