feat: множественные репозитории (Repos) и клонирование в воркере
All checks were successful
CI / test (push) Successful in 46s
CI / build-and-package (amd64, darwin) (push) Successful in 36s
CI / build-and-package (amd64, linux) (push) Successful in 37s
CI / build-and-package (amd64, windows) (push) Successful in 44s
CI / build-and-package (arm64, darwin) (push) Successful in 35s
CI / build-and-package (arm64, linux) (push) Successful in 36s
All checks were successful
CI / test (push) Successful in 46s
CI / build-and-package (amd64, darwin) (push) Successful in 36s
CI / build-and-package (amd64, linux) (push) Successful in 37s
CI / build-and-package (amd64, windows) (push) Successful in 44s
CI / build-and-package (arm64, darwin) (push) Successful in 35s
CI / build-and-package (arm64, linux) (push) Successful in 36s
- Task.Repos []string (XML-колонка repos, обратная совместимость с repo)
- config: блок git {base_url, token}
- аналитик: ответ repos[], шаблон показывает список
- core: propose без repos → возврат в сбор (E1)
- worker вариант A: один dev из общего cwd, prepareRepos клонирует
недостающие репо (git clone), validateRepoName (E3), ErrRepoNotGit (E4)
- ошибки E1-E4 в worker/errors.go
This commit is contained in:
@@ -318,8 +318,17 @@ func (c *Core) runDecide(ctx context.Context, task *storage.Task, force bool) (R
|
||||
return Result{Reply: reply, Action: "drop", TaskID: task.ID, Status: task.Status}, nil
|
||||
|
||||
case "propose":
|
||||
// применяем черновик и переходим в ready
|
||||
// применяем черновик
|
||||
applyDraft(task, decision.Draft)
|
||||
// E1: propose без репозиториев → остаёмся в сборе, просим уточнить.
|
||||
if len(task.EffectiveRepos()) == 0 {
|
||||
task.Status = storage.StatusCollecting
|
||||
if err := c.Store.UpdateTask(ctx, task); err != nil {
|
||||
return Result{}, err
|
||||
}
|
||||
reply := decChatReply(decision, "Укажи, в каком репозитории(ях) вести работу.")
|
||||
return Result{Reply: reply, Action: "send", TaskID: task.ID, Status: task.Status}, nil
|
||||
}
|
||||
task.Status = storage.StatusReady
|
||||
if err := c.Store.UpdateTask(ctx, task); err != nil {
|
||||
return Result{}, err
|
||||
@@ -353,6 +362,10 @@ func applyDraft(task *storage.Task, dec storage.Task) {
|
||||
if dec.Repo != "" {
|
||||
task.Repo = dec.Repo
|
||||
}
|
||||
if len(dec.Repos) > 0 {
|
||||
task.Repos = dec.Repos
|
||||
task.Repo = strings.Join(dec.Repos, ",")
|
||||
}
|
||||
if dec.Why != "" {
|
||||
task.Why = dec.Why
|
||||
}
|
||||
@@ -361,6 +374,14 @@ func applyDraft(task *storage.Task, dec storage.Task) {
|
||||
}
|
||||
}
|
||||
|
||||
// decChatReply возвращает ChatReply из вердикта или переданный дефолт.
|
||||
func decChatReply(dec Decision, fallback string) string {
|
||||
if dec.ChatReply != "" {
|
||||
return dec.ChatReply
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
// buildAskReply формирует ответ с вопросами.
|
||||
func buildAskReply(dec Decision, max int) string {
|
||||
reply := dec.ChatReply
|
||||
@@ -391,8 +412,8 @@ func formatSummary(t storage.Task) string {
|
||||
if t.Title != "" {
|
||||
b.WriteString("**Название:** " + t.Title + "\n")
|
||||
}
|
||||
if t.Repo != "" {
|
||||
b.WriteString("**Репозиторий:** " + t.Repo + "\n")
|
||||
if len(t.EffectiveRepos()) > 0 {
|
||||
b.WriteString("**Репозитории:** " + strings.Join(t.EffectiveRepos(), ", ") + "\n")
|
||||
}
|
||||
if t.Goal != "" {
|
||||
b.WriteString("**Цель:** " + t.Goal + "\n")
|
||||
|
||||
@@ -148,7 +148,7 @@ func TestAbortReturnsDrop(t *testing.T) {
|
||||
|
||||
func TestConsentInReady(t *testing.T) {
|
||||
c, ctx, store := setupCore(t, func(ctx context.Context, history []Message, draft storage.Task, force bool) (Decision, error) {
|
||||
return Decision{Phase: "propose", Draft: storage.Task{Title: "X"}}, nil
|
||||
return Decision{Phase: "propose", Draft: storage.Task{Title: "X", Repos: []string{"repo-x"}}}, nil
|
||||
})
|
||||
id := mkTask(t, store, ctx, "u1")
|
||||
|
||||
@@ -166,7 +166,7 @@ func TestEditInReadyGoesCollecting(t *testing.T) {
|
||||
var calls int
|
||||
c, ctx, store := setupCore(t, func(ctx context.Context, history []Message, draft storage.Task, force bool) (Decision, error) {
|
||||
calls++
|
||||
return Decision{Phase: "propose", Draft: storage.Task{Title: "X"}}, nil
|
||||
return Decision{Phase: "propose", Draft: storage.Task{Title: "X", Repos: []string{"repo-x"}}}, nil
|
||||
})
|
||||
id := mkTask(t, store, ctx, "u1")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user