harness loop: self-hosting daemon — Redmine SoR drives its own turns
`harness loop` polls the /issues.json intake on an interval (default
120s, --once for cron-style single scans), runs one bounded turn per
new/updated issue — deduped by issue id + updated_on in an append-only
loop.jsonl — then writes the REPORT back as a Redmine journal note,
transitions status per [redmine.status_map] (In Progress -> Done by
name, resolved via /issue_statuses.json), and refreshes the dedup marker
to the post-writeback updated_on so its own notes never re-trigger it.
Turns are sequential (v0); failed turns are recorded, not retried, so a
down proxy cannot hot-loop the poll. The optional Gitea REPORT commit
([gitea] commit_reports, off) rides the same flow. No slot files, no
doorbell screens, no queue scripts — the bash middle layer is replaced,
not wrapped.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@@ -70,6 +70,10 @@ func (c *RedmineClient) ListTasks(ctx context.Context) ([]task.Task, error) {
|
||||
ID int `json:"id"`
|
||||
Subject string `json:"subject"`
|
||||
Description string `json:"description"`
|
||||
UpdatedOn string `json:"updated_on"`
|
||||
Status struct {
|
||||
Name string `json:"name"`
|
||||
} `json:"status"`
|
||||
CustomFields []struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
@@ -93,11 +97,13 @@ func (c *RedmineClient) ListTasks(ctx context.Context) ([]task.Task, error) {
|
||||
prompt = is.Subject
|
||||
}
|
||||
tasks = append(tasks, task.Task{
|
||||
ID: strconv.Itoa(is.ID),
|
||||
Subject: is.Subject,
|
||||
Prompt: prompt,
|
||||
Class: class,
|
||||
Source: "redmine",
|
||||
ID: strconv.Itoa(is.ID),
|
||||
Subject: is.Subject,
|
||||
Prompt: prompt,
|
||||
Class: class,
|
||||
Source: "redmine",
|
||||
UpdatedOn: is.UpdatedOn,
|
||||
Status: is.Status.Name,
|
||||
})
|
||||
}
|
||||
return tasks, nil
|
||||
|
||||
Reference in New Issue
Block a user