fix: retain stock identities in research and AI task lists

This commit is contained in:
2026-10-09 23:08:47 +08:00
parent 9d56f6169a
commit c8c61d29bf
9 changed files with 29 additions and 7 deletions
@@ -129,6 +129,11 @@ func testCandidateAI(t *testing.T, ctx context.Context, pool *pgxpool.Pool, admi
if err != nil || len(results) != 4 {
t.Fatal("durable results missing", err, len(results))
}
for _, result := range results {
if result.Name != "Fixture" || result.Symbol != "000042" || result.Exchange != "SZSE" {
t.Fatal("analysis task lost candidate identity")
}
}
}
type rejectModel struct{ calls int }
@@ -95,6 +95,10 @@ func testStrategyBacktest(t *testing.T, ctx context.Context, pool *pgxpool.Pool,
if e != nil || done.Status != "COMPLETED" || done.FinishedAt == nil || len(done.Result) == 0 {
t.Fatalf("completed job: %v", e)
}
listed, e := repo.List(ctx)
if e != nil || len(listed) != 1 || listed[0].Symbol != bi.Symbol || listed[0].Input != nil || listed[0].Result != nil {
t.Fatal("backtest list must retain the symbol without returning large inputs")
}
if _, e := pool.Exec(ctx, `UPDATE veyra_backtest_run SET result='{}'::jsonb WHERE id=$1`, job.ID); e == nil {
t.Fatal("completed result can be overwritten")
}
+1
View File
@@ -27,6 +27,7 @@ type ResearchInput struct {
Parameters StrategyParameters `json:"parameters"`
}
type BacktestRun struct {
Symbol string `json:"symbol"`
ID string `db:"id" json:"id"`
StrategyVersionID string `db:"strategy_version_id" json:"strategy_version_id"`
Status string `db:"status" json:"status"`
+3
View File
@@ -23,6 +23,9 @@ type AIConclusion struct {
MissingInformation []string `json:"missing_information"`
}
type CandidateAnalysis struct {
Name string `json:"name,omitempty"`
Symbol string `json:"symbol,omitempty"`
Exchange string `json:"exchange,omitempty"`
ID string `db:"id" json:"id"`
CandidateRevisionID string `db:"candidate_revision_id" json:"candidate_revision_id"`
InputVersion int64 `db:"input_version" json:"input_version"`
+7
View File
@@ -21,6 +21,13 @@ const backtestColumns = `id,strategy_version_id,status,input,input_hash,result,f
func scanBacktest(row pgx.Row) (model.BacktestRun, error) {
var v model.BacktestRun
err := row.Scan(&v.ID, &v.StrategyVersionID, &v.Status, &v.Input, &v.InputHash, &v.Result, &v.Failure, &v.LeaseID, &v.CreatedAt, &v.FinishedAt)
if err == nil {
var identity struct {
Symbol string `json:"symbol"`
}
err = json.Unmarshal(v.Input, &identity)
v.Symbol = identity.Symbol
}
return v, mapError(err)
}
func (r *BacktestRepository) Detail(ctx context.Context, id string) (model.BacktestRun, error) {
+2 -2
View File
@@ -183,7 +183,7 @@ func (r *CandidateAnalysisRepository) Complete(ctx context.Context, p model.AIRe
return mapError(tx.Commit(ctx))
}
func (r *CandidateAnalysisRepository) List(ctx context.Context) ([]model.CandidateAnalysis, error) {
rows, err := r.pool.Query(ctx, `SELECT id,candidate_revision_id,input_version,policy_version,status,attempts,primary_model,review_model,primary_version,review_version,analysis,review,message,created_at,updated_at FROM veyra_candidate_analysis ORDER BY updated_at DESC LIMIT 100`)
rows, err := r.pool.Query(ctx, `SELECT a.id,a.candidate_revision_id,a.input_version,a.policy_version,a.status,a.attempts,a.primary_model,a.review_model,a.primary_version,a.review_version,a.analysis,a.review,a.message,a.created_at,a.updated_at,r.snapshot->>'name',r.snapshot->>'symbol',r.snapshot->>'exchange' FROM veyra_candidate_analysis a JOIN veyra_candidate_revision r ON r.id=a.candidate_revision_id ORDER BY a.updated_at DESC LIMIT 100`)
if err != nil {
return nil, mapError(err)
}
@@ -192,7 +192,7 @@ func (r *CandidateAnalysisRepository) List(ctx context.Context) ([]model.Candida
for rows.Next() {
var v model.CandidateAnalysis
var a, b []byte
if err = rows.Scan(&v.ID, &v.CandidateRevisionID, &v.InputVersion, &v.PolicyVersion, &v.Status, &v.Attempts, &v.PrimaryModel, &v.ReviewModel, &v.PrimaryVersion, &v.ReviewVersion, &a, &b, &v.Message, &v.CreatedAt, &v.UpdatedAt); err != nil {
if err = rows.Scan(&v.ID, &v.CandidateRevisionID, &v.InputVersion, &v.PolicyVersion, &v.Status, &v.Attempts, &v.PrimaryModel, &v.ReviewModel, &v.PrimaryVersion, &v.ReviewVersion, &a, &b, &v.Message, &v.CreatedAt, &v.UpdatedAt, &v.Name, &v.Symbol, &v.Exchange); err != nil {
return nil, mapError(err)
}
if len(a) > 0 {