crewly 1.20.349 → 1.20.351
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/skills/agent/core/complete-task/SKILL.md +6 -5
- package/config/skills/agent/core/complete-task/execute.sh +13 -4
- package/config/skills/agent/core/complete-task/execute.test.sh +7 -0
- package/config/skills/agent/core/report-status/SKILL.md +3 -3
- package/config/skills/agent/core/report-status/execute.sh +9 -5
- package/config/skills/agent/core/trace-read/SKILL.md +14 -0
- package/config/skills/agent/core/trace-read/execute.sh +25 -2
- package/config/skills/orchestrator/complete-task/SKILL.md +1 -1
- package/config/skills/orchestrator/complete-task/execute.sh +3 -2
- package/config/skills/orchestrator/render-verdict/SKILL.md +2 -1
- package/config/skills/orchestrator/render-verdict/execute.sh +8 -4
- package/config/skills/team-leader/verify-output/SKILL.md +8 -3
- package/config/skills/team-leader/verify-output/execute.sh +4 -3
- package/config/skills/team-leader/verify-output/execute.test.sh +2 -0
- package/dist/backend/backend/src/constants.d.ts +30 -5
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +32 -5
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/request/request.controller.d.ts +12 -0
- package/dist/backend/backend/src/controllers/request/request.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/request/request.controller.js +48 -0
- package/dist/backend/backend/src/controllers/request/request.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/request/request.routes.d.ts +1 -0
- package/dist/backend/backend/src/controllers/request/request.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/request/request.routes.js +4 -1
- package/dist/backend/backend/src/controllers/request/request.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +8 -5
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +91 -16
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +3 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/agent-ask-ledger.service.d.ts +6 -0
- package/dist/backend/backend/src/services/messaging/agent-ask-ledger.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/agent-ask-ledger.service.js +9 -0
- package/dist/backend/backend/src/services/messaging/agent-ask-ledger.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.d.ts +74 -5
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.js +187 -21
- package/dist/backend/backend/src/services/task-pool/completion-evidence.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/request-whereabouts.service.d.ts +88 -0
- package/dist/backend/backend/src/services/v3/request-whereabouts.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/request-whereabouts.service.js +193 -0
- package/dist/backend/backend/src/services/v3/request-whereabouts.service.js.map +1 -0
- package/dist/backend/backend/src/types/v2/completion-evidence.types.d.ts +16 -0
- package/dist/backend/backend/src/types/v2/completion-evidence.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/completion-evidence.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts +6 -0
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.js +6 -0
- package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +30 -5
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +32 -5
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/agent-ask-ledger.service.d.ts +6 -0
- package/dist/cli/backend/src/services/messaging/agent-ask-ledger.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/agent-ask-ledger.service.js +9 -0
- package/dist/cli/backend/src/services/messaging/agent-ask-ledger.service.js.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.d.ts +6 -0
- package/dist/cli/backend/src/types/v2/work-item.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.js +6 -0
- package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
- package/frontend/dist/assets/{index-36b1788c.js → index-b1fc60ea.js} +65 -65
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
- package/packages/crewly-agent/src/runtime/tool-registry.test.ts +26 -0
- package/packages/crewly-agent/src/runtime/tool-registry.ts +31 -4
|
@@ -46,12 +46,12 @@ Mark a task as complete with a summary of the work done. If the task has an outp
|
|
|
46
46
|
| `workItemId` | Preferred | ID of the V3 WorkItem to complete. This is the only input that selects the WorkItem |
|
|
47
47
|
| `sessionName` | Yes | Your agent session name |
|
|
48
48
|
| `summary` | Yes | Summary of the work completed |
|
|
49
|
-
| `evidence` | Yes* | Array of evidence entries — see **Evidence contract** below. *
|
|
49
|
+
| `evidence` | Yes* | Array of evidence entries — see **Evidence contract** below. *Required: refused without it (400 `evidence_required`), except a review `verdict` |
|
|
50
50
|
| `absoluteTaskPath` | No | **Legacy (V1).** Still accepted so older callers keep working, but it does NOT identify a WorkItem |
|
|
51
51
|
| `output` | No | Structured output object (required if task has an output schema) |
|
|
52
52
|
| ~~`skipGates`~~ | **Rejected** | **Not supported.** This endpoint runs no quality gates, so there is nothing to skip. Passing it is a hard error. Use the `check-quality-gates` skill for gates. |
|
|
53
53
|
|
|
54
|
-
**Any other field is an error.** The skill accepts only the fields in this table plus `verdict`/`feedback` (reviews) and `taskId`/`artifacts`/`testResults`/`structured` (verification requests). An unknown field (for example `projectPath`, `skipGates`, `force`) stops the call before anything is sent, and the error names the field. Put extra results inside `output`.
|
|
54
|
+
**Any other field is an error.** The skill accepts only the fields in this table plus `verdict`/`feedback`/`checks` (reviews) and `taskId`/`artifacts`/`testResults`/`structured` (verification requests). An unknown field (for example `projectPath`, `skipGates`, `force`) stops the call before anything is sent, and the error names the field. Put extra results inside `output`.
|
|
55
55
|
|
|
56
56
|
On success the skill prints **one JSON line** that always names the `workItemId`, plus the server's reply (`success`, `message`, any `warning`).
|
|
57
57
|
|
|
@@ -83,8 +83,8 @@ items for one session.
|
|
|
83
83
|
|
|
84
84
|
If you could not finish, do **not** report done: send a `blocked` entry (or use
|
|
85
85
|
`report-status --status blocked`). Malformed evidence is rejected with 400
|
|
86
|
-
naming the bad entry. A completion with no evidence is
|
|
87
|
-
|
|
86
|
+
naming the bad entry. A completion with no evidence is refused with 400
|
|
87
|
+
`evidence_required` and nothing is completed (#1312).
|
|
88
88
|
A review verdict (`verdict` set) needs no evidence.
|
|
89
89
|
|
|
90
90
|
## Example
|
|
@@ -154,9 +154,10 @@ JSON confirmation of task completion status. If validation fails:
|
|
|
154
154
|
|
|
155
155
|
When the item you're completing is a review of another agent's work:
|
|
156
156
|
|
|
157
|
-
- **Accept:**
|
|
157
|
+
- **Accept:** open or re-run the worker's evidence (the item lists it numbered; `verify-output` shows it in full) and send `"verdict":"verified"` with `"checks"`: one `{"entry":<index>,"did":"<what you did and saw>","outcome":"pass"}` per entry you checked, `"entry":null` for a direct look at the work. At least one check must name a worker evidence entry when there is any. An accept without checks, or with a `"fail"` check, is refused (400 `review_unchecked` / `review_check_failed`) and nothing is accepted.
|
|
158
158
|
- **Send it back:** add `"verdict":"rejected"` and `"feedback":"<what is wrong>"`. The worker gets a retry that includes your feedback. Feedback is required when you reject.
|
|
159
159
|
|
|
160
160
|
```bash
|
|
161
|
+
bash execute.sh '{"workItemId":"<verify item id>","sessionName":"<you>","summary":"Export is right","verdict":"verified","checks":[{"entry":0,"did":"opened export.csv: 120 rows, header present","outcome":"pass"},{"entry":1,"did":"re-ran npm test: exit 0","outcome":"pass"}]}'
|
|
161
162
|
bash execute.sh '{"workItemId":"<verify item id>","sessionName":"<you>","summary":"Header row missing","verdict":"rejected","feedback":"Add the header row and re-run the export"}'
|
|
162
163
|
```
|
|
@@ -35,7 +35,7 @@ SUMMARY=$(printf '%s' "$INPUT" | jq -r '.summary // empty')
|
|
|
35
35
|
# ignoring a field is the worst disposition: the caller believes it did
|
|
36
36
|
# something, and nothing ever fails. So every field this skill does not use
|
|
37
37
|
# fails loudly, with its name, before any request is sent.
|
|
38
|
-
ALLOWED_FIELDS='["workItemId","absoluteTaskPath","sessionName","summary","output","evidence","verdict","feedback","taskId","artifacts","testResults","structured"]'
|
|
38
|
+
ALLOWED_FIELDS='["workItemId","absoluteTaskPath","sessionName","summary","output","evidence","verdict","feedback","checks","taskId","artifacts","testResults","structured"]'
|
|
39
39
|
SKIP_GATES=$(printf '%s' "$INPUT" | jq -r 'has("skipGates")')
|
|
40
40
|
if [ "$SKIP_GATES" = "true" ]; then
|
|
41
41
|
error_exit "skipGates is not supported by complete-task and never was — it was accepted and silently discarded. POST /task-pool/complete runs no quality gates, so there is nothing here to skip. Quality gates live behind the 'check-quality-gates' skill (POST /quality-gates/check); run or skip them there. Remove skipGates from this call."
|
|
@@ -67,6 +67,13 @@ fi
|
|
|
67
67
|
if [ "$VERDICT" = "rejected" ] && [ -z "$FEEDBACK" ]; then
|
|
68
68
|
error_exit "verdict \"rejected\" needs feedback: say what is wrong so the retry can fix it"
|
|
69
69
|
fi
|
|
70
|
+
# Accepting a review records what you checked, per worker evidence entry
|
|
71
|
+
# (#1314): [{"entry":<index or null>,"did":"<what you did and saw>","outcome":"pass"|"fail"}].
|
|
72
|
+
# The server refuses an accept without it; this only catches a non-array.
|
|
73
|
+
CHECKS_JSON=$(printf '%s' "$INPUT" | jq -c '.checks // empty')
|
|
74
|
+
if [ -n "$CHECKS_JSON" ] && [ "$(printf '%s' "$CHECKS_JSON" | jq -r 'type')" != "array" ]; then
|
|
75
|
+
error_exit "checks must be a JSON array, e.g. [{\"entry\":0,\"did\":\"opened report.md: covers all 3 asks\",\"outcome\":\"pass\"}]"
|
|
76
|
+
fi
|
|
70
77
|
require_param "sessionName" "$SESSION_NAME"
|
|
71
78
|
require_param "summary" "$SUMMARY"
|
|
72
79
|
|
|
@@ -167,6 +174,7 @@ BODY=$(jq -n \
|
|
|
167
174
|
--arg verdict "$VERDICT" \
|
|
168
175
|
--arg feedback "$FEEDBACK" \
|
|
169
176
|
--argjson evidence "${EVIDENCE_JSON:-null}" \
|
|
177
|
+
--argjson checks "${CHECKS_JSON:-null}" \
|
|
170
178
|
'{
|
|
171
179
|
agentId: $agentId,
|
|
172
180
|
result: ({summary: $summary}
|
|
@@ -175,7 +183,8 @@ BODY=$(jq -n \
|
|
|
175
183
|
else {} end)
|
|
176
184
|
+ (if $verdict != "" then {verdict: $verdict} else {} end)
|
|
177
185
|
+ (if $feedback != "" then {feedback: $feedback} else {} end)
|
|
178
|
-
+ (if $evidence != null then {evidence: $evidence} else {} end)
|
|
186
|
+
+ (if $evidence != null then {evidence: $evidence} else {} end)
|
|
187
|
+
+ (if $checks != null then {checks: $checks} else {} end))
|
|
179
188
|
}')
|
|
180
189
|
|
|
181
190
|
COMPLETE_RESPONSE=$(api_call POST "/task-pool/complete/${WORK_ITEM_ID}" "$BODY")
|
|
@@ -191,8 +200,8 @@ if [ -z "$RESULT_LINE" ]; then
|
|
|
191
200
|
'{success: true, workItemId: $id, message: ("WorkItem " + $id + " completion was accepted; the server reply was not JSON."), raw: $raw}')
|
|
192
201
|
fi
|
|
193
202
|
printf '%s\n' "$RESULT_LINE"
|
|
194
|
-
#
|
|
195
|
-
#
|
|
203
|
+
# With CREWLY_EVIDENCE_MODE=warn the server accepts a completion without
|
|
204
|
+
# evidence but says so (#873, #1312). Repeat it on stderr so it is not missed.
|
|
196
205
|
EVIDENCE_WARNING=$(printf '%s' "$COMPLETE_RESPONSE" | jq -r '.warning // empty' 2>/dev/null || true)
|
|
197
206
|
if [ -n "$EVIDENCE_WARNING" ]; then
|
|
198
207
|
jq -n --arg w "$EVIDENCE_WARNING" '{warning: $w}' >&2
|
|
@@ -224,6 +224,13 @@ assert_not_contains "no request sent without feedback" "/task-pool/complete" "$R
|
|
|
224
224
|
run_skill '{"workItemId":"wi-verify","sessionName":"tl-1","summary":"x","verdict":"maybe"}'
|
|
225
225
|
assert_contains "unknown verdict is refused" "verdict must be" "$OUT"
|
|
226
226
|
|
|
227
|
+
run_skill '{"workItemId":"wi-verify","sessionName":"tl-1","summary":"ok","verdict":"verified","checks":[{"entry":0,"did":"opened it","outcome":"pass"}]}'
|
|
228
|
+
CHECKS_BODY="$(printf '%s' "$BODIES" | grep 'agentId' | head -1 || true)"
|
|
229
|
+
assert_contains "checks land in result (#1314)" '"did": "opened it"' "$CHECKS_BODY"
|
|
230
|
+
|
|
231
|
+
run_skill '{"workItemId":"wi-verify","sessionName":"tl-1","summary":"ok","verdict":"verified","checks":"looked at it"}'
|
|
232
|
+
assert_contains "non-array checks are refused" "checks must be a JSON array" "$OUT"
|
|
233
|
+
|
|
227
234
|
run_skill '{"workItemId":"wi-plain","sessionName":"dev-1","summary":"done"}'
|
|
228
235
|
PLAIN_BODY="$(printf '%s' "$BODIES" | grep 'agentId' | head -1 || true)"
|
|
229
236
|
assert_not_contains "no verdict key when none given" '"verdict"' "$PLAIN_BODY"
|
|
@@ -74,9 +74,9 @@ For a bug fix, the failing "before" run belongs in the evidence too: put it in t
|
|
|
74
74
|
|
|
75
75
|
The server rejects (400) a missing artifact, a non-zero exit code, or a
|
|
76
76
|
malformed entry; the skill then prints `{"warning":"… completing the WorkItem
|
|
77
|
-
FAILED …","error":…}` with the reason. Without any evidence, `done` is
|
|
78
|
-
**
|
|
79
|
-
|
|
77
|
+
FAILED …","error":…}` with the reason. Without any evidence, `done` is
|
|
78
|
+
**refused** (400 `evidence_required`) and the WorkItem stays open; the skill
|
|
79
|
+
prints a `next` line with the flags to add. If you could not finish, report `--status blocked` (or `done` with
|
|
80
80
|
`--blocked-step/--blocked-reason`), never `done`.
|
|
81
81
|
|
|
82
82
|
## This skill COMPLETES a WorkItem, not just reports
|
|
@@ -53,7 +53,7 @@ Evidence (status done — #873: "done" needs evidence):
|
|
|
53
53
|
--blocked-reason <why> ... and why. The WorkItem is recorded as BLOCKED, not done.
|
|
54
54
|
--evidence <json> Raw evidence array, e.g. '[{"type":"artifact","path":"/abs/f"}]'
|
|
55
55
|
A non-zero --exit-code or a missing artifact is rejected by the server. Without
|
|
56
|
-
any evidence, done is
|
|
56
|
+
any evidence, done is refused and the WorkItem stays open (#1312).
|
|
57
57
|
--help | -h Show this help
|
|
58
58
|
EOF_USAGE
|
|
59
59
|
}
|
|
@@ -385,8 +385,8 @@ if [ "$STATUS" = "done" ]; then
|
|
|
385
385
|
# `agentId is required` + `summary required in body.result`,
|
|
386
386
|
# forcing every worker into a direct-curl workaround.
|
|
387
387
|
#
|
|
388
|
-
# #873: the evidence block goes in result.evidence. Omitted when empty
|
|
389
|
-
#
|
|
388
|
+
# #873: the evidence block goes in result.evidence. Omitted when empty;
|
|
389
|
+
# the server then refuses a deliverable's completion (#1312).
|
|
390
390
|
COMPLETE_BODY=$(jq -n \
|
|
391
391
|
--arg agentId "$SESSION_NAME" \
|
|
392
392
|
--arg summary "$SUMMARY" \
|
|
@@ -410,8 +410,12 @@ if [ "$STATUS" = "done" ]; then
|
|
|
410
410
|
'{completedWorkItem: $id, resolvedBy: $how} + (if $w != "" then {warning: $w} else {} end)' >&2
|
|
411
411
|
fi
|
|
412
412
|
else
|
|
413
|
-
|
|
414
|
-
|
|
413
|
+
NEXT_STEP=""
|
|
414
|
+
case "$COMPLETE_RESULT" in
|
|
415
|
+
*evidence_required*) NEXT_STEP="Run report-status --status done again with evidence: --artifact <file or https URL> (repeatable) and/or --command '<cmd>' --exit-code N; if you could not finish, --blocked-step '<step>' --blocked-reason '<why>'." ;;
|
|
416
|
+
esac
|
|
417
|
+
jq -n --arg id "$TARGET_WI_ID" --arg err "$COMPLETE_RESULT" --arg next "$NEXT_STEP" \
|
|
418
|
+
'{warning: "status reported, but completing the WorkItem FAILED — it is still open", workItemId: $id, error: $err} + (if $next != "" then {next: $next} else {} end)' >&2
|
|
415
419
|
fi
|
|
416
420
|
fi
|
|
417
421
|
fi
|
|
@@ -27,6 +27,8 @@ triggers:
|
|
|
27
27
|
- how did the run go
|
|
28
28
|
- what happened to my work
|
|
29
29
|
- why was it stuck
|
|
30
|
+
- where is it now
|
|
31
|
+
- who has it
|
|
30
32
|
- stalls
|
|
31
33
|
- retro
|
|
32
34
|
- autonomy
|
|
@@ -87,6 +89,18 @@ You get, in at most `--max-chars` (default 4000):
|
|
|
87
89
|
counted).
|
|
88
90
|
- **Links** — the dashboard page with its Timeline tab, and the API.
|
|
89
91
|
|
|
92
|
+
## Where a request is now
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
bash execute.sh --where TKT-12 # or the request id
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Who holds the owner's request right now, what they are doing (working,
|
|
99
|
+
queued, blocked, reviewing, waiting on another agent, waiting on the owner)
|
|
100
|
+
and for how long. It follows plain-message hand-offs too: if Ella passed it
|
|
101
|
+
to Pia and Pia to Dex, you see all three and that Dex has it. Use this when
|
|
102
|
+
the owner asks "how is X going" or "is it forgotten", before guessing.
|
|
103
|
+
|
|
90
104
|
## Recent runs
|
|
91
105
|
|
|
92
106
|
```bash
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
# bash execute.sh --trace tr-20261003-ab12cd34
|
|
11
11
|
# bash execute.sh --work-item <id> | --ticket CE-7 | --ticket TKT-12 | --request <id> | --experiment EXP-3
|
|
12
12
|
# bash execute.sh --since 2026-10-01T00:00:00Z [--limit 10] # recent runs, one line each
|
|
13
|
+
# bash execute.sh --where TKT-12 | --where <request id> # who holds it NOW, doing what, since when
|
|
13
14
|
# Options: [--max-chars 4000] [--stall-minutes 30] [--json]
|
|
14
15
|
# =============================================================================
|
|
15
16
|
set -euo pipefail
|
|
@@ -25,6 +26,7 @@ Usage:
|
|
|
25
26
|
bash execute.sh --request ID The run of a Request
|
|
26
27
|
bash execute.sh --experiment EXP-3 The run of an experiment card
|
|
27
28
|
bash execute.sh --since ISO [--limit 10] Runs active since then, one line each, newest first (at most 100)
|
|
29
|
+
bash execute.sh --where TKT-12 | --where ID Where an owner request is NOW: who holds it, doing what, for how long
|
|
28
30
|
Options:
|
|
29
31
|
--max-chars N Size bound of the output (default 4000, 600..16000)
|
|
30
32
|
--stall-minutes N A gap with no progress longer than this is a stall (default 30)
|
|
@@ -32,10 +34,11 @@ Options:
|
|
|
32
34
|
EOF_USAGE
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
TRACE=""; WORK_ITEM=""; TICKET=""; REQUEST=""; EXPERIMENT=""; SINCE=""; LIMIT="10"; MAX_CHARS="4000"; STALL=""; JSON_OUT="0"
|
|
37
|
+
WHERE=""; TRACE=""; WORK_ITEM=""; TICKET=""; REQUEST=""; EXPERIMENT=""; SINCE=""; LIMIT="10"; MAX_CHARS="4000"; STALL=""; JSON_OUT="0"
|
|
36
38
|
|
|
37
39
|
while [[ $# -gt 0 ]]; do
|
|
38
40
|
case "$1" in
|
|
41
|
+
--where) [ $# -ge 2 ] || error_exit "--where requires a request id or TKT-n"; WHERE="$2"; shift 2 ;;
|
|
39
42
|
--trace|-t) [ $# -ge 2 ] || error_exit "--trace requires a value"; TRACE="$2"; shift 2 ;;
|
|
40
43
|
--work-item|-w) [ $# -ge 2 ] || error_exit "--work-item requires a value"; WORK_ITEM="$2"; shift 2 ;;
|
|
41
44
|
--ticket) [ $# -ge 2 ] || error_exit "--ticket requires a value"; TICKET="$2"; shift 2 ;;
|
|
@@ -65,9 +68,29 @@ enc() { jq -rn --arg v "$1" '$v|@uri'; }
|
|
|
65
68
|
STALL_QS=""
|
|
66
69
|
[ -n "$STALL" ] && STALL_QS="&stallMinutes=$(enc "$STALL")"
|
|
67
70
|
|
|
71
|
+
# --- Where a request is now (backed by GET /api/requests/:id/whereabouts) ---
|
|
72
|
+
if [ -n "$WHERE" ]; then
|
|
73
|
+
if ! RESP=$(api_call_full GET "/requests/$(enc "$WHERE")/whereabouts"); then
|
|
74
|
+
error_exit "No owner request $WHERE (pass a request id or TKT-n)"
|
|
75
|
+
fi
|
|
76
|
+
if [ "$JSON_OUT" = "1" ]; then
|
|
77
|
+
printf '%s' "$RESP" | jq -c '{success: true} + .data'
|
|
78
|
+
exit 0
|
|
79
|
+
fi
|
|
80
|
+
printf '%s' "$RESP" | jq -r --argjson max "$MAX_CHARS" '
|
|
81
|
+
def dur: (. / 60000 | floor) as $m
|
|
82
|
+
| if $m < 60 then "\($m)m" elif $m < 2880 then "\($m / 60 | floor)h \($m % 60)m" else "\($m / 1440 | floor)d \(($m % 1440) / 60 | floor)h" end;
|
|
83
|
+
.data as $d
|
|
84
|
+
| ([ "\(if $d.ticketNumber then "TKT-\($d.ticketNumber) · " else "" end)\($d.title[0:100]) · \($d.status)", $d.summary ]
|
|
85
|
+
+ [ $d.holders[] | "- \(.session): \(.state | gsub("_"; " ")) for \(.forMs | dur) (since \(.since[0:16] | sub("T"; " ")))\(if .workItemId then " · \(.workItemId)" else "" end)\(if .from then " · from \(.from)" else "" end)\(if .blockedReason then " · blocked: \(.blockedReason[0:120])" else "" end)\(if .what then " · \(.what[0:100])" else "" end)" ]
|
|
86
|
+
| join("\n")) as $text
|
|
87
|
+
| if ($text | length) > $max then $text[0:($max - 1)] + "…" else $text end'
|
|
88
|
+
exit 0
|
|
89
|
+
fi
|
|
90
|
+
|
|
68
91
|
# --- Recent runs -------------------------------------------------------------
|
|
69
92
|
if [ -z "$TRACE$WORK_ITEM$TICKET$REQUEST$EXPERIMENT" ]; then
|
|
70
|
-
[ -n "$SINCE" ] || { print_usage >&2; error_exit "Pass one of --trace, --work-item, --ticket, --request, --experiment or --since"; }
|
|
93
|
+
[ -n "$SINCE" ] || { print_usage >&2; error_exit "Pass one of --where, --trace, --work-item, --ticket, --request, --experiment or --since"; }
|
|
71
94
|
if ! RESP=$(api_call_full GET "/traces?since=$(enc "$SINCE")&limit=$(enc "$LIMIT")${STALL_QS}"); then
|
|
72
95
|
error_exit "Could not list traces since $SINCE"
|
|
73
96
|
fi
|
|
@@ -38,7 +38,7 @@ bash config/skills/orchestrator/complete-task/execute.sh '{"workItemId":"wi-123"
|
|
|
38
38
|
|-----------|----------|-------------|
|
|
39
39
|
| `workItemId` (alias `taskId`) | Yes | The WorkItem to complete |
|
|
40
40
|
| `summary` (alias `result`) | Yes | What was produced |
|
|
41
|
-
| `evidence` | Yes* | Evidence array (#873): `{"type":"artifact","path":…}` (must exist, or an https URL), `{"type":"command","command":…,"exitCode":0,"outputTail":…}`, or `{"type":"blocked","step":…,"reason":…}` (records the item as blocked, not done). *
|
|
41
|
+
| `evidence` | Yes* | Evidence array (#873): `{"type":"artifact","path":…}` (must exist, or an https URL), `{"type":"command","command":…,"exitCode":0,"outputTail":…}`, or `{"type":"blocked","step":…,"reason":…}` (records the item as blocked, not done). *Required for delegate/project_task/review items (400 `evidence_required` without it); bookkeeping types (triage, replans, retros) may omit it |
|
|
42
42
|
| `output` | No | Structured output stored on the WorkItem before completion |
|
|
43
43
|
| `agentId` / `sessionName` | No | Who completed it (defaults to `crewly-orc`) |
|
|
44
44
|
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
#
|
|
14
14
|
# `evidence` (#873) is sent as result.evidence. The server checks it: missing
|
|
15
15
|
# artifacts and non-zero exit codes are refused, a `blocked` entry records the
|
|
16
|
-
# item as blocked instead of done, and no evidence at all is
|
|
17
|
-
#
|
|
16
|
+
# item as blocked instead of done, and no evidence at all is refused for a
|
|
17
|
+
# deliverable (delegate, project_task, review without a verdict). Bookkeeping
|
|
18
|
+
# types (triage, replans, retros) complete without it (#1312).
|
|
18
19
|
#
|
|
19
20
|
# Backwards-compat: a `taskId` field is accepted as alias for `workItemId`.
|
|
20
21
|
|
|
@@ -45,7 +45,7 @@ orchestrator) and the backend recognizes the caller correctly.
|
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
47
|
CREWLY_SESSION_NAME=crewly-orc bash config/skills/orchestrator/render-verdict/execute.sh \
|
|
48
|
-
'{"workItemId":"abc-123","verdict":"verified","comment":"Meets the acceptance criteria"}'
|
|
48
|
+
'{"workItemId":"abc-123","verdict":"verified","comment":"Meets the acceptance criteria","checks":[{"entry":0,"did":"opened report.md: covers the 3 asks","outcome":"pass"}]}'
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
## Parameters
|
|
@@ -53,6 +53,7 @@ CREWLY_SESSION_NAME=crewly-orc bash config/skills/orchestrator/render-verdict/ex
|
|
|
53
53
|
- `workItemId` (required, alias `taskId`) — the `done_by_worker` WorkItem to verdict.
|
|
54
54
|
- `verdict` (required) — `"verified"` or `"rejected"`.
|
|
55
55
|
- `comment` (optional) — reviewer's note; required in practice for a rejection so the worker knows what to fix.
|
|
56
|
+
- `checks` (required for `verified`, #1314) — what you checked: `[{"entry":<index in the item's output.evidence, or null for a direct look>,"did":"<what you did and saw>","outcome":"pass"|"fail"}]`. At least one must name an evidence entry when the worker sent any. Without it (or with a `fail`) the server returns 400 `review_unchecked` / `review_check_failed` and nothing is verified.
|
|
56
57
|
|
|
57
58
|
## Output
|
|
58
59
|
|
|
@@ -38,10 +38,14 @@ if [ "$VERDICT" != "verified" ] && [ "$VERDICT" != "rejected" ]; then
|
|
|
38
38
|
error_exit "verdict must be \"verified\" or \"rejected\" (got: \"${VERDICT}\")"
|
|
39
39
|
fi
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
# An accept records what you checked (#1314): the server refuses
|
|
42
|
+
# "verified" without checks.
|
|
43
|
+
CHECKS=$(printf '%s' "$INPUT" | jq -c '.checks // empty')
|
|
44
|
+
if [ -n "$CHECKS" ] && [ "$(printf '%s' "$CHECKS" | jq -r 'type')" != "array" ]; then
|
|
45
|
+
error_exit "checks must be a JSON array, e.g. [{\"entry\":0,\"did\":\"opened report.md: covers the 3 asks\",\"outcome\":\"pass\"}]"
|
|
45
46
|
fi
|
|
46
47
|
|
|
48
|
+
BODY=$(jq -n --arg verdict "$VERDICT" --arg comment "$COMMENT" --argjson checks "${CHECKS:-null}" \
|
|
49
|
+
'{verdict: $verdict} + (if $comment != "" then {comment: $comment} else {} end) + (if $checks != null then {checks: $checks} else {} end)')
|
|
50
|
+
|
|
47
51
|
api_call POST "/task-pool/items/${WORK_ITEM_ID}/verdict" "$BODY"
|
|
@@ -40,10 +40,13 @@ WorkItem: artifacts that exist, commands with exit codes, blocked steps) before
|
|
|
40
40
|
running any check, and returns it as the first field of the verdict.
|
|
41
41
|
|
|
42
42
|
- `evidenceWarning` is set when the item was marked done **without evidence**
|
|
43
|
-
(
|
|
43
|
+
(possible only with `CREWLY_EVIDENCE_MODE=warn` or before #1312) — do not verify it
|
|
44
44
|
on its summary alone: check the work directly or send it back asking for
|
|
45
45
|
evidence. It is also set when the worker reported `blocked` steps.
|
|
46
46
|
- The warning, when present, leads `feedback`.
|
|
47
|
+
- Each evidence entry is listed with its index. When you accept, record what
|
|
48
|
+
you did to each one you checked (#1314): open the artifact, re-run the
|
|
49
|
+
command, look at the page. An accept without that record is refused.
|
|
47
50
|
|
|
48
51
|
## When to Use
|
|
49
52
|
|
|
@@ -162,8 +165,10 @@ requiresReview: true → TL must manually evaluate these steps
|
|
|
162
165
|
### Accept finished work; never cancel it
|
|
163
166
|
|
|
164
167
|
When the work is done and checks pass, ACCEPT it: complete the item (for a
|
|
165
|
-
"Verify: ..." item, `complete-task` with `"verdict":"verified"` and
|
|
166
|
-
evidence
|
|
168
|
+
"Verify: ..." item, `complete-task` with `"verdict":"verified"` and
|
|
169
|
+
`"checks":[{"entry":<evidence index, or null for a direct look>,"did":"<what you did and saw>","outcome":"pass"}]`,
|
|
170
|
+
at least one naming a worker evidence entry when there is any). A failed
|
|
171
|
+
check cannot be accepted: send it back with `"verdict":"rejected"`. Do not cancel a WorkItem that was done or verified, even with a
|
|
167
172
|
"verified" note: a cancel is for work that should not happen, and a project
|
|
168
173
|
ticket whose WorkItem is cancelled can go back to the queue so the same work
|
|
169
174
|
is picked up twice. Cancel only work that is NOT done.
|
|
@@ -39,8 +39,8 @@ WI_OUTPUT_RAW=$(echo "$WI_DATA" | jq -c '.data.output // empty' 2>/dev/null || t
|
|
|
39
39
|
# Evidence first (#873). The worker's completion carries an evidence block
|
|
40
40
|
# (artifacts that exist, commands with exit codes, or blocked steps), stored
|
|
41
41
|
# at output.evidence. Read it before anything else, and flag an item that was
|
|
42
|
-
# marked done WITHOUT evidence —
|
|
43
|
-
#
|
|
42
|
+
# marked done WITHOUT evidence — possible only with CREWLY_EVIDENCE_MODE=warn
|
|
43
|
+
# or on an item completed before #1312 — so it is not verified on its summary alone.
|
|
44
44
|
WI_FOUND=$(echo "$WI_DATA" | jq -r 'if (.data // null) != null then "yes" else "no" end' 2>/dev/null || echo "no")
|
|
45
45
|
WI_EVIDENCE=$(echo "$WI_DATA" | jq -c 'if (.data.output.evidence | type) == "array" then .data.output.evidence else [] end' 2>/dev/null || echo '[]')
|
|
46
46
|
EVIDENCE_WARNING=""
|
|
@@ -359,7 +359,8 @@ jq -n \
|
|
|
359
359
|
--arg workerId "$WORKER_ID" \
|
|
360
360
|
--arg templateId "$TEMPLATE_ID" \
|
|
361
361
|
'{
|
|
362
|
-
evidence: $evidence,
|
|
362
|
+
evidence: ($evidence | to_entries | map(.value + {index: .key})),
|
|
363
|
+
acceptWith: "complete-task with \"verdict\":\"verified\" and \"checks\":[{\"entry\":<evidence index, or null for a direct look>,\"did\":\"<what you did and saw>\",\"outcome\":\"pass\"}] (#1314)",
|
|
363
364
|
evidenceWarning: (if $evidenceWarning != "" then $evidenceWarning else null end),
|
|
364
365
|
passed: ($passed == "true"),
|
|
365
366
|
score: ($score | tonumber),
|
|
@@ -126,6 +126,8 @@ echo "verify-output: evidence first (#873)"
|
|
|
126
126
|
|
|
127
127
|
assert_json_field "evidence is the first key of the verdict" \
|
|
128
128
|
'{"workItemId":"wi-ev"}' 'keys_unsorted[0]' 'evidence'
|
|
129
|
+
assert_json_field "each evidence entry carries its index for the checks (#1314)" \
|
|
130
|
+
'{"workItemId":"wi-ev"}' '.evidence[1].index' '1'
|
|
129
131
|
assert_json_field "evidence block is surfaced from output.evidence" \
|
|
130
132
|
'{"workItemId":"wi-ev"}' '[.evidence[].type] | join(",")' 'artifact,command'
|
|
131
133
|
assert_json_field "no evidence warning when evidence is present" \
|
|
@@ -1779,12 +1779,20 @@ export declare const COMPLETION_EVIDENCE_CONSTANTS: {
|
|
|
1779
1779
|
/** The two rollout modes for a completion that carries no evidence. */
|
|
1780
1780
|
readonly MODES: readonly string[];
|
|
1781
1781
|
/**
|
|
1782
|
-
* Default mode for a completion with no evidence. `
|
|
1783
|
-
*
|
|
1784
|
-
*
|
|
1785
|
-
*
|
|
1782
|
+
* Default mode for a completion with no evidence. `enforce` (default since
|
|
1783
|
+
* #1312): 400 `evidence_required`. `warn` (the escape hatch, set with
|
|
1784
|
+
* {@link ENV_MODE}): accepted, logged, and the response carries a `warning`.
|
|
1785
|
+
* Malformed evidence, missing artifacts, failing commands and `blocked`
|
|
1786
|
+
* entries are handled the same in both modes.
|
|
1786
1787
|
*/
|
|
1787
1788
|
readonly EVIDENCE_ENFORCEMENT_MODE: "warn" | "enforce";
|
|
1789
|
+
/**
|
|
1790
|
+
* WorkItem types whose completion must carry evidence: a worker's
|
|
1791
|
+
* deliverable. Every other type is harness bookkeeping (triage, replans,
|
|
1792
|
+
* retros, reconciles, notifications) and may complete without it. An item
|
|
1793
|
+
* with no known type is treated as a deliverable.
|
|
1794
|
+
*/
|
|
1795
|
+
readonly REQUIRED_FOR_TYPES: readonly string[];
|
|
1788
1796
|
/** Env var that overrides {@link EVIDENCE_ENFORCEMENT_MODE} (`warn` | `enforce`). */
|
|
1789
1797
|
readonly ENV_MODE: "CREWLY_EVIDENCE_MODE";
|
|
1790
1798
|
/** Most evidence entries accepted on one completion. */
|
|
@@ -1800,8 +1808,25 @@ export declare const COMPLETION_EVIDENCE_CONSTANTS: {
|
|
|
1800
1808
|
readonly MISSING: "evidence_required";
|
|
1801
1809
|
readonly ARTIFACT_NOT_FOUND: "evidence_artifact_not_found";
|
|
1802
1810
|
readonly ARTIFACT_UNRESOLVABLE: "evidence_artifact_relative_path";
|
|
1811
|
+
readonly ARTIFACT_EMPTY: "evidence_artifact_empty";
|
|
1812
|
+
readonly ARTIFACT_STALE: "evidence_artifact_stale";
|
|
1803
1813
|
readonly COMMAND_FAILED: "evidence_command_failed";
|
|
1804
|
-
|
|
1814
|
+
readonly REVIEW_UNCHECKED: "review_unchecked";
|
|
1815
|
+
readonly REVIEW_CHECKS_MALFORMED: "review_checks_malformed";
|
|
1816
|
+
readonly REVIEW_CHECK_FAILED: "review_check_failed";
|
|
1817
|
+
};
|
|
1818
|
+
/** Worker evidence entries listed, numbered, in a review item's description (#1314). */
|
|
1819
|
+
readonly REVIEW_LISTED_ENTRIES: 10;
|
|
1820
|
+
/** Outcomes a reviewer records for one check (#1314). */
|
|
1821
|
+
readonly CHECK_OUTCOMES: readonly string[];
|
|
1822
|
+
/** The shape of a reviewer's check record, quoted in every refusal (#1314). */
|
|
1823
|
+
readonly CHECKS_HINT: string;
|
|
1824
|
+
/**
|
|
1825
|
+
* A local file artifact last modified more than this before its WorkItem
|
|
1826
|
+
* was created is stale: it was not made for this task (#1313). The slack
|
|
1827
|
+
* covers clock skew and a file saved just before the item was filed.
|
|
1828
|
+
*/
|
|
1829
|
+
readonly STALE_GRACE_MS: number;
|
|
1805
1830
|
/** The shape a worker must send, quoted in every rejection and warning. */
|
|
1806
1831
|
readonly SHAPE_HINT: string;
|
|
1807
1832
|
};
|