chore: auto-commit (97 archivos)
- .claude/CLAUDE.md - .claude/agents/fn-recopilador/SKILL.md - .claude/rules/INDEX.md - .claude/rules/cpp_apps.md - bash/functions/infra/build_cpp_windows.sh - cpp/CMakeLists.txt - cpp/PATTERNS.md - cpp/framework/app_base.cpp - cpp/framework/app_base.h - dev/issues/README.md - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
package infra
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
// ProposalFromFailure creates a proposal row in registry.db for each failed
|
||||
// CheckResult. It opens the database at registryDB, filters results with
|
||||
// Status=="fail", and inserts one proposal per failure using:
|
||||
// - kind="new_function" for severity=="critical" checks (highest urgency proxy)
|
||||
// - kind="improve_function" for severity=="warning" checks
|
||||
//
|
||||
// Note: the proposals table kind constraint only allows
|
||||
// (new_function, new_type, improve_function, improve_type, new_pipeline).
|
||||
// Until a dedicated "bug" kind is added, we use new_function/improve_function
|
||||
// as the closest proxies for critical and warning failures respectively.
|
||||
//
|
||||
// Returns the list of proposal IDs created, or an error if the DB cannot be
|
||||
// opened or any INSERT fails.
|
||||
func ProposalFromFailure(registryDB string, appID string, results []CheckResult, executionID string) ([]string, error) {
|
||||
db, err := SQLiteOpen(registryDB, "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("proposal_from_failure: open registry db: %w", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
var created []string
|
||||
now := time.Now().UTC().Format(time.RFC3339)
|
||||
|
||||
for _, r := range results {
|
||||
if r.Status != "fail" {
|
||||
continue
|
||||
}
|
||||
|
||||
propID, err := generatePropID()
|
||||
if err != nil {
|
||||
return created, fmt.Errorf("proposal_from_failure: generate id: %w", err)
|
||||
}
|
||||
|
||||
kind := proposalKind(r.Severity)
|
||||
title := fmt.Sprintf("e2e fail: %s::%s", appID, r.ID)
|
||||
desc := buildDescription(r)
|
||||
|
||||
evidence, _ := json.Marshal(map[string]any{
|
||||
"check_id": r.ID,
|
||||
"execution_id": executionID,
|
||||
"exit_code": r.ExitCode,
|
||||
"error": r.Error,
|
||||
"severity": r.Severity,
|
||||
})
|
||||
|
||||
_, err = db.Exec(`
|
||||
INSERT INTO proposals (id, kind, target_id, title, description, evidence, status, created_by, reviewed_by, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, 'pending', 'reactive_loop', '', ?, ?)`,
|
||||
propID, kind, appID, title, desc, string(evidence), now, now,
|
||||
)
|
||||
if err != nil {
|
||||
return created, fmt.Errorf("proposal_from_failure: insert proposal %s: %w", propID, err)
|
||||
}
|
||||
created = append(created, propID)
|
||||
}
|
||||
|
||||
return created, nil
|
||||
}
|
||||
|
||||
// proposalKind maps check severity to an allowed proposals.kind value.
|
||||
// critical -> new_function (highest urgency proxy)
|
||||
// warning -> improve_function
|
||||
func proposalKind(severity string) string {
|
||||
if severity == "warning" {
|
||||
return "improve_function"
|
||||
}
|
||||
return "new_function"
|
||||
}
|
||||
|
||||
// buildDescription assembles a human-readable description for the proposal.
|
||||
func buildDescription(r CheckResult) string {
|
||||
desc := fmt.Sprintf("E2E check %q failed (severity: %s, exit_code: %d).", r.ID, r.Severity, r.ExitCode)
|
||||
if r.Error != "" {
|
||||
desc += "\n\nError: " + r.Error
|
||||
}
|
||||
if r.Stdout != "" {
|
||||
desc += "\n\nStdout:\n" + r.Stdout
|
||||
}
|
||||
if r.Stderr != "" {
|
||||
desc += "\n\nStderr:\n" + r.Stderr
|
||||
}
|
||||
desc += "\n\nSugerencia: revisar el comando/endpoint del check y el estado del servicio."
|
||||
return desc
|
||||
}
|
||||
|
||||
// generatePropID generates a random proposal ID of the form "prop_<16hexchars>".
|
||||
func generatePropID() (string, error) {
|
||||
b := make([]byte, 8)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return "", fmt.Errorf("crypto/rand: %w", err)
|
||||
}
|
||||
return "prop_" + hex.EncodeToString(b), nil
|
||||
}
|
||||
Reference in New Issue
Block a user