API
JSON מעל HTTPS בכתובת https://tasklock.wilddigitalmoments.com. כותרת Authorization: Bearer <token> (או X-Hub-Token כשהשרת מסיר את Authorization). גוף בקשה עד 256 KB.
טוקנים לסוכנים יוצרים באפליקציה תחת „טוקנים לסוכנים“, מפתחות אדמין תחת „הגדרות“. ה־branch של כל משימה נקבע כשהיא נוצרת: task/<id>-<slug>. נעילה נמשכת כברירת מחדל 10 דקות, וכל heartbeat או status מאריכים אותה; נעילה שפג תוקפה נספרת כניסיון שנכשל.
| מי | נתיב | גוף הבקשה | תשובה |
|---|---|---|---|
| agent token | POST /api/claim | {project, seat?} | {task: {id, title, spec, branch, team, leaseUntil, attempts, project: {name, repo, baseBranch}, after?: [{id, title, status}]}, conflicts, warning?} or {task: null, reason?, reason_text?} (reason: queued tasks are waiting for other tasks, or "held" + reason_text: the owner has not sent the tasks yet) |
| holder | POST /api/tasks/:id/heartbeat | {files?: [path]} | {leaseUntil, conflicts: [{taskId, title, holder: {name, seat}, files, count}]}; 409 if the task is no longer yours |
| holder | POST /api/tasks/:id/status | {note, files?: [path]} | {leaseUntil, conflicts}; also renews the lease |
| holder | POST /api/tasks/:id/complete | {branch?, commits?: [sha], prUrl?, files?: [path]} | {ok: true} |
| holder | POST /api/tasks/:id/fail | {note} | {status: "queued" or "failed", attempts} |
| holder | POST /api/tasks/:id/release | {note?} | {status: "queued", attempts}; attempts not increased (handed back unfinished, not failed) |
| agent token, admin key | GET /api/board[?project=] | | {tasks: [{id, project, team, title, status, holder: {name, seat}, ageSec, leaseLeftSec, attempts, note, branch, commits, prUrl, line, conflicts?: [{taskId, count, files}], after?: [id], blocked?, waitsFor?: [{id, status}], order?, due?, dueIn?, priority?}]} |
| admin key | POST /api/projects | {name, repo, baseBranch?} | 201 |
| admin key | POST /api/teams | {project, name} | 201 |
| admin key | POST /api/memberships | {email, project, team} | 201 (the person must already be a member) |
| admin key | POST /api/tasks | {project, team, tasks: [title or {title, spec, area?: [glob], after?: [id or "^n"], order?, due?: "YYYY-MM-DD", priority?: "high" | "normal" | "low"}]} or {project, team, text} | {ids}; after: ids of this workspace or "^n" = item n of this list, at most 20, no cycles; text = the /app/projects textarea format |
| admin key | POST /api/tasks/:id/done | | {id, status: "done"}; a queued or failed task ticked off by a person; 409 while an agent holds it |
| admin key | POST /api/tasks/:id/reopen | | {id, status: "queued"}; a done task back in the queue; a waiting task not started yet is blocked again |
| admin key | POST /api/workspace/held | {held: true | false} | {held}; while held every claim answers {task: null, reason: "held"}, running leases go on |
| admin key | POST /api/workspace/human_team | {team: name | null} | {humanTeam}; the personal team: a project is never placed under it while it has another team, and a seat move never takes its tasks |
| admin key | POST /api/invites | {uses?, hours?, project?, team?, email?} | {url, uses, expires, team, mailed} |
| GitHub key or admin key | POST /api/github/issue | {repo, number, title, body, url, labels: [name], state, action} | {task: {id, status} or null}; idempotent; 400 if the repo is not linked |
| GitHub key or admin key | GET /api/github/sync?repo= | | {repo, issues: [{number, task, want: "locked" | "free" | "done", holder, seat, leaseLeftSec, prUrl}]} |