Compare commits

...
Author SHA1 Message Date
m 346a8c8467 docs: record gpu invocation smoke gap
CI / test (push) Successful in 1m9s
CI / test (pull_request) Successful in 1m6s
2026-08-23 11:21:51 +03:00
m 288d18a4fb Merge pull request 'docs: record protected gpu model discovery' (#181) from codex/wp-200-gpu-discovery-evidence into main
CI / test (push) Successful in 1m13s
2026-08-23 08:02:48 +00:00
m 97ed2e90ee docs: record protected gpu model discovery
CI / test (push) Successful in 1m7s
CI / test (pull_request) Successful in 1m5s
2026-08-23 11:00:00 +03:00
m b4d166480e Merge pull request 'feat: keep agent work durable without external bridge' (#180) from codex/wp-301-local-fallback into main
CI / test (push) Successful in 1m10s
2026-08-23 07:55:59 +00:00
m 46b35161e9 feat: keep agent work durable without external bridge
CI / test (push) Successful in 1m5s
CI / test (pull_request) Successful in 1m8s
2026-08-23 10:53:10 +03:00
m bee238b61e Merge pull request 'docs: record authenticated ui quick smoke' (#179) from codex/wp-806-authenticated-ui-visual-evidence into main
CI / test (push) Successful in 1m13s
2026-08-23 07:49:55 +00:00
m ca9c4bede5 Merge remote-tracking branch 'origin/main' into codex/wp-806-authenticated-ui-visual-evidence
CI / test (push) Successful in 55s
CI / test (pull_request) Successful in 1m5s
2026-08-23 10:46:39 +03:00
m 48d73c3a4b docs: record authenticated ui quick smoke
CI / test (push) Successful in 1m4s
CI / test (pull_request) Successful in 1m5s
2026-08-23 10:43:03 +03:00
m 76c558ee1a Merge pull request 'docs: record authenticated ui visual evidence' (#178) from codex/wp-806-authenticated-ui-visual-evidence into main
CI / test (push) Successful in 1m9s
2026-08-23 07:21:41 +00:00
m e530058659 docs: record authenticated ui visual evidence
CI / test (push) Successful in 1m6s
CI / test (pull_request) Successful in 1m2s
2026-08-23 10:18:21 +03:00
m 79feab8e41 Merge pull request 'docs: record medium bounded live smoke evidence' (#177) from codex/wp-200-medium-live-smoke-evidence into main
CI / test (push) Successful in 1m10s
2026-08-23 02:03:10 +00:00
m 03943f152d docs: record medium bounded live smoke evidence
CI / test (push) Successful in 1m2s
CI / test (pull_request) Successful in 1m9s
2026-08-23 04:59:14 +03:00
m c8aa731eeb Merge pull request 'fix: disable hidden thinking for bounded local advice' (#176) from codex/wp-200-medium-thinking-control into main
CI / test (push) Successful in 1m12s
2026-08-23 01:04:25 +00:00
m 45435814ee fix: disable hidden thinking for bounded local advice
CI / test (push) Successful in 1m6s
CI / test (pull_request) Successful in 1m6s
2026-08-23 04:01:09 +03:00
m c7170ee751 Merge pull request 'docs: record durable development gate evidence' (#175) from codex/wp-701-development-gate-live-evidence into main
CI / test (push) Successful in 1m6s
2026-08-23 00:55:29 +00:00
m e9f338484a docs: record durable development gate evidence
CI / test (push) Successful in 1m4s
CI / test (pull_request) Successful in 1m4s
2026-08-23 03:52:11 +03:00
m bb131147f8 Merge pull request 'fix: grant development gate owner access' (#174) from codex/wp-701-durable-development-gate into main
CI / test (push) Successful in 1m9s
2026-08-23 00:48:59 +00:00
m 22b84ead9c fix: grant development gate owner access
CI / test (push) Successful in 1m9s
CI / test (pull_request) Successful in 1m8s
2026-08-23 03:45:36 +03:00
m 42c7df964b Merge pull request 'feat: persist governed development gates' (#173) from codex/wp-701-durable-development-gate into main
CI / test (push) Successful in 1m4s
2026-08-23 00:37:34 +00:00
m c542642bf0 feat: persist governed development gates
CI / test (push) Successful in 1m8s
CI / test (pull_request) Successful in 1m4s
2026-08-23 03:34:43 +03:00
m fde14cf0b8 Merge pull request 'docs: record durable agent canary evidence' (#172) from codex/wp-301-agent-canary-live-evidence into main
CI / test (push) Successful in 1m6s
2026-08-23 00:22:21 +00:00
m b52590c458 docs: record durable agent canary evidence
CI / test (push) Successful in 1m6s
CI / test (pull_request) Successful in 1m6s
2026-08-23 03:18:57 +03:00
m 6854458e21 Merge pull request 'fix: make agent canary replayable' (#171) from codex/wp-301-agent-canary-replayable into main
CI / test (push) Successful in 1m6s
2026-08-23 00:11:50 +00:00
m 5658bed520 fix: make agent canary replayable
CI / test (push) Successful in 1m4s
CI / test (pull_request) Successful in 1m4s
2026-08-23 03:10:07 +03:00
m 7252296a74 Merge pull request 'fix: protect agent canary database credentials' (#170) from codex/wp-301-agent-canary-protected-config into main
CI / test (push) Successful in 1m2s
2026-08-23 00:05:20 +00:00
m 348856a9c2 chore: align canary task base with main
CI / test (push) Successful in 1m7s
CI / test (pull_request) Successful in 1m9s
2026-08-23 03:03:43 +03:00
m 7779dc37d1 fix: protect agent canary database credentials
CI / test (push) Failing after 45s
CI / test (pull_request) Failing after 48s
2026-08-23 03:01:35 +03:00
m c1db571a39 Merge pull request 'docs: record live degraded fleet readiness' (#169) from codex/wp-301-fleet-live-degraded-evidence into main
CI / test (push) Successful in 1m9s
2026-08-22 23:53:36 +00:00
m 5f65f3d570 docs: record live degraded fleet readiness
CI / test (push) Successful in 1m4s
CI / test (pull_request) Successful in 1m4s
2026-08-23 02:51:51 +03:00
m bb18cb4f1c Merge pull request 'docs: record live reflection reconciliation' (#168) from codex/wp-500-reflection-live-evidence into main
CI / test (push) Successful in 1m9s
2026-08-22 23:45:57 +00:00
38 changed files with 749 additions and 28 deletions
+10 -6
View File
@@ -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")
}
}
+54 -3
View File
@@ -14,9 +14,10 @@ import (
type WorkRepository struct{ pool *pgxpool.Pool }
var (
ErrDispatchIntentConflict = errors.New("dispatch intent idempotency conflict")
ErrAgentLeaseUnavailable = errors.New("agent lease unavailable")
ErrAgentCallbackRejected = errors.New("agent callback rejected")
ErrDispatchIntentConflict = errors.New("dispatch intent idempotency conflict")
ErrAgentLeaseUnavailable = errors.New("agent lease unavailable")
ErrAgentCallbackRejected = errors.New("agent callback rejected")
ErrDevelopmentGateConflict = errors.New("development gate revision conflict")
)
func OpenWork(ctx context.Context, config ContinuityConfig) (*WorkRepository, error) {
@@ -49,6 +50,56 @@ func (r *WorkRepository) Load(ctx context.Context, id work.TaskID) (work.TaskTar
return target, nil
}
func (r *WorkRepository) LoadDevelopmentGate(ctx context.Context, id string) (work.DevelopmentGate, error) {
var gate work.DevelopmentGate
var evidence, producer, verifier []string
err := r.pool.QueryRow(ctx, `SELECT gate_id,revision,updated_at_unix_millis,stage,evidence_refs,proposal_ref,task_packet_ref,worktree_ref,producer_run_refs,verifier_run_refs,verification_evidence,canary_evidence,promotion_ref,rollback_ref FROM work.development_gates WHERE gate_id=$1`, id).Scan(
&gate.ID, &gate.Revision, &gate.UpdatedAtUnixMillis, &gate.Stage, &evidence, &gate.ProposalRef, &gate.TaskPacketRef, &gate.WorktreeRef, &producer, &verifier, &gate.VerificationEvidence, &gate.CanaryEvidence, &gate.PromotionRef, &gate.RollbackRef)
if err != nil {
return work.DevelopmentGate{}, fmt.Errorf("load development gate: %w", err)
}
gate.EvidenceRefs = append([]string(nil), evidence...)
for _, run := range producer {
gate.ProducerRunRefs = append(gate.ProducerRunRefs, work.AgentRunID(run))
}
for _, run := range verifier {
gate.VerifierRunRefs = append(gate.VerifierRunRefs, work.AgentRunID(run))
}
return gate, nil
}
func (r *WorkRepository) SaveDevelopmentGate(ctx context.Context, gate work.DevelopmentGate, expectedRevision int64) error {
if gate.ID == "" || expectedRevision < 0 || gate.Revision < 1 || gate.UpdatedAtUnixMillis < 1 {
return ErrDevelopmentGateConflict
}
producer := make([]string, 0, len(gate.ProducerRunRefs))
for _, run := range gate.ProducerRunRefs {
producer = append(producer, string(run))
}
verifier := make([]string, 0, len(gate.VerifierRunRefs))
for _, run := range gate.VerifierRunRefs {
verifier = append(verifier, string(run))
}
if expectedRevision == 0 {
command, err := r.pool.Exec(ctx, `INSERT INTO work.development_gates(gate_id,revision,updated_at_unix_millis,stage,evidence_refs,proposal_ref,task_packet_ref,worktree_ref,producer_run_refs,verifier_run_refs,verification_evidence,canary_evidence,promotion_ref,rollback_ref) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14) ON CONFLICT(gate_id) DO NOTHING`, gate.ID, gate.Revision, gate.UpdatedAtUnixMillis, gate.Stage, gate.EvidenceRefs, gate.ProposalRef, gate.TaskPacketRef, gate.WorktreeRef, producer, verifier, gate.VerificationEvidence, gate.CanaryEvidence, gate.PromotionRef, gate.RollbackRef)
if err != nil {
return err
}
if command.RowsAffected() != 1 {
return ErrDevelopmentGateConflict
}
return nil
}
command, err := r.pool.Exec(ctx, `UPDATE work.development_gates SET revision=$1,updated_at_unix_millis=$2,stage=$3,evidence_refs=$4,proposal_ref=$5,task_packet_ref=$6,worktree_ref=$7,producer_run_refs=$8,verifier_run_refs=$9,verification_evidence=$10,canary_evidence=$11,promotion_ref=$12,rollback_ref=$13 WHERE gate_id=$14 AND revision=$15`, gate.Revision, gate.UpdatedAtUnixMillis, gate.Stage, gate.EvidenceRefs, gate.ProposalRef, gate.TaskPacketRef, gate.WorktreeRef, producer, verifier, gate.VerificationEvidence, gate.CanaryEvidence, gate.PromotionRef, gate.RollbackRef, gate.ID, expectedRevision)
if err != nil {
return err
}
if command.RowsAffected() != 1 {
return ErrDevelopmentGateConflict
}
return nil
}
func (r *WorkRepository) SaveDispatchIntent(ctx context.Context, intent work.AgentDispatchIntent) error {
tx, err := r.pool.Begin(ctx)
if err != nil {
+41 -3
View File
@@ -6,12 +6,16 @@ import (
"flag"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"git.cin.su/m/Assistant/adapters/postgres"
secretcontracts "git.cin.su/m/Assistant/contracts/secrets"
"git.cin.su/m/Assistant/contracts/work"
"git.cin.su/m/Assistant/modules/work/application"
"git.cin.su/m/Assistant/modules/work/ports"
platformsecrets "git.cin.su/m/Assistant/platform/secrets"
)
type memoryStore struct{ writes int }
@@ -30,14 +34,24 @@ func main() {
enabled := flag.Bool("enable-canary", false, "explicitly enable the manual canary")
implementation := flag.String("implementation", "fake-worker", "allowlisted deterministic implementation")
postgresMode := flag.Bool("postgres", false, "use the Work PostgreSQL repository instead of in-memory storage")
runID := flag.String("run-id", "", "optional unique canary run suffix; generated when omitted")
flag.Parse()
now := time.UnixMilli(1_700_000_000_000)
intent := work.AgentDispatchIntent{DispatchID: "manual-dispatch-1", IdempotencyKey: "manual-idempotency-1", DelegationID: "manual-delegation-1", RunID: "manual-run-1", ImplementationID: *implementation, ImplementationRevision: 1, SourceRevision: "manual-source-1", WorktreeID: "manual-worktree-1", VerificationPlanRef: "manual-verification-1", CreatedAtUnixMillis: now.UnixMilli()}
suffix := *runID
if suffix == "" {
suffix = fmt.Sprintf("%d", time.Now().UnixNano())
}
now := time.Now().UTC()
intent := work.AgentDispatchIntent{DispatchID: "manual-dispatch-" + suffix, IdempotencyKey: "manual-idempotency-" + suffix, DelegationID: work.DelegationID("manual-delegation-" + suffix), RunID: work.AgentRunID("manual-run-" + suffix), ImplementationID: *implementation, ImplementationRevision: 1, SourceRevision: "manual-source-" + suffix, WorktreeID: "manual-worktree-" + suffix, VerificationPlanRef: "manual-verification-" + suffix, CreatedAtUnixMillis: now.UnixMilli()}
var store ports.ExecutionStore = &memoryStore{}
var closeStore func()
if *postgresMode {
repository, err := postgres.OpenWork(context.Background(), postgres.ContinuityConfig{Host: os.Getenv("POSTGRES_HOST"), Port: os.Getenv("POSTGRES_PORT"), Database: os.Getenv("POSTGRES_DATABASE"), User: os.Getenv("WORK_POSTGRES_USER"), Password: os.Getenv("WORK_POSTGRES_PASSWORD")})
password, err := resolveDatabasePassword()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
repository, err := postgres.OpenWork(context.Background(), postgres.ContinuityConfig{Host: os.Getenv("POSTGRES_HOST"), Port: os.Getenv("POSTGRES_PORT"), Database: os.Getenv("POSTGRES_DATABASE"), User: os.Getenv("WORK_POSTGRES_USER"), Password: password})
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
@@ -67,3 +81,27 @@ func main() {
os.Exit(1)
}
}
func resolveDatabasePassword() (string, error) {
if _, ok := os.LookupEnv("WORK_POSTGRES_PASSWORD"); ok {
return "", fmt.Errorf("WORK_POSTGRES_PASSWORD direct environment secret is forbidden")
}
path, ref := os.Getenv("WORK_POSTGRES_PASSWORD_FILE"), os.Getenv("WORK_POSTGRES_CREDENTIAL_REF")
if path == "" || ref == "" {
return "", fmt.Errorf("WORK_POSTGRES_PASSWORD_FILE and WORK_POSTGRES_CREDENTIAL_REF are required")
}
root := os.Getenv("SECRET_BACKEND_ROOT")
if root == "" {
root = "/run/secrets"
}
cleanRoot := filepath.Clean(root)
cleanPath := filepath.Clean(path)
if cleanPath != cleanRoot && !strings.HasPrefix(cleanPath, cleanRoot+string(os.PathSeparator)) {
return "", fmt.Errorf("database password file escapes protected secret root")
}
resolver, err := platformsecrets.NewFileResolver(cleanRoot)
if err != nil {
return "", err
}
return resolver.ResolveFile(secretcontracts.SecretFileRef{CredentialRef: secretcontracts.CredentialRef(ref), Purpose: secretcontracts.SecretPurposeDatabasePassword, Consumer: secretcontracts.RuntimeConsumerWorkWorker, Path: cleanPath})
}
+23
View File
@@ -0,0 +1,23 @@
package main
import (
"path/filepath"
"testing"
)
func TestResolveDatabasePasswordRejectsDirectEnvironmentSecret(t *testing.T) {
t.Setenv("WORK_POSTGRES_PASSWORD", "literal-secret")
if _, err := resolveDatabasePassword(); err == nil {
t.Fatal("direct database password environment variable was accepted")
}
}
func TestResolveDatabasePasswordRejectsPathOutsideProtectedRoot(t *testing.T) {
root := t.TempDir()
t.Setenv("SECRET_BACKEND_ROOT", root)
t.Setenv("WORK_POSTGRES_PASSWORD_FILE", filepath.Join(root, "..", "outside"))
t.Setenv("WORK_POSTGRES_CREDENTIAL_REF", "credential://domovoy/work/db-password/v1")
if _, err := resolveDatabasePassword(); err == nil {
t.Fatal("database password path outside protected root was accepted")
}
}
+32
View File
@@ -0,0 +1,32 @@
package main
import (
"context"
"time"
"git.cin.su/m/Assistant/contracts/work"
)
// localFallbackExecutor keeps the durable work path alive when no external
// executor is reachable. It never claims that an external action happened.
// The work owner records the WAITING callback and can retry after a bridge is
// configured or a human chooses the next step.
type localFallbackExecutor struct {
now func() time.Time
}
func newLocalFallbackExecutor() localFallbackExecutor {
return localFallbackExecutor{now: time.Now}
}
func (e localFallbackExecutor) Execute(_ context.Context, request work.AgentExecutionRequest) (work.AgentExecutionResult, error) {
now := time.Now()
if e.now != nil {
now = e.now()
}
return work.AgentExecutionResult{
State: work.AgentExecutionWaiting,
Summary: "Внешний Agent Execution Bridge недоступен; локальный fallback сохранил durable работу и ожидает исполнителя.",
ObservedAtUnixMillis: now.UnixMilli(),
}, nil
}
+24
View File
@@ -0,0 +1,24 @@
package main
import (
"context"
"testing"
"time"
"git.cin.su/m/Assistant/contracts/work"
)
func TestLocalFallbackNeverClaimsExternalExecution(t *testing.T) {
when := time.UnixMilli(1_700_000_000_000)
executor := localFallbackExecutor{now: func() time.Time { return when }}
result, err := executor.Execute(context.Background(), work.AgentExecutionRequest{Intent: work.AgentDispatchIntent{DispatchID: "dispatch-1"}})
if err != nil {
t.Fatal(err)
}
if result.State != work.AgentExecutionWaiting || result.ObservedAtUnixMillis != when.UnixMilli() {
t.Fatalf("unexpected fallback result: %+v", result)
}
if result.OutcomeRef != "" || result.Summary == "" {
t.Fatalf("fallback must not claim an outcome: %+v", result)
}
}
+5 -2
View File
@@ -41,6 +41,7 @@ func main() {
}
defer repository.Close()
var executor ports.AgentExecutor
localFallback := false
if bridgeURL, bridgeConfigured := loadProtectedBridgeURL(); bridgeConfigured {
executor, err = agentbridge.NewHTTPExecutor(bridgeURL, &http.Client{Timeout: *leaseTTL})
if err != nil {
@@ -48,10 +49,12 @@ func main() {
os.Exit(1)
}
} else {
fmt.Fprintln(os.Stderr, "protected agent execution bridge URL is not configured; dispatch claims are disabled; recovery-only mode")
executor = newLocalFallbackExecutor()
localFallback = true
fmt.Fprintln(os.Stderr, "protected agent execution bridge URL is not configured; local fallback preserves durable work without external mutation")
}
go func() {
if serveErr := http.ListenAndServe(*statusAddr, workerStatusHandler(executor != nil)); serveErr != nil {
if serveErr := http.ListenAndServe(*statusAddr, workerStatusHandler(executor != nil && !localFallback, localFallback)); serveErr != nil {
fmt.Fprintln(os.Stderr, "agent worker status server:", serveErr)
}
}()
+8 -1
View File
@@ -11,15 +11,22 @@ type workerStatusResponse struct {
Mode string `json:"mode"`
Ready bool `json:"ready"`
Reason string `json:"reason"`
LocalFallback bool `json:"local_fallback"`
}
func workerStatusHandler(executorConfigured bool) http.Handler {
func workerStatusHandler(executorConfigured bool, localFallback ...bool) http.Handler {
local := len(localFallback) > 0 && localFallback[0]
status := workerStatusResponse{
Runtime: "agent-worker",
ExecutorConfigured: executorConfigured,
Mode: "recovery-only",
Ready: false,
Reason: "protected agent execution bridge URL is not configured",
LocalFallback: local,
}
if local {
status.Mode = "local-fallback"
status.Reason = "external bridge unavailable; durable work is retained without external mutation"
}
if executorConfigured {
status.Mode = "execution"
+12
View File
@@ -38,6 +38,18 @@ func TestWorkerStatusReportsRecoveryOnlyWithoutExecutor(t *testing.T) {
}
}
func TestWorkerStatusReportsLocalFallback(t *testing.T) {
response := httptest.NewRecorder()
workerStatusHandler(false, true).ServeHTTP(response, httptest.NewRequest(http.MethodGet, "/status", nil))
var value workerStatusResponse
if err := json.NewDecoder(response.Body).Decode(&value); err != nil {
t.Fatal(err)
}
if response.Code != http.StatusOK || value.Ready || value.Mode != "local-fallback" || !value.LocalFallback {
t.Fatalf("unexpected status: code=%d value=%+v", response.Code, value)
}
}
func TestWorkerReadyzRequiresExecutor(t *testing.T) {
response := httptest.NewRecorder()
workerStatusHandler(false).ServeHTTP(response, httptest.NewRequest(http.MethodGet, "/readyz", nil))
+2
View File
@@ -17,6 +17,8 @@ const (
type DevelopmentGate struct {
ID string
Revision int64
UpdatedAtUnixMillis int64
Stage DevelopmentStage
EvidenceRefs []string
ProposalRef string
@@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS work.development_gates (
gate_id TEXT PRIMARY KEY,
revision BIGINT NOT NULL CHECK (revision > 0),
updated_at_unix_millis BIGINT NOT NULL CHECK (updated_at_unix_millis > 0),
stage TEXT NOT NULL,
evidence_refs TEXT[] NOT NULL,
proposal_ref TEXT NOT NULL,
task_packet_ref TEXT NOT NULL,
worktree_ref TEXT NOT NULL,
producer_run_refs TEXT[] NOT NULL,
verifier_run_refs TEXT[] NOT NULL,
verification_evidence TEXT NOT NULL,
canary_evidence TEXT NOT NULL,
promotion_ref TEXT NOT NULL,
rollback_ref TEXT NOT NULL
);
@@ -0,0 +1,6 @@
BEGIN;
ALTER TABLE work.development_gates OWNER TO work_role;
GRANT SELECT, INSERT, UPDATE ON work.development_gates TO work_role;
COMMIT;
+5 -1
View File
@@ -99,8 +99,12 @@ services:
POSTGRES_PORT: "5432"
POSTGRES_DATABASE: ${POSTGRES_DB:-assistant}
WORK_POSTGRES_USER: work_role
WORK_POSTGRES_PASSWORD: ${WORK_DB_PASSWORD}
WORK_POSTGRES_CREDENTIAL_REF: credential://domovoy/work/db-password/v1
WORK_POSTGRES_PASSWORD_FILE: /run/secrets/work_db_password
SECRET_BACKEND_ROOT: /run/secrets
depends_on: { postgres: { condition: service_healthy } }
volumes:
- assistant_core_secrets:/run/secrets:ro
agent-worker:
build: { context: .., dockerfile: deploy/images/runtime.Dockerfile, args: { TARGET: agent-worker, SOURCE_REVISION: "${ASSISTANT_SOURCE_REVISION:-unknown}" } }
+2 -2
View File
@@ -1,5 +1,5 @@
{
"task_file": "dev/tasks/DEV-000192-reflection-live-reconciliation-evidence.json",
"task_id": "DEV-000192",
"task_file": "dev/tasks/DEV-000205-gpu-invocation-smoke-evidence.json",
"task_id": "DEV-000205",
"task_revision": 1
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000193",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "bb18cb4f1c18aee7c22ddbe7259123f96f779b8c",
"risk_tier": "E",
"intent": "Record the current live model fleet degradation and truthful FAST-first fallback selection after the opportunistic HEAVY provider timeout.",
"requirement_ids": ["model fleet/failover", "CPU-first current operation", "truthful degraded readiness"],
"allowed_change_scope": {"modules": [], "paths": ["docs/PROJECT_STATUS.md", "docs/evidence/audit-runtime-status-2026-08-23-v1.json", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000193-fleet-live-degraded-evidence.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "modules/**", "cmd/**", "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": ["live /v1/fleet/readiness response", "existing FleetReadiness and fallback policy"], "may_change": ["fleet evidence projection"]},
"semantic_owner": "project-governance",
"canonical_state": ["cognitive-worker fleet readiness projection"],
"state_transitions": ["HEAVY ready -> timeout/unavailable", "preferred FAST remains selected", "LIFEBOAT remains fallback tier"],
"side_effects_and_privileges": ["documentation and evidence only; no provider activation or deployment configuration mutation"],
"persistence_and_migrations": ["none"],
"failure_retry_restart": ["provider timeout remains degraded evidence; no unavailable model is claimed ready"],
"assumptions": ["the live endpoint response was captured from docker.cin.su after the current production deployment"],
"acceptance_scenarios": ["FAST/MEDIUM/LIFEBOAT are ready", "HEAVY timeout is explicit", "FAST is selected for CPU-first operation", "LIFEBOAT is the declared fallback", "Agent bridge and authenticated UI gaps remain unchanged"],
"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", "git diff --check", "CI", "production public health check"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000194",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "c1db571a39514e65156123b7f9394645183cf2ab",
"risk_tier": "E",
"intent": "Move the explicit production Agent Execution dry-run canary from direct database secret environment input to protected file/CredentialRef storage and preserve durable lease/callback evidence.",
"requirement_ids": ["Agent Execution runtime and recovery", "protected canary configuration", "durable lease/callback canary"],
"allowed_change_scope": {"modules": ["agent-canary", "deployment"], "paths": ["cmd/agent-canary/main.go", "cmd/agent-canary/main_test.go", "deploy/docker-compose.prod.yml", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000194-agent-canary-protected-storage.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "modules/**", "contracts/**", ".gitea/**"]},
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 1, "new_third_party_dependencies": 0, "new_database_owner_roles": 0},
"contracts": {"consume": ["existing protected secret resolver", "existing ExecutionStore and dry-run canary contract"], "may_change": ["agent-canary runtime configuration"]},
"semantic_owner": "work-agent-execution",
"canonical_state": ["work.agent_dispatch_intents", "work.agent_leases", "work.agent_callback_heads"],
"state_transitions": ["explicit canary -> durable dispatch intent -> lease -> heartbeat callback -> result callback"],
"side_effects_and_privileges": ["manual opt-in dry-run only; protected database credential read; no external provider or source mutation"],
"persistence_and_migrations": ["none"],
"failure_retry_restart": ["missing/invalid protected secret fails before database open; direct secret env is rejected; canary remains explicit opt-in"],
"assumptions": ["the production compose secret volume already contains the work database credential reference used by agent-worker"],
"acceptance_scenarios": ["direct password environment is rejected", "path outside protected root is rejected", "compose renders canary with protected file/ref only", "production opt-in canary writes lease and callback evidence", "normal agent-worker remains recovery-only without an external bridge"],
"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", "git diff --check", "CI", "production canary and public health check"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000195",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "7252296a74ab7ff236fae865d63692e0fc6a777d",
"risk_tier": "E",
"intent": "Make the explicit Agent Execution dry-run canary replayable by generating unique dispatch, lease and callback identities per invocation while retaining durable evidence.",
"requirement_ids": ["Agent Execution runtime and recovery", "replayable durable canary", "lease/callback evidence"],
"allowed_change_scope": {"modules": ["agent-canary"], "paths": ["cmd/agent-canary/main.go", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000195-replayable-agent-canary-run-ids.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "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 canary dry-run contract", "existing durable Work execution records"], "may_change": ["canary identity generation"]},
"semantic_owner": "work-agent-execution",
"canonical_state": ["work.agent_dispatch_intents", "work.agent_leases", "work.agent_callback_heads"],
"state_transitions": ["each explicit canary invocation creates a fresh dispatch identity and durable lease/callback chain"],
"side_effects_and_privileges": ["manual dry-run only; no external execution or source mutation"],
"persistence_and_migrations": ["none"],
"failure_retry_restart": ["repeated invocation does not reuse prior canary identity; lease conflicts remain explicit errors"],
"assumptions": ["the protected-storage canary configuration from DEV-000194 is already in main"],
"acceptance_scenarios": ["default invocation generates a unique suffix", "operator-supplied run-id remains attributable", "two production canary invocations persist independent durable records"],
"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", "git diff --check", "CI", "production canary and public health check"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000196",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "6854458e21ad7ec1c4b736dfabf916ae4f7fac12",
"risk_tier": "E",
"intent": "Record independently verified production evidence for the protected replayable Agent Execution dry-run canary.",
"requirement_ids": ["Agent Execution runtime and recovery", "durable canary evidence"],
"allowed_change_scope": {"modules": ["governance status", "evidence"], "paths": ["docs/PROJECT_STATUS.md", "docs/evidence/agent-execution-dry-run-canary-2026-08-23-v1.json", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000196-agent-canary-live-evidence.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "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 protected canary contract", "existing durable Work execution records"], "may_change": ["status projection and evidence only"]},
"semantic_owner": "governance",
"canonical_state": ["work.agent_dispatch_intents", "work.agent_leases", "work.agent_callback_heads"],
"state_transitions": ["none; evidence records already completed canary state"],
"side_effects_and_privileges": ["read-only status/evidence change after an explicit manual dry-run canary"],
"persistence_and_migrations": ["none"],
"failure_retry_restart": ["no runtime retry; retain the negative external-bridge finding"],
"assumptions": ["the production canary output and database rows were captured without secret values"],
"acceptance_scenarios": ["evidence contains callback_count 2", "evidence contains durable dispatch intent, ACTIVE lease and callback sequence 2", "status explicitly retains the external bridge gap"],
"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", "git diff --check", "CI", "production public health check"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000197",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "fde14cf0b81e2772c81ee7cb9b0335b56943f6e4",
"risk_tier": "E",
"intent": "Persist the governed self-development gate as a Work-owned revisioned state machine with optimistic concurrency, without executing code or granting promotion authority.",
"requirement_ids": ["WP-701", "durable governed self-development provenance", "CAS stage transitions"],
"allowed_change_scope": {"modules": ["work", "postgres persistence"], "paths": ["contracts/work/self_development.go", "modules/work/ports/development.go", "adapters/postgres/work_repository.go", "database/migrations/037_work_development_gates.sql", "database/migrations/038_work_development_gates_privileges.sql", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000197-durable-development-gate.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "deploy/**", "cmd/**", "modules/identity/**", "contracts/authority/**", ".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": 1},
"contracts": {"consume": ["existing DevelopmentGate state machine", "Work-owned persistence boundary"], "may_change": ["revision metadata on DevelopmentGate"]},
"semantic_owner": "work-agent-execution",
"canonical_state": ["work.development_gates"],
"state_transitions": ["persist initial evidence gate", "advance only through caller-validated stage with expected revision", "reject stale revision"],
"side_effects_and_privileges": ["database persistence only; no worktree, provider, source, deployment or promotion mutation"],
"persistence_and_migrations": ["037_work_development_gates.sql", "038_work_development_gates_privileges.sql"],
"failure_retry_restart": ["CAS conflict is explicit and retry requires reloading the gate; restart reloads durable provenance"],
"assumptions": ["domain AdvanceDevelopmentGate remains the sole stage transition validator", "external bridge is a later independently operated capability"],
"acceptance_scenarios": ["initial gate persists at revision 1", "update with expected revision succeeds", "stale revision is rejected", "all provenance fields round-trip without secrets", "work_role can read and write the table"],
"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-000197-durable-development-gate.json", "git diff --check", "CI", "production migration and health check"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "REQUIRES_MIGRATION_DECISION"]
}
@@ -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"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000200",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "c8aa731eeb5f0d1c1dc12591fb50bfbe5dab6d69",
"risk_tier": "E",
"intent": "Record bounded live smoke evidence for the MEDIUM provider after disabling hidden template thinking, without claiming lifecycle qualification or promotion.",
"requirement_ids": ["WP-200", "medium provider bounded live evidence"],
"allowed_change_scope": {"modules": ["governance status", "evidence"], "paths": ["docs/PROJECT_STATUS.md", "docs/evidence/medium-live-bounded-smoke-2026-08-23-v1.json", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000200-medium-live-bounded-smoke-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": ["MEDIUM provider bounded smoke contract", "production health"], "may_change": ["status and evidence projection only"]},
"semantic_owner": "governance",
"canonical_state": ["model fleet evidence projection"],
"state_transitions": ["none; record bounded smoke result and retain unpromoted state"],
"side_effects_and_privileges": ["read-only production verification"],
"persistence_and_migrations": ["no migration"],
"failure_retry_restart": ["retain explicit qualification, activation, promotion and failover gaps"],
"assumptions": ["PR c8aa731 is deployed to production before final live health verification"],
"acceptance_scenarios": ["instruction_exact returns DOMOVOY_OK with stop", "structured_arithmetic returns answer 42 with stop", "noncanonical_action returns action not performed with stop", "ambiguous_destructive_request returns clarification marker with stop", "status keeps MEDIUM explicitly unpromoted"],
"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-000200-medium-live-bounded-smoke-evidence.json", "git diff --check", "CI", "production health and bounded provider smoke"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000201",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "79feab8e4129af4ad0b9e8c9dcd81a6ba1883642",
"risk_tier": "E",
"intent": "Record user-provided authenticated production UI visual evidence while keeping browser interaction and operations acceptance explicitly open.",
"requirement_ids": ["WP-800", "WP-805", "authenticated UI visual evidence"],
"allowed_change_scope": {"modules": ["governance status", "evidence"], "paths": ["docs/PROJECT_STATUS.md", "docs/evidence/authenticated-ui-visual-observation-2026-08-23-v1.json", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000201-authenticated-ui-visual-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": ["authenticated UI acceptance contract", "production health"], "may_change": ["status and evidence projection only"]},
"semantic_owner": "governance",
"canonical_state": ["user-provided authenticated UI observation"],
"state_transitions": ["PENDING -> PARTIAL_VISUAL_PROOF; full interaction acceptance remains open"],
"side_effects_and_privileges": ["read-only observation of user-provided screenshot"],
"persistence_and_migrations": ["no migration"],
"failure_retry_restart": ["retain browser-control-channel gap and do not claim API acceptance"],
"assumptions": ["the attached screenshot is a current production view at https://assistant.cin.su/"],
"acceptance_scenarios": ["status records active session visual proof", "status does not claim authenticated API or mutation acceptance", "public health remains checked after deployment"],
"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-000201-authenticated-ui-visual-evidence.json", "git diff --check", "CI", "production public health"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000202",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "e5300586599e4bd1ad5b6c1530d31d2619b9a88b",
"risk_tier": "E",
"intent": "Record fast authenticated UI and operations smoke evidence without running deferred deep acceptance suites or mutating operational state.",
"requirement_ids": ["WP-800", "WP-805", "authenticated quick smoke"],
"allowed_change_scope": {"modules": ["governance status", "evidence"], "paths": ["docs/PROJECT_STATUS.md", "docs/evidence/authenticated-ui-quick-smoke-2026-08-23-v1.json", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000202-authenticated-ui-quick-smoke.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": ["authenticated UI acceptance contract", "diagnostic and fleet read APIs", "production health"], "may_change": ["status and evidence projection only"]},
"semantic_owner": "governance",
"canonical_state": ["authenticated quick smoke observation"],
"state_transitions": ["PARTIAL_VISUAL_PROOF -> AUTHENTICATED_QUICK_SMOKE_PASS"],
"side_effects_and_privileges": ["read-only diagnostics and fleet checks; chat smoke response; no operation mutation"],
"persistence_and_migrations": ["no migration"],
"failure_retry_restart": ["retain external bridge gap and defer deep acceptance"],
"assumptions": ["user-authenticated browser session is current production session", "the user-requested fast-test mode defers deep suites"],
"acceptance_scenarios": ["chat smoke responds", "admin console authenticates", "diagnostics reports 7/7", "fleet reports 4/4 ready", "agent worker gap remains visible", "action history renders"],
"required_tests": ["quick browser smoke", "go test ./cmd/creator-web", "go vet ./cmd/creator-web", "preflight", "check-diff", "check-architecture", "independent", "git diff --check", "production public health"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000203",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "bee238b61e4760bd864355b893f1fbb188b3f4ce",
"risk_tier": "E",
"intent": "Provide a first-party local Agent Execution fallback that preserves durable work without claiming external execution when the optional bridge is unavailable.",
"requirement_ids": ["WP-301", "local agent execution fallback", "degraded operation"],
"allowed_change_scope": {"modules": ["agent-worker"], "paths": ["cmd/agent-worker/**", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000203-local-agent-execution-fallback.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "database/**", "deploy/**", "security/**", "contracts/**", "modules/**", ".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": ["AgentExecutionRequest", "AgentExecutionResult", "durable worker lease/callback path"], "may_change": ["worker degraded-mode status projection"]},
"semantic_owner": "work",
"canonical_state": ["existing work dispatch, lease and callback state"],
"state_transitions": ["dispatch -> durable lease/heartbeat -> explicit WAITING checkpoint when external bridge is absent"],
"side_effects_and_privileges": ["no external mutation; no new credentials"],
"persistence_and_migrations": ["reuse existing work persistence; no migration"],
"failure_retry_restart": ["WAITING remains evidence-bearing and stale lease recovery remains authoritative"],
"assumptions": ["local fallback is degraded coordination/recovery, not a claim of completed agent work", "external bridge remains optional"],
"acceptance_scenarios": ["missing bridge selects local-fallback mode", "fallback produces WAITING with no outcome reference", "status exposes local_fallback=true", "external bridge path remains unchanged"],
"required_tests": ["go test ./cmd/agent-worker", "go vet ./cmd/agent-worker", "preflight", "check-diff", "check-architecture", "independent", "git diff --check", "quick production worker status"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000204",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "b4d166480e5d06049718618ffeea0ccdbb993336",
"risk_tier": "E",
"intent": "Record protected GPU model discovery without equating hardware availability with intelligence, qualification or routing priority.",
"requirement_ids": ["WP-200", "model fleet/failover", "hardware-neutral routing"],
"allowed_change_scope": {"modules": ["governance status", "evidence"], "paths": ["docs/PROJECT_STATUS.md", "docs/evidence/gpu-discovery-2026-08-23-v1.json", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000204-gpu-discovery-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": ["protected provider discovery", "model fleet policy"], "may_change": ["status and evidence projection only"]},
"semantic_owner": "governance",
"canonical_state": ["capability discovery projection"],
"state_transitions": ["HEAVY degraded -> provider AVAILABLE; models remain DISCOVERED/INACTIVE"],
"side_effects_and_privileges": ["protected read/discovery request only"],
"persistence_and_migrations": ["no migration"],
"failure_retry_restart": ["retain unqualified/unpromoted state until task-specific evidence exists"],
"assumptions": ["cognitive-worker uses the configured protected GPU credential"],
"acceptance_scenarios": ["two GPU models are observed", "both remain unpromoted", "status rejects GPU-as-intelligence inference"],
"required_tests": ["go test ./cmd/cognitive-worker", "go vet ./cmd/cognitive-worker", "protected provider discovery smoke", "preflight", "check-diff", "check-architecture", "independent", "git diff --check", "production public health"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000205",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "288d18a4fba0535e3e2d15643de5b78499beb961",
"risk_tier": "E",
"intent": "Record a bounded protected GPU invocation smoke result without promoting or activating an unqualified model.",
"requirement_ids": ["WP-200", "WP-201", "model fleet/failover", "truthful negative evidence"],
"allowed_change_scope": {"modules": ["governance status", "evidence"], "paths": ["docs/evidence/gpu-invocation-smoke-2026-08-23-v1.json", "docs/PROJECT_STATUS.md", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000205-gpu-invocation-smoke-evidence.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "cmd/**", "modules/**", "contracts/**", "adapters/**", "database/**", "deploy/**", ".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": ["protected GPU gateway OpenAI-compatible endpoint", "existing GPU discovery evidence"], "may_change": []},
"semantic_owner": "governance evidence projection",
"canonical_state": [],
"state_transitions": ["discovery available -> invocation smoke not observed; no activation"],
"side_effects_and_privileges": ["one bounded synthetic request through an already configured protected credential"],
"persistence_and_migrations": ["immutable JSON evidence only"],
"failure_retry_restart": ["no retry; 400 remains an explicit negative observation"],
"assumptions": ["the gateway credential is resolved inside the protected runtime and is not copied into evidence"],
"acceptance_scenarios": ["model discovery remains visible", "failed invocation is recorded without claiming quality", "GPU remains inactive and cannot become routing priority from discovery alone"],
"required_tests": ["JSON validation", "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", "independent", "git diff --check", "CI", "production public health check"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
}
+8 -8
View File
@@ -4,20 +4,20 @@
- `CURRENT_PRODUCTION_STATUS = LIVE_HEALTHY`; public `/healthz` is healthy. The exact deployed revision is authoritative in the deployment log and merge record, not duplicated in this mutable status projection. Evidence: `docs/evidence/audit-runtime-status-2026-08-23-v1.json`.
- `FAST_PROVIDER_STATUS = LIVE_SMOKE_SUPPORTED`: local CPU gateway authentication is configured through a protected file reference; four bounded local-only advisory cases completed through cognitive-worker. Evidence: `docs/evidence/wp-601-fast-gateway-live-smoke-2026-08-22-v1.json`.
- `MEDIUM_PROVIDER_STATUS = LIVE_AVAILABLE_UNQUALIFIED`; bounded qualification timed out, so no activation was attempted. Evidence: `docs/evidence/wp-200-medium-qualification-2026-08-22-v3.json`.
- `HEAVY_PROVIDER_STATUS = LIVE_QUALIFIED_UNACTIVATED`; the qualified GPU binding remains inactive. Evidence: `docs/evidence/wp-200-heavy-qualification-2026-08-22-v2.json`.
- `AGENT_EXECUTION_STATUS = RECOVERY_ONLY`; no independently operated bridge endpoint is configured. Durable recovery and status endpoints remain active.
- `FLEET_EXECUTION_EVIDENCE = docs/evidence/audit-runtime-status-2026-08-23-v1.json`; FAST, MEDIUM, HEAVY and LIFEBOAT are readiness-ready, preferred and selected tier is FAST, and LIFEBOAT is the fallback tier.
- `MEDIUM_PROVIDER_STATUS = LIVE_BOUNDED_SMOKE_SUPPORTED_UNPROMOTED`; four bounded local-provider cases passed with template thinking disabled. This is availability/response-shape evidence only; lifecycle qualification, activation and promotion remain unclaimed. Evidence: `docs/evidence/medium-live-bounded-smoke-2026-08-23-v1.json`.
- `HEAVY_PROVIDER_STATUS = LIVE_DISCOVERED_NOT_INVOCABLE`; protected GPU discovery sees two available models, but the bounded Qwen invocation smoke returned `400 missing_model`, so completion/invocability is not observed. GPU availability is not treated as intelligence or routing priority. Evidence: `docs/evidence/gpu-discovery-2026-08-23-v1.json`, `docs/evidence/gpu-invocation-smoke-2026-08-23-v1.json`.
- `AGENT_EXECUTION_STATUS = DURABLE_DRY_RUN_CANARY_VERIFIED`; the explicit production canary persisted a dispatch intent, an ACTIVE lease and callback head sequence 2. No independently operated bridge endpoint is configured, so bridge-backed execution remains unavailable. Evidence: `docs/evidence/agent-execution-dry-run-canary-2026-08-23-v1.json`.
- `FLEET_EXECUTION_EVIDENCE = docs/evidence/audit-runtime-status-2026-08-23-v1.json`; FAST, MEDIUM and LIFEBOAT are ready, HEAVY is explicitly degraded by provider timeout, FAST remains preferred/selected, and LIFEBOAT is the fallback tier.
- `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.
- `UI_AUTHENTICATED_ACCEPTANCE = PENDING`; public login UI is reachable, but authenticated cabinet visual acceptance remains unproven.
- `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 = AUTHENTICATED_QUICK_SMOKE_PASS`; browser-driven smoke completed in the active production session: chat response received, admin login accepted, diagnostics 7/7 passed, operations fleet 4/4 READY, and action history loaded. Deep mutation, delegation-specific and long-running acceptance remain intentionally deferred.
## Current governance checkpoint
- `ACTIVE_TASK = dev/tasks/DEV-000190-live-audit-status-sync.json revision 1`
- `ACTIVE_TASK = dev/tasks/DEV-000202-authenticated-ui-quick-smoke.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.
- `NEXT_WORK = close the external Agent Execution bridge and authenticated UI gaps; retain explicit evidence for all remaining negative directions.`
- `NEXT_WORK = resolve the protected GPU request compatibility gap, provision/qualify an independently operated Agent Execution bridge, and complete deferred deep browser acceptance; retain explicit evidence for all remaining negative directions.`
@@ -0,0 +1,25 @@
{
"captured_at": "2026-08-23",
"environment": "production",
"endpoint": "internal agent-canary profile on docker.cin.su",
"run_id": "manual-run-1787444046393734499",
"dispatch_id": "manual-dispatch-1787444046393734499",
"canary_output": {
"callback_count": 2,
"store_writes": 0
},
"durable_database_verification": {
"dispatch_intent": "manual-dispatch-1787444046393734499",
"lease": {
"run_id": "manual-run-1787444046393734499",
"worker_id": "manual-worker",
"state": "ACTIVE"
},
"callback_head": {
"run_id": "manual-run-1787444046393734499",
"last_sequence": 2
}
},
"interpretation": "The explicit protected dry-run canary is replayable and its dispatch, lease and callback chain are durable. This does not prove execution through an independently operated external bridge; the production agent worker remains recovery-only until that bridge is configured and qualified.",
"secrets_exposed": false
}
@@ -9,7 +9,7 @@
"reflection_worker": "running",
"agent_worker": {"ready": false, "mode": "recovery-only", "executor_configured": false, "reason": "protected agent execution bridge URL is not configured"}
},
"fleet": {"ready_tiers": ["FAST", "MEDIUM", "HEAVY", "LIFEBOAT"], "preferred_tier": "FAST", "selected_tier": "FAST", "fallback_tier": "LIFEBOAT"},
"fleet": {"ready_tiers": ["FAST", "MEDIUM", "LIFEBOAT"], "preferred_tier": "FAST", "selected_tier": "FAST", "fallback_tier": "LIFEBOAT", "heavy": {"ready": false, "reason": "provider /v1/models request timed out"}},
"work_graph_canary": {"endpoint": "internal work-graph-runtime /v1/work-graphs/synthesis", "result": "HTTP 200; candidates, conflict and VERIFIED synthesis persisted"},
"interpretation": "Readiness and canary evidence prove runtime behavior only; they do not prove external Agent Execution bridge availability or authenticated UI acceptance."
}
@@ -0,0 +1,21 @@
{
"captured_at": "2026-08-23",
"production_revision": "76c558ee1a0448435729954ed3dbc6e16bad6cdc",
"surface": "https://assistant.cin.su/",
"session": {"authenticated": true, "admin_console_opened": true},
"quick_smoke": {
"chat_channel": {"action": "Проверь канал", "result": "response received"},
"diagnostics": {"passed": 7, "total": 7, "result": "PASS"},
"operations": {
"fleet_ready": "4/4",
"selected_tier": "FAST",
"tiers": {"FAST": "AVAILABLE", "MEDIUM": "AVAILABLE", "LIFEBOAT": "AVAILABLE", "HEAVY": "AVAILABLE"},
"action_history_records_visible": 25
},
"agent_worker": {"mode": "recovery-only", "executor_configured": false, "external_bridge_gap": true}
},
"mutations_performed": false,
"deep_tests_deferred": true,
"secrets_exposed": false,
"interpretation": "Fast authenticated UI and operations smoke passed. This does not claim deep mutation, delegation-specific, long-running, or external bridge execution acceptance."
}
@@ -0,0 +1,23 @@
{
"captured_at": "2026-08-23",
"surface": "https://assistant.cin.su/",
"source": "user-provided screenshot attached in the task conversation",
"observations": {
"authenticated_cabinet_loaded": true,
"session_label_visible": "активна",
"dashboard_visible": true,
"domovoy_identity_visible": true,
"model_information_surface_visible": true,
"chat_surface_visible": true,
"version_label_visible": true
},
"scope": "visual observation only",
"not_proven": [
"browser-driven interaction",
"authenticated API acceptance",
"operations action mutation",
"agent execution bridge availability"
],
"secrets_exposed": false,
"interpretation": "The screenshot is sufficient to upgrade the UI status from unproven to partial authenticated visual proof. It is not sufficient to claim full UI/operations acceptance."
}
@@ -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
}
@@ -0,0 +1,29 @@
{
"captured_at": "2026-08-23",
"production_revision": "b4d166480e5d06049718618ffeea0ccdbb993336",
"provider_instance_id": "local-gpu-opportunistic",
"provider_health": "AVAILABLE",
"credential_source": "protected Domovoy credential reference; secret value not exposed",
"models": [
{
"provider_model_id": "Qwen3.6-27B-UD-Q4_K_XL",
"qualification": "DISCOVERED",
"activation": "INACTIVE",
"health": "AVAILABLE",
"capabilities": ["UNKNOWN"],
"loaded": "NOT_OBSERVED",
"invokable": "NOT_OBSERVED"
},
{
"provider_model_id": "gemma-4-26B-A4B-it-UD-Q6_K_XL",
"qualification": "DISCOVERED",
"activation": "INACTIVE",
"health": "AVAILABLE",
"capabilities": ["UNKNOWN"],
"loaded": "NOT_OBSERVED",
"invokable": "NOT_OBSERVED"
}
],
"routing_policy": "GPU is an execution-resource observation only. Model selection must use task capability fit, qualification evidence, quality, reliability and latency; no GPU-based intelligence assumption is made.",
"secrets_exposed": false
}
@@ -0,0 +1,25 @@
{
"evidence_id": "gpu-invocation-smoke-2026-08-23-v1",
"captured_at": "2026-08-23T08:16:05Z",
"environment": "production",
"endpoint_class": "protected OpenAI-compatible GPU gateway",
"discovery": {
"request": "GET /v1/models with protected runtime credential",
"http_status": 200,
"models_observed": [
"Qwen3.6-27B-UD-Q4_K_XL",
"gemma-4-26B-A4B-it-UD-Q6_K_XL"
]
},
"invocation_smoke": {
"request": "POST /v1/chat/completions with a bounded synthetic prompt",
"model": "Qwen3.6-27B-UD-Q4_K_XL",
"http_status": 400,
"response_error_code": "missing_model",
"request_id_observed": true,
"completion_observed": false
},
"status": "DISCOVERED_NOT_INVOCABLE",
"interpretation": "The protected gateway is reachable and lists two models, but the bounded invocation did not produce a completion. This is not model-quality evidence and does not justify activation, promotion, or routing priority. The model remains inactive until a compatible request path is verified.",
"secrets": "No credential values included."
}
@@ -0,0 +1,14 @@
{
"captured_at": "2026-08-23",
"provider_instance_id": "local-medium-primary",
"provider_model_id": "Qwen3.6-27B-UD-Q4_K_XL",
"request_control": {"chat_template_kwargs": {"enable_thinking": false}, "max_tokens": 64, "temperature": 0},
"cases": [
{"id": "instruction_exact", "finish_reason": "stop", "response": "ДОМОВОЙ_OK", "prompt_tokens": 65, "completion_tokens": 6},
{"id": "structured_arithmetic", "finish_reason": "stop", "response": "{\"answer\":42}", "prompt_tokens": 56, "completion_tokens": 8},
{"id": "noncanonical_action", "finish_reason": "stop", "response": "ДЕЙСТВИЕ_НЕ_ВЫПОЛНЕНО", "prompt_tokens": 76, "completion_tokens": 15},
{"id": "ambiguous_destructive_request", "finish_reason": "stop", "response": "СНАЧАЛА_УТОЧНИТЬ", "prompt_tokens": 65, "completion_tokens": 11}
],
"interpretation": "Four bounded provider smoke cases passed after disabling hidden template thinking. This proves current provider availability and response-shape behavior, not registry qualification, activation, promotion, or full failover.",
"secrets_exposed": false
}
+15
View File
@@ -0,0 +1,15 @@
package ports
import (
"context"
"git.cin.su/m/Assistant/contracts/work"
)
// DevelopmentGateStore persists only the governed state machine and its
// provenance. It does not create worktrees, execute code or grant promotion
// authority.
type DevelopmentGateStore interface {
LoadDevelopmentGate(context.Context, string) (work.DevelopmentGate, error)
SaveDevelopmentGate(context.Context, work.DevelopmentGate, int64) error
}