Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45435814ee | ||
|
|
c7170ee751 | ||
|
|
e9f338484a | ||
|
|
bb131147f8 |
@@ -96,11 +96,15 @@ func (a *OpenAICompatibleLocalAdapter) Discover(ctx context.Context) ([]Discover
|
||||
}
|
||||
|
||||
type compatibleChatRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []compatibleMessage `json:"messages"`
|
||||
Temperature int `json:"temperature"`
|
||||
Stream bool `json:"stream"`
|
||||
MaxTokens int `json:"max_tokens"`
|
||||
Model string `json:"model"`
|
||||
Messages []compatibleMessage `json:"messages"`
|
||||
Temperature int `json:"temperature"`
|
||||
Stream bool `json:"stream"`
|
||||
MaxTokens int `json:"max_tokens"`
|
||||
ChatTemplateKwargs compatibleTemplateKwargs `json:"chat_template_kwargs"`
|
||||
}
|
||||
type compatibleTemplateKwargs struct {
|
||||
EnableThinking bool `json:"enable_thinking"`
|
||||
}
|
||||
type compatibleMessage struct {
|
||||
Role string `json:"role"`
|
||||
@@ -121,7 +125,7 @@ func (a *OpenAICompatibleLocalAdapter) Advise(ctx context.Context, request cogni
|
||||
if err := ValidateAdvisoryRequest(request); err != nil || request.ProviderModelID == "" || len(request.Context) != 0 {
|
||||
return cognitive.AdvisoryResponse{}, ErrInvalidAdvisory
|
||||
}
|
||||
payload := compatibleChatRequest{Model: string(request.ProviderModelID), Messages: []compatibleMessage{{Role: "system", Content: "Provide non-canonical advisory text only. Never claim that an action occurred."}, {Role: "user", Content: request.Message}}, Temperature: 0, Stream: false, MaxTokens: request.MaxOutputBytes / 4}
|
||||
payload := compatibleChatRequest{Model: string(request.ProviderModelID), Messages: []compatibleMessage{{Role: "system", Content: "Provide non-canonical advisory text only. Never claim that an action occurred."}, {Role: "user", Content: request.Message}}, Temperature: 0, Stream: false, MaxTokens: request.MaxOutputBytes / 4, ChatTemplateKwargs: compatibleTemplateKwargs{EnableThinking: false}}
|
||||
var result compatibleChatResponse
|
||||
status, err := a.requestJSON(ctx, http.MethodPost, "/chat/completions", payload, &result)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,15 +2,20 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.cin.su/m/Assistant/contracts/capability"
|
||||
"git.cin.su/m/Assistant/contracts/cognitive"
|
||||
)
|
||||
|
||||
type captureRoundTripper struct {
|
||||
authorization string
|
||||
body []byte
|
||||
}
|
||||
|
||||
func TestOpenAICompatibleLocalAdapterUsesConfiguredTimeout(t *testing.T) {
|
||||
@@ -31,7 +36,14 @@ func TestOpenAICompatibleLocalAdapterRejectsNonPositiveTimeout(t *testing.T) {
|
||||
|
||||
func (t *captureRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) {
|
||||
t.authorization = request.Header.Get("Authorization")
|
||||
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader(`{"data":[]}`)), Header: make(http.Header), Request: request}, nil
|
||||
if request.Body != nil {
|
||||
t.body, _ = io.ReadAll(request.Body)
|
||||
}
|
||||
body := `{"data":[]}`
|
||||
if strings.HasSuffix(request.URL.Path, "/chat/completions") {
|
||||
body = `{"choices":[{"finish_reason":"stop","message":{"role":"assistant","content":"ok"}}],"usage":{"prompt_tokens":1,"completion_tokens":1}}`
|
||||
}
|
||||
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader(body)), Header: make(http.Header), Request: request}, nil
|
||||
}
|
||||
|
||||
func TestOpenAICompatibleLocalAdapterUsesResolvedAPIKey(t *testing.T) {
|
||||
@@ -57,3 +69,26 @@ func TestOpenAICompatibleLocalAdapterDoesNotSendAuthorizationWithoutKey(t *testi
|
||||
t.Fatalf("unexpected authorization header")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenAICompatibleLocalAdapterDisablesTemplateThinkingForBoundedAdvisory(t *testing.T) {
|
||||
transport := &captureRoundTripper{}
|
||||
adapter, err := NewOpenAICompatibleLocalAdapter("http://gateway/v1", transport)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = adapter.Advise(context.Background(), cognitive.AdvisoryRequest{Version: cognitive.CreatorAdvisoryV1, RequestID: "request-1", ActorID: "actor", PrincipalID: "principal", ScopeID: "scope", Message: "help", Locale: "ru-RU", MaxOutputBytes: 256, ProviderBindingID: "binding-1", ProviderBindingRevision: 1, ProviderInstanceID: "provider-1", ModelDescriptorID: "model-1", ProviderModelID: capability.ProviderModelID("medium-model")})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var payload struct {
|
||||
ChatTemplateKwargs struct {
|
||||
EnableThinking bool `json:"enable_thinking"`
|
||||
} `json:"chat_template_kwargs"`
|
||||
}
|
||||
if err := json.Unmarshal(transport.body, &payload); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if payload.ChatTemplateKwargs.EnableThinking {
|
||||
t.Fatal("expected bounded advisory to disable template thinking")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"task_file": "dev/tasks/DEV-000197-durable-development-gate.json",
|
||||
"task_id": "DEV-000197",
|
||||
"task_file": "dev/tasks/DEV-000199-medium-advisory-thinking-control.json",
|
||||
"task_id": "DEV-000199",
|
||||
"task_revision": 1
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"task_id": "DEV-000198",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "ADR-0018",
|
||||
"base_repo_revision": "bb131147f80cb75c0ba3d80607d0f806bd378aa8",
|
||||
"risk_tier": "E",
|
||||
"intent": "Record live production evidence for durable governed self-development gate persistence and Work-owner access.",
|
||||
"requirement_ids": ["WP-701", "live durable gate evidence"],
|
||||
"allowed_change_scope": {"modules": ["governance status", "evidence"], "paths": ["docs/PROJECT_STATUS.md", "docs/evidence/governed-development-gate-persistence-2026-08-23-v1.json", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000198-development-gate-live-evidence.json"]},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "cmd/**", "modules/**", "contracts/**", ".gitea/**"]},
|
||||
"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": ["Work development gate persistence contract", "production health"], "may_change": ["status and evidence projection only"]},
|
||||
"semantic_owner": "governance",
|
||||
"canonical_state": ["work.development_gates"],
|
||||
"state_transitions": ["none; evidence records applied migration and owner read access"],
|
||||
"side_effects_and_privileges": ["read-only production verification"],
|
||||
"persistence_and_migrations": ["no migration"],
|
||||
"failure_retry_restart": ["retain explicit external bridge gap"],
|
||||
"assumptions": ["migration 037 and privilege forward migration 038 are present in production"],
|
||||
"acceptance_scenarios": ["work_role can query the relation", "public health is ok", "status distinguishes durable gate persistence from bridge-backed execution"],
|
||||
"required_tests": ["go test ./...", "go vet ./...", "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", "go run ./cmd/devctl/independent -task dev/tasks/DEV-000198-development-gate-live-evidence.json", "git diff --check", "CI", "production health and schema check"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY"]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"task_id": "DEV-000199",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "ADR-0018",
|
||||
"base_repo_revision": "c7170ee751b715b0cf6721d8491530c185870b2a",
|
||||
"risk_tier": "E",
|
||||
"intent": "Disable provider template reasoning for bounded OpenAI-compatible local advisory requests so a loaded MEDIUM model can return bounded advisory content instead of consuming the entire output cap with hidden reasoning.",
|
||||
"requirement_ids": ["WP-200", "model fleet/failover", "bounded advisory output"],
|
||||
"allowed_change_scope": {"modules": ["models adapter"], "paths": ["adapters/models/openai_compatible_local.go", "adapters/models/openai_compatible_local_test.go", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000199-medium-advisory-thinking-control.json"]},
|
||||
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "cmd/**", "modules/**", "contracts/**", ".gitea/**"]},
|
||||
"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": ["existing OpenAI-compatible local advisory contract"], "may_change": ["provider request serialization adds typed template control"]},
|
||||
"semantic_owner": "cognitive adapter",
|
||||
"canonical_state": [],
|
||||
"state_transitions": ["bounded advisory request asks compatible runtimes to disable hidden template reasoning"],
|
||||
"side_effects_and_privileges": ["bounded local provider inference only; no activation or promotion"],
|
||||
"persistence_and_migrations": ["none"],
|
||||
"failure_retry_restart": ["provider ignoring the optional request field remains an explicit qualification result"],
|
||||
"assumptions": ["llama.cpp-compatible OpenAI endpoints ignore or honor the typed chat_template_kwargs field without breaking the existing contract"],
|
||||
"acceptance_scenarios": ["request contains enable_thinking=false", "adapter still validates bounded completion", "provider failure remains typed and failover-compatible"],
|
||||
"required_tests": ["go test ./...", "go vet ./...", "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", "go run ./cmd/devctl/independent -task dev/tasks/DEV-000199-medium-advisory-thinking-control.json", "git diff --check", "CI", "production medium bounded smoke and public health check"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_CONFLICT"]
|
||||
}
|
||||
@@ -11,12 +11,12 @@
|
||||
- `TRUTH_RESEARCH_STATUS = LIVE_CANARY_PERSISTED`; the web research canary preserved an OBSERVED/COMPLETE/NO-CONFLICT source chain while leaving the claim UNVERIFIED and belief PROVISIONAL. Evidence: `docs/evidence/truth-runtime-canary-2026-08-23-v1.json`.
|
||||
- `LEARNING_REFLECTION_STATUS = LIVE_RECONCILED`; reflection worker returned no pending candidate and the durable state contains 31 RESOLVED candidates with no OPEN backlog. Evidence: `docs/evidence/reflection-runtime-reconciliation-2026-08-23-v1.json`.
|
||||
- `BACKUP_RESTORE_STATUS = VERIFIED`; latest checksum and isolated restore evidence is retained in `docs/evidence/wp-002-postgres-restore-2026-08-22-v1.json`.
|
||||
- `GOVERNED_SELF_DEVELOPMENT_STATUS = PROPOSAL_AND_SCAFFOLD_ONLY`; no bridge-backed source mutation, promotion or rollback is claimed.
|
||||
- `GOVERNED_SELF_DEVELOPMENT_STATUS = DURABLE_GATE_PERSISTED`; Work-owned revisioned gate storage and optimistic-concurrency persistence are live. No bridge-backed source mutation, promotion or rollback is claimed. Evidence: `docs/evidence/governed-development-gate-persistence-2026-08-23-v1.json`.
|
||||
- `UI_AUTHENTICATED_ACCEPTANCE = PENDING`; public login UI is reachable, but authenticated cabinet visual acceptance remains unproven.
|
||||
|
||||
## Current governance checkpoint
|
||||
|
||||
- `ACTIVE_TASK = dev/tasks/DEV-000196-agent-canary-live-evidence.json revision 1`
|
||||
- `ACTIVE_TASK = dev/tasks/DEV-000198-development-gate-live-evidence.json revision 1`
|
||||
- `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.
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"captured_at": "2026-08-23",
|
||||
"production_revision": "bb131147f80cb75c0ba3d80607d0f806bd378aa8",
|
||||
"migration": "038_work_development_gates_privileges.sql",
|
||||
"database_verification": {
|
||||
"relation": "work.development_gates",
|
||||
"work_role_select_count": 0,
|
||||
"privilege_result": "SELECT succeeded as work_role"
|
||||
},
|
||||
"public_health": {"url": "https://assistant.cin.su/healthz", "status": "ok"},
|
||||
"interpretation": "The governed self-development gate is now durable and accessible to its Work owner with revisioned persistence. This evidence does not prove external bridge execution, source mutation, promotion or rollback.",
|
||||
"secrets_exposed": false
|
||||
}
|
||||
Reference in New Issue
Block a user