API

JSON מעל HTTPS בכתובת https://tasklock.wilddigitalmoments.com. כותרת Authorization: Bearer <token> (או X-Hub-Token כשהשרת מסיר את Authorization). גוף בקשה עד 256 KB.

טוקנים לסוכנים יוצרים באפליקציה תחת „טוקנים לסוכנים“, מפתחות אדמין תחת „הגדרות“. ה־branch של כל משימה נקבע כשהיא נוצרת: task/<id>-<slug>. נעילה נמשכת כברירת מחדל 10 דקות, וכל heartbeat או status מאריכים אותה; נעילה שפג תוקפה נספרת כניסיון שנכשל.

מינתיבגוף הבקשהתשובה
agent tokenPOST /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)
holderPOST /api/tasks/:id/heartbeat{files?: [path]}{leaseUntil, conflicts: [{taskId, title, holder: {name, seat}, files, count}]}; 409 if the task is no longer yours
holderPOST /api/tasks/:id/status{note, files?: [path]}{leaseUntil, conflicts}; also renews the lease
holderPOST /api/tasks/:id/complete{branch?, commits?: [sha], prUrl?, files?: [path]}{ok: true}
holderPOST /api/tasks/:id/fail{note}{status: "queued" or "failed", attempts}
holderPOST /api/tasks/:id/release{note?}{status: "queued", attempts}; attempts not increased (handed back unfinished, not failed)
agent token, admin keyGET /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 keyPOST /api/projects{name, repo, baseBranch?}201
admin keyPOST /api/teams{project, name}201
admin keyPOST /api/memberships{email, project, team}201 (the person must already be a member)
admin keyPOST /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 keyPOST /api/tasks/:id/done{id, status: "done"}; a queued or failed task ticked off by a person; 409 while an agent holds it
admin keyPOST /api/tasks/:id/reopen{id, status: "queued"}; a done task back in the queue; a waiting task not started yet is blocked again
admin keyPOST /api/workspace/held{held: true | false}{held}; while held every claim answers {task: null, reason: "held"}, running leases go on
admin keyPOST /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 keyPOST /api/invites{uses?, hours?, project?, team?, email?}{url, uses, expires, team, mailed}
GitHub key or admin keyPOST /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 keyGET /api/github/sync?repo={repo, issues: [{number, task, want: "locked" | "free" | "done", holder, seat, leaseLeftSec, prUrl}]}