crewly 1.20.419 → 1.20.421

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.
Files changed (49) hide show
  1. package/config/skills/agent/core/project-tickets/SKILL.md +21 -0
  2. package/config/skills/agent/core/project-tickets/execute.sh +15 -5
  3. package/config/skills/agent/core/record-learning/SKILL.md +12 -1
  4. package/config/skills/agent/core/record-learning/execute.sh +24 -2
  5. package/config/skills/team-leader/decide-correction/SKILL.md +65 -0
  6. package/config/skills/team-leader/decide-correction/execute.sh +63 -0
  7. package/config/skills/team-leader/handle-failure/SKILL.md +2 -0
  8. package/config/skills/team-leader/handle-failure/execute.sh +18 -0
  9. package/dist/backend/backend/src/constants.d.ts +35 -0
  10. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  11. package/dist/backend/backend/src/constants.js +36 -0
  12. package/dist/backend/backend/src/constants.js.map +1 -1
  13. package/dist/backend/backend/src/controllers/memory/memory.controller.d.ts +42 -2
  14. package/dist/backend/backend/src/controllers/memory/memory.controller.d.ts.map +1 -1
  15. package/dist/backend/backend/src/controllers/memory/memory.controller.js +111 -4
  16. package/dist/backend/backend/src/controllers/memory/memory.controller.js.map +1 -1
  17. package/dist/backend/backend/src/controllers/memory/memory.routes.d.ts +3 -0
  18. package/dist/backend/backend/src/controllers/memory/memory.routes.d.ts.map +1 -1
  19. package/dist/backend/backend/src/controllers/memory/memory.routes.js +7 -1
  20. package/dist/backend/backend/src/controllers/memory/memory.routes.js.map +1 -1
  21. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts +8 -0
  22. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts.map +1 -1
  23. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js +28 -0
  24. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js.map +1 -1
  25. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.d.ts +1 -0
  26. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.d.ts.map +1 -1
  27. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.js +4 -1
  28. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.js.map +1 -1
  29. package/dist/backend/backend/src/index.d.ts.map +1 -1
  30. package/dist/backend/backend/src/index.js +25 -0
  31. package/dist/backend/backend/src/index.js.map +1 -1
  32. package/dist/backend/backend/src/services/memory/correction-ladder.service.d.ts +225 -0
  33. package/dist/backend/backend/src/services/memory/correction-ladder.service.d.ts.map +1 -0
  34. package/dist/backend/backend/src/services/memory/correction-ladder.service.js +335 -0
  35. package/dist/backend/backend/src/services/memory/correction-ladder.service.js.map +1 -0
  36. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-retro.d.ts +99 -1
  37. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-retro.d.ts.map +1 -1
  38. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-retro.js +188 -16
  39. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-retro.js.map +1 -1
  40. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts +53 -4
  41. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts.map +1 -1
  42. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js +226 -27
  43. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js.map +1 -1
  44. package/dist/backend/build-info.json +2 -2
  45. package/dist/cli/backend/src/constants.d.ts +35 -0
  46. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  47. package/dist/cli/backend/src/constants.js +36 -0
  48. package/dist/cli/backend/src/constants.js.map +1 -1
  49. package/package.json +1 -1
@@ -295,6 +295,27 @@ become backlog tickets on the Crewly project, deduplicated and at most 3 a
295
295
  day, and the owner approves them with one card. Never file harness gaps as
296
296
  tickets yourself.
297
297
 
298
+ ### Weekly cross-team retro (orchestrator)
299
+
300
+ Once a week (Monday 09:00, or the first tick after) the orchestrator gets one
301
+ `autopilot_retro` WorkItem titled `Weekly autopilot retro: <week>` when at
302
+ least one lead filed a daily retro that ISO week. The brief lists every
303
+ project's week numbers, its daily retro pages and the harness gaps filed. Read
304
+ the pages, name what repeated across teams and what only Crewly can fix, then
305
+ file it:
306
+
307
+ ```bash
308
+ bash execute.sh retro --week 2026-W44 \
309
+ --summary "Three teams stalled on owner copy approvals; CE and Flopost both lost a day to a stopped member shown as busy." \
310
+ --problem "harness_gap|Triage brief shows stopped members as busy|Seen in CE 10-27 and Flopost 10-29 retros" \
311
+ --problem "owner_dependency|Copy approvals waited >3h in 4 of 7 days"
312
+ ```
313
+
314
+ Same problem classes and limits as the daily retro. Crewly writes the page to
315
+ the global wiki (`llm-curated/autopilot-retros/weekly/<week>.md`) and files the
316
+ harness gaps on the Crewly project with one owner card. Only the owner or the
317
+ orchestrator may file it.
318
+
298
319
  ### What to look for
299
320
 
300
321
  Read yesterday's run with `trace-read` first; each problem names the stage
@@ -31,6 +31,7 @@
31
31
  # bash execute.sh stats --project P [--days 14] [--label feed] (owner / orc / lead)
32
32
  # bash execute.sh runs --project P [--days 7] [--label feed] (owner / orc / lead)
33
33
  # bash execute.sh retro --project P --day YYYY-MM-DD --summary "…" [--problem "class|title|detail|evidence" …]
34
+ # bash execute.sh retro --week YYYY-Www --summary "…" [--problem … …] (orchestrator: weekly cross-team retro)
34
35
  # bash execute.sh self-review --project P --gap "…" [--moved "…"] --next-bet "…"
35
36
  # bash execute.sh '{"action":"create","project":"P","title":"…"}'
36
37
  #
@@ -100,6 +101,8 @@ Usage:
100
101
  Team lead: file the daily autopilot retro.
101
102
  class = agent_judgment | missing_skill |
102
103
  harness_gap | owner_dependency
104
+ bash execute.sh retro --week YYYY-Www --summary "…" [--problem … …]
105
+ Orchestrator: file the weekly cross-team retro.
103
106
  bash execute.sh self-review --project P --gap "…" [--moved "…"] --next-bet "…"
104
107
  Team lead: file the autopilot self-review (gap to
105
108
  the target, what moved it, the next bet)
@@ -114,7 +117,7 @@ STATUS=""; SOURCE=""; REQUEST_ID=""; NOTE=""; OWNER_REVIEW=""; ASSIGNEE=""; STAR
114
117
  ACCEPTANCE_JSON="null"
115
118
  HAS_DESCRIPTION=0
116
119
  QUESTION=""; CLEAR=""; OPTIONS_JSON="[]"; DEFAULT_OPT=""; DEADLINE=""; SENSITIVE=""; AP_ENABLED=""; AP_DRIVER=""; AP_BUDGET=""; AP_MAX=""
117
- AP_RETRO=""; AP_REPLANS=""; AP_REPLAN_TTL=""; DAYS=""; LABEL=""; DAY=""; SUMMARY=""; PROBLEMS_JSON="[]"
120
+ AP_RETRO=""; AP_REPLANS=""; AP_REPLAN_TTL=""; DAYS=""; LABEL=""; DAY=""; WEEK=""; SUMMARY=""; PROBLEMS_JSON="[]"
118
121
  DEFER_UNTIL=""; AP_SKIP=""; HOLD=""; HAS_HOLD=0
119
122
  METRIC=""; AP_SPEED=""; GAP=""; MOVED=""; NEXT_BET=""
120
123
 
@@ -211,6 +214,7 @@ while [[ $# -gt 0 ]]; do
211
214
  --days) [ $# -ge 2 ] || error_exit "--days requires a value"; DAYS="$2"; shift 2 ;;
212
215
  --label) [ $# -ge 2 ] || error_exit "--label requires a value"; LABEL="$2"; shift 2 ;;
213
216
  --day) [ $# -ge 2 ] || error_exit "--day requires a value"; DAY="$2"; shift 2 ;;
217
+ --week) [ $# -ge 2 ] || error_exit "--week requires YYYY-Www"; WEEK="$2"; shift 2 ;;
214
218
  --summary) [ $# -ge 2 ] || error_exit "--summary requires a value"; SUMMARY="$2"; shift 2 ;;
215
219
  --problem) [ $# -ge 2 ] || error_exit "--problem requires \"class|title|detail|evidence\""
216
220
  PROBLEMS_JSON=$(jq -c --arg p "$2" '. + [($p | split("|")) as $f | {class: ($f[0] // "" | gsub("^\\s+|\\s+$"; "")), title: ($f[1] // "")} + (if ($f[2] // "") != "" then {detail: $f[2]} else {} end) + (if ($f[3:] | join("|")) != "" then {evidence: ($f[3:] | join("|"))} else {} end)]' <<<"$PROBLEMS_JSON"); shift 2 ;;
@@ -369,11 +373,17 @@ case "$ACTION" in
369
373
  fi
370
374
  ;;
371
375
  retro)
372
- require_param "project" "$PROJECT"
373
- require_param "day (--day YYYY-MM-DD)" "$DAY"
374
376
  require_param "summary (--summary)" "$SUMMARY"
375
- BODY=$(jq -n --arg d "$DAY" --arg s "$SUMMARY" --argjson p "$PROBLEMS_JSON" '{day: $d, summary: $s, problems: $p}')
376
- api_call POST "/project-ticket-autopilot/$(enc "$PROJECT")/retro" "$BODY" | jq '{success, retro: .data, error}'
377
+ if [ -n "$WEEK" ]; then
378
+ # Weekly cross-team retro (owner / orchestrator): no project, the week is the scope.
379
+ BODY=$(jq -n --arg w "$WEEK" --arg s "$SUMMARY" --argjson p "$PROBLEMS_JSON" '{week: $w, summary: $s, problems: $p}')
380
+ api_call POST "/project-ticket-autopilot/weekly-retro" "$BODY" | jq '{success, retro: .data, error}'
381
+ else
382
+ require_param "project" "$PROJECT"
383
+ require_param "day (--day YYYY-MM-DD)" "$DAY"
384
+ BODY=$(jq -n --arg d "$DAY" --arg s "$SUMMARY" --argjson p "$PROBLEMS_JSON" '{day: $d, summary: $s, problems: $p}')
385
+ api_call POST "/project-ticket-autopilot/$(enc "$PROJECT")/retro" "$BODY" | jq '{success, retro: .data, error}'
386
+ fi
377
387
  ;;
378
388
  self-review)
379
389
  require_param "project" "$PROJECT"
@@ -49,6 +49,14 @@ Record a learning or insight gained during task execution. These learnings are s
49
49
  | `--project` / `-p` | `projectPath` | Yes | Absolute path to the project |
50
50
  | `--learning` / `-l` | `learning` | Yes | The learning or insight (or pipe via stdin) |
51
51
  | `--learning-file` | — | No | Read learning from a file path |
52
+ | `--class` | `correctionClass` | No | Correction class slug (e.g. `git-add-all`) when this learning records a **correction** — see below |
53
+ | `--task` | `relatedTask` | No | Ticket / WorkItem the learning came from |
54
+
55
+ ## Corrections: give them a class
56
+
57
+ When the learning is a correction — someone told you (or you found out) that a way of working was wrong — add `--class <slug>`: a short, stable name for the *kind* of mistake, not this instance of it (`git-add-all`, `skip-tests-before-pr`, `owner-thread-status-lines`). Reuse the same slug every time the same kind comes back; check with `GET /api/memory/corrections?projectPath=…` if unsure.
58
+
59
+ Why: prose is read every turn and still lets the same mistake back in. The second time a class is recorded in a project, the team lead gets one WorkItem asking whether it can be made impossible (structural change), caught before merge (lint/test/CI), caught when it happens (hook), or must stay prose — and records the choice. Without a class, a correction is just another line in memory.
52
60
 
53
61
  ---
54
62
 
@@ -90,6 +98,9 @@ echo "Don't use git add -A — it catches .env files" | bash execute.sh --agent
90
98
 
91
99
  # Learning from file
92
100
  bash execute.sh --agent dev-1 --role developer --project /projects/app --learning-file /tmp/insight.txt
101
+
102
+ # A correction, classed so a repeat reaches the team lead
103
+ bash execute.sh --agent dev-1 --role developer --project /projects/app --class git-add-all --task CREW-42 --learning "[[git]] Never git add -A in this repo: it stages .env. Caught in CREW-42 review."
93
104
  ```
94
105
 
95
106
  ## Examples — Legacy JSON (backward compatible)
@@ -100,4 +111,4 @@ bash execute.sh '{"agentId":"dev-1","agentRole":"developer","projectPath":"/proj
100
111
 
101
112
  ## Output
102
113
 
103
- JSON confirmation that the learning was recorded.
114
+ JSON confirmation that the learning was recorded. With `--class`, also `correction: { class, count, raised }` — `raised: true` means this occurrence sent the team lead the ladder WorkItem.
@@ -22,6 +22,8 @@ AGENT_ID=""
22
22
  AGENT_ROLE=""
23
23
  PROJECT_PATH=""
24
24
  LEARNING=""
25
+ CORRECTION_CLASS=""
26
+ RELATED_TASK=""
25
27
  STRICT=0
26
28
  SKIP_PREFLIGHT=0
27
29
 
@@ -53,6 +55,14 @@ while [[ $# -gt 0 ]]; do
53
55
  LEARNING="$(cat "$2")"
54
56
  shift 2
55
57
  ;;
58
+ --class)
59
+ CORRECTION_CLASS="$2"
60
+ shift 2
61
+ ;;
62
+ --task)
63
+ RELATED_TASK="$2"
64
+ shift 2
65
+ ;;
56
66
  --strict)
57
67
  STRICT=1
58
68
  shift
@@ -67,7 +77,12 @@ while [[ $# -gt 0 ]]; do
67
77
  ;;
68
78
  --help|-h)
69
79
  cat <<'EOF'
70
- Usage: execute.sh --agent <id> --role <role> --project <path> --learning '<text>' [--strict] [--no-preflight]
80
+ Usage: execute.sh --agent <id> --role <role> --project <path> --learning '<text>' [--class <slug>] [--task <id>] [--strict] [--no-preflight]
81
+
82
+ --class <slug> This learning is a correction of kind <slug> (e.g. git-add-all).
83
+ The second time a class is recorded, the team lead gets a
84
+ WorkItem asking for a check in code instead of more prose (#810).
85
+ --task <id> Ticket / WorkItem the learning came from.
71
86
 
72
87
  Karpathy-lite preflight rules (see SKILL.md):
73
88
  1. [[Entity]] opener (HARD)
@@ -113,6 +128,8 @@ if [ -n "$INPUT_JSON" ]; then
113
128
  [ -z "$AGENT_ROLE" ] && AGENT_ROLE=$(printf '%s' "$INPUT" | jq -r '.agentRole // empty')
114
129
  [ -z "$PROJECT_PATH" ] && PROJECT_PATH=$(printf '%s' "$INPUT" | jq -r '.projectPath // empty')
115
130
  [ -z "$LEARNING" ] && LEARNING=$(printf '%s' "$INPUT" | jq -r '.learning // empty')
131
+ [ -z "$CORRECTION_CLASS" ] && CORRECTION_CLASS=$(printf '%s' "$INPUT" | jq -r '.correctionClass // empty')
132
+ [ -z "$RELATED_TASK" ] && RELATED_TASK=$(printf '%s' "$INPUT" | jq -r '.relatedTask // empty')
116
133
  if [ "$STRICT" -eq 0 ]; then
117
134
  JSON_STRICT=$(printf '%s' "$INPUT" | jq -r '.strict // empty')
118
135
  [ "$JSON_STRICT" = "true" ] && STRICT=1
@@ -176,12 +193,17 @@ export _LRN_ROLE="$AGENT_ROLE"
176
193
  export _LRN_PROJECT="$PROJECT_PATH"
177
194
  export _LRN_CONTENT="$LEARNING"
178
195
  export _LRN_STRICT="$STRICT"
196
+ export _LRN_CLASS="$CORRECTION_CLASS"
197
+ export _LRN_TASK="$RELATED_TASK"
179
198
 
180
199
  if [ "$STRICT" -eq 1 ]; then
181
200
  BODY=$(jq -n '{agentId: env._LRN_AGENT, agentRole: env._LRN_ROLE, projectPath: env._LRN_PROJECT, learning: env._LRN_CONTENT, strict: true}')
182
201
  else
183
202
  BODY=$(jq -n '{agentId: env._LRN_AGENT, agentRole: env._LRN_ROLE, projectPath: env._LRN_PROJECT, learning: env._LRN_CONTENT}')
184
203
  fi
185
- unset _LRN_AGENT _LRN_ROLE _LRN_PROJECT _LRN_CONTENT _LRN_STRICT
204
+ # Optional fields: a correction class (ladder, #810) and the task it came from.
205
+ [ -n "$CORRECTION_CLASS" ] && BODY=$(printf '%s' "$BODY" | jq '. + {correctionClass: env._LRN_CLASS}')
206
+ [ -n "$RELATED_TASK" ] && BODY=$(printf '%s' "$BODY" | jq '. + {relatedTask: env._LRN_TASK}')
207
+ unset _LRN_AGENT _LRN_ROLE _LRN_PROJECT _LRN_CONTENT _LRN_STRICT _LRN_CLASS _LRN_TASK
186
208
 
187
209
  api_call POST "/memory/record-learning" "$BODY"
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: Decide Correction
3
+ description: "Record which rung of the correction ladder closes a repeated correction class: structural change, lint/test/CI check, state-triggered hook, or prose with a stated reason (#810)."
4
+ version: 1.0.0
5
+ category: management
6
+ skillType: claude-skill
7
+ assignableRoles:
8
+ - team-leader
9
+ triggers:
10
+ - decide correction
11
+ - correction ladder
12
+ - make it impossible
13
+ - add a check for this
14
+ tags:
15
+ - correction
16
+ - ladder
17
+ - quality
18
+ - management
19
+ execution:
20
+ type: script
21
+ script:
22
+ file: execute.sh
23
+ interpreter: bash
24
+ timeoutMs: 15000
25
+ ---
26
+
27
+ # Decide Correction
28
+
29
+ The correction ladder counts corrections per **class** (a short slug such as `git-add-all`) in each project. The second time a class is recorded you receive a WorkItem: the same kind of mistake came back, and prose (memory, SOP, prompt) did not stop it. This skill records your answer and closes the ladder for that class.
30
+
31
+ ## The rungs, highest first
32
+
33
+ | Rung | Meaning | Example |
34
+ |------|---------|---------|
35
+ | `structural` | Change the API, type or file layout so the mistake can no longer be expressed | the helper takes a typed enum instead of a free string |
36
+ | `check` | A lint rule, test or CI step fails before merge | an ESLint rule, a test that greps for `git add -A` in scripts |
37
+ | `hook` | A state-triggered hook or skill guard catches it the moment it happens | a pre-commit hook; a skill script that refuses the argument |
38
+ | `prose` | Keep it as memory/SOP text — with the reason nothing above is worth it | "happens once a quarter, the fix costs more than the mistake" |
39
+
40
+ Do the work for the rung you pick (or open the PR / ticket for it) **first**, then record the choice with the link. A `prose` decision is not final: if the class comes back twice more, the ladder raises it again and names your earlier reason.
41
+
42
+ ## Usage
43
+
44
+ ```bash
45
+ bash {{SKILLS_PATH}}/team-leader/decide-correction/execute.sh \
46
+ --project /projects/app --class git-add-all --rung check \
47
+ --reason "test in scripts.test.ts fails on 'git add -A'" --link https://github.com/org/repo/pull/321
48
+ ```
49
+
50
+ ## Parameters
51
+
52
+ | Flag | JSON Field | Required | Description |
53
+ |------|-----------|----------|-------------|
54
+ | `--project` / `-p` | `projectPath` | Yes | Absolute project root the class was recorded in |
55
+ | `--class` / `-c` | `correctionClass` | Yes | The class slug from the WorkItem title |
56
+ | `--rung` / `-r` | `rung` | Yes | `structural`, `check`, `hook` or `prose` |
57
+ | `--reason` | `reason` | Yes | Why this rung (required for every rung) |
58
+ | `--link` | `link` | No | PR, file, rule or hook that implements it |
59
+ | `--by` | `decidedBy` | No | Your session name (default `$CREWLY_SESSION_NAME`) |
60
+
61
+ ## Output
62
+
63
+ The class record: tally, occurrences, and the decision just made. To see every class of a project: `GET /api/memory/corrections?projectPath=<root>`.
64
+
65
+ The owner is not involved in ladder decisions. Never post them in the owner's thread.
@@ -0,0 +1,63 @@
1
+ #!/bin/bash
2
+ # Record the team lead's rung for a correction class (#810).
3
+ # execute.sh --project <root> --class <slug> --rung <structural|check|hook|prose> --reason '<why>' [--link <url>] [--by <session>]
4
+ set -euo pipefail
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ source "${SCRIPT_DIR}/../_common/lib.sh"
7
+
8
+ INPUT_JSON=""
9
+ PROJECT_PATH=""
10
+ CLASS=""
11
+ RUNG=""
12
+ REASON=""
13
+ LINK=""
14
+ BY="${CREWLY_SESSION_NAME:-}"
15
+
16
+ if [[ $# -gt 0 && ${1:0:1} == '{' ]]; then
17
+ INPUT_JSON="$1"
18
+ shift || true
19
+ fi
20
+
21
+ while [[ $# -gt 0 ]]; do
22
+ case "$1" in
23
+ --project|-p) PROJECT_PATH="$2"; shift 2 ;;
24
+ --class|-c) CLASS="$2"; shift 2 ;;
25
+ --rung|-r) RUNG="$2"; shift 2 ;;
26
+ --reason) REASON="$2"; shift 2 ;;
27
+ --link) LINK="$2"; shift 2 ;;
28
+ --by) BY="$2"; shift 2 ;;
29
+ --json|-j) INPUT_JSON="$2"; shift 2 ;;
30
+ --help|-h)
31
+ echo "Usage: execute.sh --project <root> --class <slug> --rung <structural|check|hook|prose> --reason '<why>' [--link <url>] [--by <session>]"
32
+ exit 0
33
+ ;;
34
+ *) unknown_arg_exit "$1" ;;
35
+ esac
36
+ done
37
+
38
+ if [ -n "$INPUT_JSON" ]; then
39
+ INPUT=$(read_json_input "$INPUT_JSON")
40
+ [ -z "$PROJECT_PATH" ] && PROJECT_PATH=$(printf '%s' "$INPUT" | jq -r '.projectPath // empty')
41
+ [ -z "$CLASS" ] && CLASS=$(printf '%s' "$INPUT" | jq -r '.correctionClass // empty')
42
+ [ -z "$RUNG" ] && RUNG=$(printf '%s' "$INPUT" | jq -r '.rung // empty')
43
+ [ -z "$REASON" ] && REASON=$(printf '%s' "$INPUT" | jq -r '.reason // empty')
44
+ [ -z "$LINK" ] && LINK=$(printf '%s' "$INPUT" | jq -r '.link // empty')
45
+ [ -z "$BY" ] && BY=$(printf '%s' "$INPUT" | jq -r '.decidedBy // empty')
46
+ fi
47
+
48
+ require_param "projectPath (--project)" "$PROJECT_PATH"
49
+ require_param "correctionClass (--class)" "$CLASS"
50
+ require_param "rung (--rung)" "$RUNG"
51
+ require_param "reason (--reason)" "$REASON"
52
+ [ -z "$BY" ] && BY="team-leader"
53
+
54
+ case "$RUNG" in
55
+ structural|check|hook|prose) ;;
56
+ *) error_exit "rung must be one of structural, check, hook, prose (got: $RUNG)" ;;
57
+ esac
58
+
59
+ export _DC_PROJECT="$PROJECT_PATH" _DC_RUNG="$RUNG" _DC_REASON="$REASON" _DC_LINK="$LINK" _DC_BY="$BY"
60
+ BODY=$(jq -n '{projectPath: env._DC_PROJECT, rung: env._DC_RUNG, reason: env._DC_REASON, decidedBy: env._DC_BY} + (if env._DC_LINK != "" then {link: env._DC_LINK} else {} end)')
61
+ unset _DC_PROJECT _DC_RUNG _DC_REASON _DC_LINK _DC_BY
62
+
63
+ api_call POST "/memory/corrections/$(printf '%s' "$CLASS" | jq -sRr @uri | tr -d '\n')/decide" "$BODY"
@@ -50,6 +50,7 @@ bash {{SKILLS_PATH}}/team-leader/handle-failure/execute.sh '{"workerId":"worker-
50
50
  | `teamId` | No | Team ID (needed for reassignment lookup) |
51
51
  | `requiredRole` | No | Role required for the task (helps find alternatives) |
52
52
  | `taskDescription` | No | Brief task description for context |
53
+ | `projectPath` | No | Project root; with `failureInfo.correctionClass`, the failure is counted on the project's correction ladder (#810) |
53
54
  | `failureInfo` | Yes | Failure details object (see below) |
54
55
 
55
56
  ### failureInfo Object
@@ -60,6 +61,7 @@ bash {{SKILLS_PATH}}/team-leader/handle-failure/execute.sh '{"workerId":"worker-
60
61
  | `failedSteps` | Array of failed verification step names |
61
62
  | `retries` | Number of retries already attempted |
62
63
  | `failureType` | Category of failure (see below) |
64
+ | `correctionClass` | Optional. A short slug for the *kind* of mistake behind the failure (`skip-tests-before-pr`, `git-add-all`). Give one when the failure was a correction of how the worker works, not a flaky environment. The second time a class is recorded in a project you (the lead) get one WorkItem asking whether it can be made impossible, caught by a check or a hook, or must stay prose — answered with `decide-correction`. The output carries `correction: { class, count, raised }`. |
63
65
 
64
66
  ### Failure Types
65
67
 
@@ -19,6 +19,11 @@ RETRIES=$(printf '%s' "$INPUT" | jq -r '.failureInfo.retries // 0')
19
19
  FAILURE_TYPE=$(printf '%s' "$INPUT" | jq -r '.failureInfo.failureType // "unknown"')
20
20
  ERROR_MSG=$(printf '%s' "$INPUT" | jq -r '.failureInfo.error // "Unknown error"')
21
21
  FAILED_STEPS=$(printf '%s' "$INPUT" | jq -c '.failureInfo.failedSteps // []')
22
+ # Correction ladder (#810): a classed failure is counted per project; the
23
+ # second occurrence of a class sends this lead a WorkItem asking for a check
24
+ # in code instead of another retry note.
25
+ CORRECTION_CLASS=$(printf '%s' "$INPUT" | jq -r '.failureInfo.correctionClass // empty')
26
+ PROJECT_PATH=$(printf '%s' "$INPUT" | jq -r '.projectPath // empty')
22
27
 
23
28
  require_param "workerId" "$WORKER_ID"
24
29
 
@@ -97,6 +102,17 @@ if [ "$ACTION" = "reassign" ] && [ -n "$TEAM_ID" ]; then
97
102
  fi
98
103
  fi
99
104
 
105
+ # Correction ladder (#810): count the classed failure; the answer says whether
106
+ # this occurrence raised the ladder WorkItem. Never fails the decision.
107
+ CORRECTION_JSON="null"
108
+ if [ -n "$CORRECTION_CLASS" ] && [ -n "$PROJECT_PATH" ]; then
109
+ export _HF_PROJECT="$PROJECT_PATH" _HF_CLASS="$CORRECTION_CLASS" _HF_AGENT="${WORKER_SESSION:-$WORKER_ID}" _HF_TEXT="$ERROR_MSG" _HF_TASK="$TASK_DESCRIPTION"
110
+ CORR_BODY=$(jq -n '{projectPath: env._HF_PROJECT, correctionClass: env._HF_CLASS, agentId: env._HF_AGENT, text: env._HF_TEXT, source: "failure"} + (if env._HF_TASK != "" then {relatedTask: env._HF_TASK} else {} end)')
111
+ unset _HF_PROJECT _HF_CLASS _HF_AGENT _HF_TEXT _HF_TASK
112
+ CORRECTION_JSON=$( (api_call POST "/memory/corrections" "$CORR_BODY" 2>/dev/null || true) | jq -c '.data // null' 2>/dev/null || true)
113
+ [ -z "$CORRECTION_JSON" ] && CORRECTION_JSON="null"
114
+ fi
115
+
100
116
  # Output decision
101
117
  jq -n \
102
118
  --arg action "$ACTION" \
@@ -106,8 +122,10 @@ jq -n \
106
122
  --arg originalWorkerId "$WORKER_ID" \
107
123
  --arg failureType "$FAILURE_TYPE" \
108
124
  --arg retries "$RETRIES" \
125
+ --argjson correction "$CORRECTION_JSON" \
109
126
  '{
110
127
  action: $action,
128
+ correction: $correction,
111
129
  nextWorkerId: (if $nextWorkerId != "" then $nextWorkerId else null end),
112
130
  nextWorkerSession: (if $nextWorkerSession != "" then $nextWorkerSession else null end),
113
131
  instructions: $instructions,
@@ -152,6 +152,16 @@ export declare const TICKET_AUTOPILOT_CONSTANTS: {
152
152
  /** Option labels of that card */
153
153
  readonly RETRO_APPROVE_LABEL: "Approve";
154
154
  readonly RETRO_SKIP_LABEL: "Skip";
155
+ /** `metadata.kind` of the weekly retro WorkItem (same WorkItem type as the daily retro) */
156
+ readonly WEEKLY_RETRO_METADATA_KIND: "autopilot_weekly_retro";
157
+ /** Local weekday (0 = Sunday) on or after which, at RETRO_HOUR_LOCAL, the previous ISO week's retro is scheduled */
158
+ readonly WEEKLY_RETRO_WEEKDAY_LOCAL: 1;
159
+ /** Global-vault folder the weekly retros are written to */
160
+ readonly WEEKLY_RETRO_WIKI_DIR: "llm-curated/autopilot-retros/weekly";
161
+ /** Most projects listed in detail in the weekly brief (the rest are counted) */
162
+ readonly WEEKLY_RETRO_MAX_PROJECTS_IN_BRIEF: 12;
163
+ /** How long filed daily retros are remembered (days) — the weekly retro reads them */
164
+ readonly RETRO_FILED_MEMORY_DAYS: 60;
155
165
  /** WorkItem type / `metadata.kind` of the goal replan the driver receives when nothing is left to triage */
156
166
  readonly REPLAN_WORK_ITEM_TYPE: "goal_replan";
157
167
  readonly REPLAN_METADATA_KIND: "goal_replan";
@@ -2181,6 +2191,31 @@ export declare const WIKI_GAPS_CONSTANTS: {
2181
2191
  /** Session that authors the page. */
2182
2192
  readonly CALLER_SESSION: "system:wiki-knowledge-gaps";
2183
2193
  };
2194
+ /**
2195
+ * Correction ladder (#810): repeated corrections of one class become a
2196
+ * team-lead WorkItem asking for a check in code instead of more prose.
2197
+ */
2198
+ export declare const CORRECTION_LADDER_CONSTANTS: {
2199
+ /** Per-project store, under the project data dir */
2200
+ readonly STORE_FILE: "correction-ladder.json";
2201
+ /** Occurrences of a class (or after a prose decision) that raise the lead's WorkItem */
2202
+ readonly THRESHOLD: 2;
2203
+ /** An undecided WorkItem older than this is treated as abandoned and raised again */
2204
+ readonly REOPEN_AFTER_MS: number;
2205
+ /** The rungs, highest first: make it impossible → catch before merge → catch when it happens → tell them again */
2206
+ readonly RUNGS: readonly ["structural", "check", "hook", "prose"];
2207
+ /** Class slug bounds */
2208
+ readonly CLASS_MIN_CHARS: 2;
2209
+ readonly CLASS_MAX_CHARS: 48;
2210
+ /** Occurrences kept per class (newest) */
2211
+ readonly MAX_OCCURRENCES_KEPT: 20;
2212
+ /** Occurrences quoted in the lead's brief */
2213
+ readonly OCCURRENCES_IN_BRIEF: 5;
2214
+ /** Correction text kept per occurrence */
2215
+ readonly OCCURRENCE_TEXT_MAX_CHARS: 400;
2216
+ /** WorkItem `metadata.kind` */
2217
+ readonly WORKITEM_KIND: "correction-ladder";
2218
+ };
2184
2219
  /**
2185
2220
  * Daily agent-memory refresh (#1345): what an agent recorded in the wiki
2186
2221
  * log is reflected into its `memory.json` and the project's memory.