Compare commits

..
Author SHA1 Message Date
m c5b5055ff1 fix(cognitive): separate reachability from quality evidence
CI / test (push) Successful in 1m9s
CI / test (pull_request) Successful in 59s
2026-08-23 14:02:02 +03:00
m 7476f43ffa feat(capability): gate additional model evaluations
CI / test (push) Successful in 1m5s
feat(capability): gate additional model evaluations (#195)
2026-08-23 10:57:52 +00:00
m be29ed5776 feat(capability): gate additional model evaluations
CI / test (push) Successful in 1m8s
CI / test (pull_request) Successful in 59s
2026-08-23 13:56:16 +03:00
m ab840878fe docs(status): refresh current runtime evidence
CI / test (push) Successful in 58s
docs(status): refresh current runtime evidence (#194)
2026-08-23 10:52:12 +00:00
m aebc932b97 docs(status): refresh current runtime evidence
CI / test (push) Successful in 1m2s
CI / test (pull_request) Successful in 1m7s
2026-08-23 13:50:44 +03:00
m 05a246ea3f fix(agent-worker): report local fallback truthfully
CI / test (push) Successful in 1m5s
fix(agent-worker): report local fallback truthfully (#193)
2026-08-23 10:42:50 +00:00
m c847988630 fix(agent-worker): report local fallback truthfully
CI / test (push) Successful in 1m3s
CI / test (pull_request) Successful in 1m3s
2026-08-23 13:41:22 +03:00
m 62f0c529b3 feat(work): persist governed development candidates
CI / test (push) Successful in 53s
feat(work): persist governed development candidates (#192)
2026-08-23 10:29:05 +00:00
m 54958d0902 feat(work): persist governed development candidates
CI / test (push) Successful in 54s
CI / test (pull_request) Successful in 58s
2026-08-23 13:26:41 +03:00
m 8d3e7f7cac feat(work): make agent execution recovery durable
CI / test (push) Successful in 1m4s
DEV-000214 durable Agent Execution recovery
2026-08-23 10:15:19 +00:00
19 changed files with 391 additions and 27 deletions
+27 -4
View File
@@ -18,10 +18,11 @@ 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")
ErrDevelopmentGateConflict = errors.New("development gate revision conflict")
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")
ErrDevelopmentCandidateConflict = errors.New("development candidate conflict")
)
func OpenWork(ctx context.Context, config ContinuityConfig) (*WorkRepository, error) {
@@ -104,6 +105,28 @@ func (r *WorkRepository) SaveDevelopmentGate(ctx context.Context, gate work.Deve
return nil
}
func (r *WorkRepository) SaveExtensionProposal(ctx context.Context, value work.ExtensionProposal) error {
result, err := r.pool.Exec(ctx, `INSERT INTO work.extension_proposals(proposal_id,requested_by_principal_id,stage,evidence_refs,deduplicated_signal_keys,desired_outcome,smallest_change_layer,affected_owners,affected_contracts,risk_tier,evaluation_plan,alternatives,rollback_plan,assumptions,created_at_unix_millis) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15) ON CONFLICT(proposal_id) DO NOTHING`, value.ID, value.RequestedByPrincipalID, value.Stage, value.EvidenceRefs, value.DeduplicatedSignalKeys, value.DesiredOutcome, value.SmallestChangeLayer, value.AffectedOwners, value.AffectedContracts, value.RiskTier, value.EvaluationPlan, value.Alternatives, value.RollbackPlan, value.Assumptions, value.CreatedAtUnixMillis)
if err != nil {
return err
}
if result.RowsAffected() != 1 {
return ErrDevelopmentCandidateConflict
}
return nil
}
func (r *WorkRepository) SaveDevelopmentScaffold(ctx context.Context, value work.DevelopmentScaffold) error {
result, err := r.pool.Exec(ctx, `INSERT INTO work.development_scaffolds(scaffold_id,requested_by_principal_id,stage,proposal_ref,base_repo_revision,worktree_ref,task_intent,modules,allowed_paths,forbidden_paths,required_tests,artifact_lineage_refs,protected_main_access,production_access,secret_access,created_at_unix_millis) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16) ON CONFLICT(scaffold_id) DO NOTHING`, value.ID, value.RequestedByPrincipalID, value.Stage, value.ProposalRef, value.BaseRepoRevision, value.WorktreeRef, value.TaskIntent, value.Modules, value.AllowedPaths, value.ForbiddenPaths, value.RequiredTests, value.ArtifactLineageRefs, value.ProtectedMainAccess, value.ProductionAccess, value.SecretAccess, value.CreatedAtUnixMillis)
if err != nil {
return err
}
if result.RowsAffected() != 1 {
return ErrDevelopmentCandidateConflict
}
return nil
}
func (r *WorkRepository) SaveDispatchIntent(ctx context.Context, intent work.AgentDispatchIntent) error {
tx, err := r.pool.Begin(ctx)
if err != nil {
+3
View File
@@ -49,6 +49,9 @@ func main() {
os.Exit(1)
}
} else {
// The local evaluator keeps task-qualification work alive, but it is not
// an external Agent Execution Bridge and must never be reported as one.
localFallback = true
executor = newTaskEvaluationExecutor(envOr("COGNITIVE_WORKER_URL", "http://cognitive-worker:8083"), envOr("WORK_GRAPH_RUNTIME_URL", "http://work-graph-runtime:8088"), &http.Client{Timeout: *leaseTTL})
fmt.Fprintln(os.Stderr, "protected agent execution bridge URL is not configured; task evaluations use the local durable evaluator, other work remains in fallback")
}
+12
View File
@@ -50,6 +50,18 @@ func TestWorkerStatusReportsLocalFallback(t *testing.T) {
}
}
func TestWorkerStatusDoesNotCallLocalFallbackAnExternalExecutor(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 value.ExecutorConfigured || value.Ready || !value.LocalFallback || value.Mode != "local-fallback" {
t.Fatalf("local fallback was presented as external execution: %+v", value)
}
}
func TestWorkerReadyzRequiresExecutor(t *testing.T) {
response := httptest.NewRecorder()
workerStatusHandler(false).ServeHTTP(response, httptest.NewRequest(http.MethodGet, "/readyz", nil))
+4 -3
View File
@@ -68,9 +68,10 @@ func (g cognitiveGateway) taskEvaluationHandler(w http.ResponseWriter, r *http.R
response, invokeErr := g.invokeAdmitted(r.Context(), string(invocation.RequestID), provider, invocation, int(request.MaxOutputBytes))
observation := capability.TaskCaseObservation{CaseID: item.CaseID, LatencyMicros: time.Since(started).Microseconds(), EvidenceArtifactRef: item.EvidenceArtifactRef}
if invokeErr == nil && response.FinishReason == cognitive.FinishCompleted && response.AdvisoryText != "" {
observation.Result = capability.EvaluationSupported
// Invocation success proves reachability/support for this case,
// not semantic answer quality. A verifier may score quality later.
// Invocation success proves reachability only. Without an
// independent verifier and answer evidence, semantic support and
// quality must remain UNKNOWN rather than becoming false evidence.
observation.Result = capability.EvaluationUnknown
observation.QualityScoreMillis = 0
} else {
observation.Result = capability.EvaluationUnknown
+6 -1
View File
@@ -47,7 +47,12 @@ func TestTaskEvaluationHandlerInvokesEveryBoundedCase(t *testing.T) {
if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil {
t.Fatal(err)
}
if len(response.Observations) != 2 || response.Observations[0].Result != capability.EvaluationSupported || response.Observations[1].Result != capability.EvaluationSupported {
if len(response.Observations) != 2 || response.Observations[0].Result != capability.EvaluationUnknown || response.Observations[1].Result != capability.EvaluationUnknown {
t.Fatalf("unexpected observations: %+v", response.Observations)
}
for _, observation := range response.Observations {
if observation.QualityScoreMillis != 0 || observation.CriticalFailure {
t.Fatalf("reachability-only evidence must not carry quality or failure claims: %+v", observation)
}
}
}
+55
View File
@@ -178,6 +178,61 @@ func main() {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(session)
})
mux.HandleFunc("POST /v1/creator/development/proposals", func(w http.ResponseWriter, r *http.Request) {
session, ok := authenticateCreator(w, r)
if !ok {
return
}
var request struct {
Evidence []work.ExtensionEvidence `json:"evidence"`
Proposal work.ExtensionProposalRequest `json:"proposal"`
}
decoder := json.NewDecoder(http.MaxBytesReader(w, r.Body, 64<<10))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&request); err != nil {
http.Error(w, "invalid development proposal", http.StatusBadRequest)
return
}
proposal, err := workdomain.BuildExtensionProposal(request.Evidence, request.Proposal)
if err != nil {
http.Error(w, "development proposal rejected", http.StatusUnprocessableEntity)
return
}
proposal.RequestedByPrincipalID = string(session.PrincipalID)
if err := workRepository.SaveExtensionProposal(r.Context(), proposal); err != nil {
http.Error(w, "development proposal conflict", http.StatusConflict)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
_ = json.NewEncoder(w).Encode(proposal)
})
mux.HandleFunc("POST /v1/creator/development/scaffolds", func(w http.ResponseWriter, r *http.Request) {
session, ok := authenticateCreator(w, r)
if !ok {
return
}
var request work.DevelopmentScaffoldRequest
decoder := json.NewDecoder(http.MaxBytesReader(w, r.Body, 64<<10))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&request); err != nil {
http.Error(w, "invalid development scaffold", http.StatusBadRequest)
return
}
scaffold, err := workdomain.BuildDevelopmentScaffold(request)
if err != nil {
http.Error(w, "development scaffold rejected", http.StatusUnprocessableEntity)
return
}
scaffold.RequestedByPrincipalID = string(session.PrincipalID)
if err := workRepository.SaveDevelopmentScaffold(r.Context(), scaffold); err != nil {
http.Error(w, "development scaffold conflict", http.StatusConflict)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
_ = json.NewEncoder(w).Encode(scaffold)
})
mux.HandleFunc("GET /v1/creator/focus", func(w http.ResponseWriter, r *http.Request) {
session, ok := authenticateCreator(w, r)
if !ok {
+17 -15
View File
@@ -70,6 +70,7 @@ type ExtensionProposalRequest struct {
// authority grant, implementation body or promotion decision.
type ExtensionProposal struct {
ID string
RequestedByPrincipalID string
Stage ExtensionProposalStage
EvidenceRefs []string
DeduplicatedSignalKeys []string
@@ -113,19 +114,20 @@ type DevelopmentScaffoldRequest struct {
// DevelopmentScaffold is a provenance-linked task-packet candidate. It has
// no executable instruction, credential, checkout handle or authority grant.
type DevelopmentScaffold struct {
ID string
Stage DevelopmentScaffoldStage
ProposalRef string
BaseRepoRevision string
WorktreeRef string
TaskIntent string
Modules []string
AllowedPaths []string
ForbiddenPaths []string
RequiredTests []string
ArtifactLineageRefs []string
ProtectedMainAccess string
ProductionAccess string
SecretAccess string
CreatedAtUnixMillis int64
ID string
RequestedByPrincipalID string
Stage DevelopmentScaffoldStage
ProposalRef string
BaseRepoRevision string
WorktreeRef string
TaskIntent string
Modules []string
AllowedPaths []string
ForbiddenPaths []string
RequiredTests []string
ArtifactLineageRefs []string
ProtectedMainAccess string
ProductionAccess string
SecretAccess string
CreatedAtUnixMillis int64
}
@@ -0,0 +1,45 @@
BEGIN;
SET ROLE work_role;
CREATE TABLE IF NOT EXISTS work.extension_proposals (
proposal_id TEXT PRIMARY KEY,
requested_by_principal_id TEXT NOT NULL,
stage TEXT NOT NULL,
evidence_refs TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
deduplicated_signal_keys TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
desired_outcome TEXT NOT NULL,
smallest_change_layer TEXT NOT NULL,
affected_owners TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
affected_contracts TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
risk_tier TEXT NOT NULL,
evaluation_plan TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
alternatives TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
rollback_plan TEXT NOT NULL,
assumptions TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
created_at_unix_millis BIGINT NOT NULL,
CHECK (proposal_id <> ''), CHECK (requested_by_principal_id <> ''), CHECK (stage = 'PROPOSED'), CHECK (desired_outcome <> ''), CHECK (smallest_change_layer <> ''), CHECK (risk_tier <> ''), CHECK (rollback_plan <> ''), CHECK (created_at_unix_millis > 0)
);
CREATE TABLE IF NOT EXISTS work.development_scaffolds (
scaffold_id TEXT PRIMARY KEY,
requested_by_principal_id TEXT NOT NULL,
stage TEXT NOT NULL,
proposal_ref TEXT NOT NULL,
base_repo_revision TEXT NOT NULL,
worktree_ref TEXT NOT NULL,
task_intent TEXT NOT NULL,
modules TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
allowed_paths TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
forbidden_paths TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
required_tests TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
artifact_lineage_refs TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
protected_main_access TEXT NOT NULL,
production_access TEXT NOT NULL,
secret_access TEXT NOT NULL,
created_at_unix_millis BIGINT NOT NULL,
CHECK (scaffold_id <> ''), CHECK (requested_by_principal_id <> ''), CHECK (stage = 'SANDBOXED'), CHECK (proposal_ref <> ''), CHECK (base_repo_revision <> ''), CHECK (worktree_ref <> ''), CHECK (task_intent <> ''), CHECK (protected_main_access = 'DENIED'), CHECK (production_access = 'DENIED'), CHECK (secret_access = 'DENIED'), CHECK (created_at_unix_millis > 0)
);
RESET ROLE;
COMMIT;
+2 -2
View File
@@ -1,5 +1,5 @@
{
"task_file": "dev/tasks/DEV-000214-agent-execution-recovery.json",
"task_id": "DEV-000214",
"task_file": "dev/tasks/DEV-000219-reachability-not-quality.json",
"task_id": "DEV-000219",
"task_revision": 1
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000215",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "8d3e7f7cac236aa50919bd1cd854012dcc8500a5",
"risk_tier": "E",
"intent": "Expose a durable, authenticated control-plane boundary for governed self-development proposals and isolated scaffold candidates without executing source mutation, bypassing verification, or granting promotion authority.",
"requirement_ids": ["durable proposal intake", "isolated scaffold contract", "authenticated operator boundary", "no implicit promotion"],
"allowed_change_scope": {"modules": ["work", "core-runtime"], "paths": ["contracts/work/self_development.go", "modules/work/domain/**", "cmd/core-runtime/main.go", "adapters/postgres/work_repository.go", "database/migrations/043_governed_development_candidates.sql", "tests/semantic_evolution/**", "tests/work/**", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000215-governed-development-control-plane.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "deploy/**", "cmd/devctl/**", "modules/identity/**", "modules/capability/**", "LLM-local/**"]},
"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": ["ADR-0022 governed self-development boundary", "creator authentication", "work development gate"], "may_change": ["work-owned proposal/scaffold persistence and authenticated control-plane endpoints"]},
"semantic_owner": "work owns proposal, scaffold and development gate lineage",
"canonical_state": ["work-owned extension proposal and scaffold candidates are durable; source tree and production remain outside this task"],
"state_transitions": ["repeated evidence -> PROPOSED", "proposal -> SANDBOXED scaffold candidate", "gate remains explicit and cannot be promoted by these endpoints"],
"side_effects_and_privileges": ["authenticated creator session required; database writes stay within work owner; no checkout, source mutation, deployment or secret access"],
"persistence_and_migrations": ["043 adds durable work-owned proposal/scaffold candidate records"],
"failure_retry_restart": ["idempotent candidate IDs preserve lineage; duplicate IDs are rejected; no endpoint advances promotion stage"],
"assumptions": ["an independent executor and verifier remain separate future capabilities"],
"acceptance_scenarios": ["unauthenticated requests are rejected", "repeated evidence creates a durable proposal", "protected paths cannot create a scaffold", "valid scaffold is durable and remains SANDBOXED", "no promotion or source mutation occurs"],
"required_tests": ["go test", "go vet", "preflight", "check-diff", "check-architecture", "independent", "git diff --check", "migration/schema checks", "CI", "production public health check"],
"terminal_gap_states": ["BLOCKED_BY_SPEC_GAP", "BLOCKED_BY_ARCHITECTURE_GAP", "BLOCKED_BY_MISSING_CAPABILITY"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000216",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "62f0c529b3f8b3c92e4a69fcc6298d59b3015fde",
"risk_tier": "E",
"intent": "Keep agent-worker status truthful when the protected external execution bridge is absent while retaining local task-evaluation fallback.",
"requirement_ids": ["WP-301", "truthful degraded status", "local fallback"],
"allowed_change_scope": {"modules": ["agent-worker"], "paths": ["cmd/agent-worker/main.go", "cmd/agent-worker/status_test.go", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000216-agent-worker-status-truth.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "database/**", "deploy/**", "security/**", "contracts/**", "modules/**", "LLM-local/**"]},
"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 bridge file", "agent-worker status response", "local task-evaluation fallback"], "may_change": []},
"semantic_owner": "work",
"canonical_state": ["existing worker status projection and durable dispatch lifecycle"],
"state_transitions": ["bridge absent -> local-fallback status", "bridge present -> execution status"],
"side_effects_and_privileges": ["no external mutation; no new credentials; no persistence change"],
"persistence_and_migrations": ["none"],
"failure_retry_restart": ["bridge absence remains explicit after restart; local evaluator remains available for bounded qualification work"],
"assumptions": ["task-evaluation fallback is not general external agent execution"],
"acceptance_scenarios": ["worker marks local_fallback when protected bridge URL is absent", "status never reports executor_configured=true for local fallback", "configured bridge path remains execution mode", "no secret value is exposed"],
"required_tests": ["go test ./cmd/agent-worker", "go vet ./cmd/agent-worker", "preflight", "check-diff", "check-architecture", "independent", "git diff --check", "CI", "production worker status"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000217",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "05a246ea3f240a77be769969ad62a236fba33bac",
"risk_tier": "E",
"intent": "Refresh the project status projection and redacted live evidence after the agent-worker truthful fallback fix without changing runtime behavior.",
"requirement_ids": ["current audit evidence", "task lineage accuracy", "negative-state transparency"],
"allowed_change_scope": {"modules": ["operations-evidence"], "paths": ["docs/PROJECT_STATUS.md", "docs/evidence/audit-runtime-status-2026-08-23-v2.json", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000217-current-status-evidence.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "cmd/**", "modules/**", "contracts/**", "database/**", "deploy/**", "LLM-local/**"]},
"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 health/readiness/status responses", "merged task lineage"], "may_change": ["operations status projection and redacted evidence artifact"]},
"semantic_owner": "operations-evidence projection",
"canonical_state": ["none; docs and evidence are rebuildable projections"],
"state_transitions": ["stale status projection -> current evidence projection"],
"side_effects_and_privileges": ["read-only live checks; no secrets, credentials or runtime mutation"],
"persistence_and_migrations": ["none"],
"failure_retry_restart": ["evidence records unavailable/degraded states explicitly; no success inferred from missing data"],
"assumptions": ["historical evidence remains immutable and is not rewritten"],
"acceptance_scenarios": ["active task points to the current merged packet", "bridge absence is reported as local fallback", "GPU timeout is reported as degraded without changing FAST preference", "authenticated UI availability is not claimed without a current signed-in session", "no secret value appears in the projection"],
"required_tests": ["go test", "go vet", "preflight", "check-diff", "check-architecture", "independent", "git diff --check", "CI", "production public health and runtime status"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
}
@@ -0,0 +1,23 @@
{
"task_id": "DEV-000218",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "ab840878fe7d21a0a6aeb69193a3d58ea23a56e0",
"risk_tier": "E",
"intent": "Add a conservative deterministic policy gate for creating additional model-evaluation profiles only after general evaluation evidence remains unresolved.",
"requirement_ids": ["general-first evaluation", "bounded additional evaluation", "no unnecessary fleet-wide tests"],
"allowed_change_scope": {"modules": ["capability"], "paths": ["modules/capability/domain/task_evaluation.go", "modules/capability/domain/task_evaluation_test.go", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000218-automatic-expansion-policy.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "cmd/**", "contracts/**", "LLM-local/**"]},
"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": ["TaskEvaluationProfile", "TaskEvaluation", "TaskEvaluationExpansionRequest"], "may_change": []},
"semantic_owner": "capability owns model qualification evidence and expansion policy",
"canonical_state": ["none; this packet creates no persistence or activation authority"],
"state_transitions": ["general COMPLETED/PARTIAL unresolved evidence -> bounded additional profile candidate", "qualified candidate -> no expansion"],
"side_effects_and_privileges": ["pure deterministic decision; no provider call, no model invocation, no mutation"],
"persistence_and_migrations": ["none"],
"failure_retry_restart": ["missing trigger evidence or additional cases fails closed; repeated decision is deterministic"],
"assumptions": ["a later task supplies task-specific additional cases from an unresolved outcome and schedules them through the existing Work Graph"],
"acceptance_scenarios": ["general graph not completed/partial does not expand", "unknown/unsupported/low-scoring candidates expand only with evidence and new cases", "one qualified candidate suppresses expansion", "no provider or hardware label changes the decision"],
"required_tests": ["go test", "go vet", "preflight", "check-diff", "check-architecture", "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-000219",
"task_revision": 1,
"architecture_revision": "ADR-0018",
"base_repo_revision": "7476f43ffa57d55f5a5a9bddc7f1c74e9b87ae0e",
"risk_tier": "E",
"intent": "Prevent task-evaluation invocation success from being recorded as semantic model quality or support without independent verifier evidence.",
"requirement_ids": ["truthful model evidence", "independent verification", "no false qualification"],
"allowed_change_scope": {"modules": ["cognitive-worker"], "paths": ["cmd/cognitive-worker/task_evaluation.go", "cmd/cognitive-worker/task_evaluation_test.go", "dev/ACTIVE_TASK.json", "dev/tasks/DEV-000219-reachability-not-quality.json"]},
"forbidden_change_scope": {"paths": ["architecture/**", "security/**", "database/**", "deploy/**", "contracts/**", "modules/**", "LLM-local/**"]},
"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": ["TaskEvaluationExecutionRequest/Response", "TaskCaseObservation", "Cognitive Gateway"], "may_change": []},
"semantic_owner": "capability evidence remains owner; cognitive-worker only records invocation observation",
"canonical_state": ["existing task-evaluation evidence; no new persistence"],
"state_transitions": ["successful invocation -> UNKNOWN reachability observation", "independent verifier evidence -> future supported/quality observation"],
"side_effects_and_privileges": ["no additional provider calls or privileges"],
"persistence_and_migrations": ["none"],
"failure_retry_restart": ["unknown evidence remains retryable/eligible for a separately verified evaluation; no promotion follows invocation alone"],
"assumptions": ["a later verifier task will attach answer-quality evidence and score cases"],
"acceptance_scenarios": ["nonempty provider response is not SUPPORTED", "quality score remains zero", "provider invocation failure remains UNKNOWN with critical failure", "no model/hardware label can manufacture quality evidence"],
"required_tests": ["go test", "go vet", "preflight", "check-diff", "check-architecture", "independent", "git diff --check", "CI", "production public health check"],
"terminal_gap_states": ["BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_SPEC_GAP"]
}
+4 -2
View File
@@ -13,13 +13,15 @@
- `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 = 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_UI_SESSION_STATUS = NO_CURRENT_AUTHENTICATED_SESSION`; the historical quick-smoke evidence above is retained, but the current acceptance run has no signed-in browser session, so no new authenticated visual result is claimed. Public cabinet shell and unauthenticated protection were checked separately.
- `AGENT_WORKER_STATUS_CORRECTION = LIVE_TRUTHFUL_LOCAL_FALLBACK`; after DEV-000216, absence of the protected bridge is reported as `executor_configured=false`, `mode=local-fallback`, `ready=false`; local task evaluation is not represented as external agent execution. Evidence: `docs/evidence/audit-runtime-status-2026-08-23-v2.json`.
## Current governance checkpoint
- `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-000207-gpu-invocation-qualification.json revision 1`
- `ACTIVE_TASK = dev/tasks/DEV-000217-current-status-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.
- `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.`
- `NEXT_WORK = provision/qualify an independently operated Agent Execution bridge when available, complete deferred deep browser acceptance with a signed-in session, and add task-quality verification only when live work produces an unresolved case; retain explicit evidence for all remaining negative directions.`
@@ -0,0 +1,33 @@
{
"observed_on": "2026-08-23",
"source": "production docker.cin.su read-only live checks",
"public": {
"healthz": {"status": 200, "runtime": "creator-web"}
},
"agent_worker": {
"runtime": "agent-worker",
"executor_configured": false,
"mode": "local-fallback",
"ready": false,
"local_fallback": true,
"reason": "external bridge unavailable; durable work is retained without external mutation"
},
"fleet": {
"preferred_tier": "FAST",
"selected_tier": "FAST",
"ready_tiers": ["FAST", "MEDIUM", "LIFEBOAT"],
"fallback_tier": "LIFEBOAT",
"heavy": {"ready": false, "reason_class": "provider timeout"}
},
"runtimes": {
"core": "ready",
"work_graph": "ready",
"research": "ready",
"reflection_worker": "running"
},
"ui": {
"public_admin_shell": "available",
"authenticated_browser_session": "not_available_for_current_acceptance"
},
"secret_policy": "values omitted; only typed states and reason classes retained"
}
@@ -2,6 +2,7 @@ package domain
import (
"errors"
"fmt"
"git.cin.su/m/Assistant/contracts/artifact"
"git.cin.su/m/Assistant/contracts/capability"
@@ -9,6 +10,35 @@ import (
var ErrInvalidTaskEvaluation = errors.New("invalid task evaluation")
const automaticExpansionMinimumOverallScore int64 = 700
// AutomaticTaskEvaluationExpansion decides whether a completed general
// evaluation has evidence that warrants a bounded additional profile. It is
// deliberately conservative: one supported candidate above the quality
// threshold suppresses expansion, while unknown/unsupported/low-scoring or
// critically failing candidates keep the unresolved path explicit.
func AutomaticTaskEvaluationExpansion(parent capability.TaskEvaluationProfile, parentGraphState string, evaluations []capability.TaskEvaluation, request capability.TaskEvaluationExpansionRequest, profileID capability.TaskEvaluationProfileID, revision int64) (capability.TaskEvaluationProfile, bool, error) {
if parentGraphState != "COMPLETED" && parentGraphState != "PARTIAL" {
return capability.TaskEvaluationProfile{}, false, nil
}
if len(evaluations) == 0 {
return capability.TaskEvaluationProfile{}, false, nil
}
for _, evaluation := range evaluations {
if evaluation.Result == capability.EvaluationSupported && evaluation.OverallScoreMillis >= automaticExpansionMinimumOverallScore && evaluation.CriticalFailureMillis == 0 {
return capability.TaskEvaluationProfile{}, false, nil
}
}
if request.TriggerEvidenceRef == "" || len(request.NewCaseIDs) == 0 {
return capability.TaskEvaluationProfile{}, false, fmt.Errorf("unresolved task evaluation requires trigger evidence and additional cases")
}
profile, err := BuildAdditionalTaskEvaluationProfile(parent, request, profileID, revision)
if err != nil {
return capability.TaskEvaluationProfile{}, false, err
}
return profile, true, nil
}
func BuildAdditionalTaskEvaluationProfile(parent capability.TaskEvaluationProfile, request capability.TaskEvaluationExpansionRequest, profileID capability.TaskEvaluationProfileID, revision int64) (capability.TaskEvaluationProfile, error) {
if err := parent.Validate(); err != nil || parent.Stage != capability.TaskEvaluationGeneral || request.ParentProfileID != parent.ID || request.CapabilityID != parent.CapabilityID || request.TriggerEvidenceRef == "" || len(request.NewCaseIDs) == 0 || profileID == "" || revision < 1 || request.BenchmarkVersion == "" {
return capability.TaskEvaluationProfile{}, ErrInvalidTaskEvaluation
@@ -33,3 +33,21 @@ func TestBuildAdditionalProfileRequiresUnresolvedEvidenceAndPreservesHistory(t *
t.Fatalf("profile=%+v err=%v", profile, err)
}
}
func TestAutomaticExpansionWaitsForGeneralGraphAndUnresolvedCandidates(t *testing.T) {
parent := capability.TaskEvaluationProfile{ID: "general-v1", Revision: 1, CapabilityID: "creator-advisory", Stage: capability.TaskEvaluationGeneral, BenchmarkVersion: "general-v1", RequiredCaseIDs: []string{"general"}, QualityWeightMillis: 700, ReliabilityWeightMillis: 200, LatencyWeightMillis: 100}
request := capability.TaskEvaluationExpansionRequest{ParentProfileID: parent.ID, CapabilityID: parent.CapabilityID, TriggerEvidenceRef: "outcome-unsolved", NewCaseIDs: []string{"edge-case"}, BenchmarkVersion: "additional-v1"}
value, expanded, err := AutomaticTaskEvaluationExpansion(parent, "COMPLETED", []capability.TaskEvaluation{{ID: "evaluation-1", ProfileID: parent.ID, BindingID: "binding-1", BindingRevision: 1, CapabilityID: parent.CapabilityID, Result: capability.EvaluationUnknown, OverallScoreMillis: 0, CriticalFailureMillis: 1000, BenchmarkVersion: parent.BenchmarkVersion, ArtifactID: "artifact-1", ObservedAtUnixMillis: 1}}, request, "additional-v1", 1)
if err != nil || !expanded || value.Stage != capability.TaskEvaluationAdditional || value.ParentProfileID != parent.ID {
t.Fatalf("expected bounded expansion, profile=%+v expanded=%t err=%v", value, expanded, err)
}
}
func TestAutomaticExpansionDoesNotRunWhenAQualifiedCandidateExists(t *testing.T) {
parent := capability.TaskEvaluationProfile{ID: "general-v1", Revision: 1, CapabilityID: "creator-advisory", Stage: capability.TaskEvaluationGeneral, BenchmarkVersion: "general-v1", RequiredCaseIDs: []string{"general"}, QualityWeightMillis: 700, ReliabilityWeightMillis: 200, LatencyWeightMillis: 100}
request := capability.TaskEvaluationExpansionRequest{ParentProfileID: parent.ID, CapabilityID: parent.CapabilityID, TriggerEvidenceRef: "outcome-unsolved", NewCaseIDs: []string{"edge-case"}, BenchmarkVersion: "additional-v1"}
value, expanded, err := AutomaticTaskEvaluationExpansion(parent, "PARTIAL", []capability.TaskEvaluation{{ID: "evaluation-1", ProfileID: parent.ID, BindingID: "binding-1", BindingRevision: 1, CapabilityID: parent.CapabilityID, Result: capability.EvaluationSupported, OverallScoreMillis: 850, CriticalFailureMillis: 0, BenchmarkVersion: parent.BenchmarkVersion, ArtifactID: "artifact-1", ObservedAtUnixMillis: 1}}, request, "additional-v1", 1)
if err != nil || expanded || value.ID != "" {
t.Fatalf("qualified candidate must suppress expansion: profile=%+v expanded=%t err=%v", value, expanded, err)
}
}
@@ -0,0 +1,20 @@
package semantic_evolution_test
import (
"os"
"strings"
"testing"
)
func TestGovernedDevelopmentCandidateMigrationIsWorkOwnedAndSandboxed(t *testing.T) {
payload, err := os.ReadFile("../../database/migrations/043_governed_development_candidates.sql")
if err != nil {
t.Fatal(err)
}
source := strings.ToLower(string(payload))
for _, fragment := range []string{"set role work_role", "create table if not exists work.extension_proposals", "create table if not exists work.development_scaffolds", "stage = 'sandboxed'", "protected_main_access = 'denied'", "production_access = 'denied'", "secret_access = 'denied'"} {
if !strings.Contains(source, fragment) {
t.Fatalf("migration is missing %q", fragment)
}
}
}