@jaybeeuu/agent-cortex 2.8.0 → 2.10.0

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 (52) hide show
  1. package/CHANGELOG.md +304 -0
  2. package/README.md +30 -3
  3. package/agents/README.md +7 -2
  4. package/agents/guppi/agent.md +231 -0
  5. package/agents/guppi/claude/frontmatter.json +6 -0
  6. package/agents/guppi/pi/frontmatter.json +6 -0
  7. package/agents/plan/agent.md +6 -0
  8. package/agents/ralph-plan/agent.md +6 -0
  9. package/bin/installers/claude.mjs +8 -23
  10. package/bin/installers/pi.mjs +8 -2
  11. package/extensions/interrupt-bookmark/README.md +129 -0
  12. package/extensions/interrupt-bookmark/index.test.ts +717 -0
  13. package/extensions/interrupt-bookmark/index.ts +354 -0
  14. package/extensions/interrupt-bookmark/package.json +20 -0
  15. package/extensions/skill-stats/README.md +84 -3
  16. package/extensions/skill-stats/index.ts +62 -3
  17. package/extensions/skill-stats/package.json +1 -1
  18. package/extensions/skill-stats/rollup.test.ts +643 -0
  19. package/extensions/skill-stats/rollup.ts +415 -0
  20. package/extensions/skill-stats/timeline.ts +101 -0
  21. package/package.json +1 -1
  22. package/scripts/lib/compose-agent.mjs +45 -7
  23. package/scripts/lib/manifest.mjs +29 -0
  24. package/skills/review/review-defects/EXAMPLES.md +80 -4
  25. package/skills/review/review-defects/SKILL.md +47 -16
  26. package/skills/review/review-report/EXAMPLES.md +118 -0
  27. package/skills/review/review-report/SKILL.md +138 -0
  28. package/skills/review/review-report/scripts/report.mjs +1032 -0
  29. package/skills/workflow/hitl-queue/BOUNDARY.md +122 -0
  30. package/skills/workflow/hitl-queue/DEADLINES.md +59 -0
  31. package/skills/workflow/hitl-queue/RECOMMEND.md +89 -0
  32. package/skills/workflow/hitl-queue/SCOPES.md +118 -0
  33. package/skills/workflow/hitl-queue/SKILL.md +150 -0
  34. package/skills/workflow/hitl-queue/scripts/boundary.mjs +493 -0
  35. package/skills/workflow/hitl-queue/scripts/queue.mjs +1012 -0
  36. package/skills/workflow/hitl-queue/scripts/recommend.mjs +492 -0
  37. package/skills/workflow/hitl-queue/scripts/scopes.mjs +479 -0
  38. package/skills/workflow/plan/SKILL.md +13 -0
  39. package/skills/workflow/prioritise-work/CHALLENGE.md +139 -0
  40. package/skills/workflow/prioritise-work/SKILL.md +150 -0
  41. package/skills/workflow/prioritise-work/scripts/challenge.mjs +505 -0
  42. package/skills/workflow/prioritise-work/scripts/strategy.mjs +756 -0
  43. package/skills/workflow/prioritise-work/templates/strategy.md +87 -0
  44. package/skills/workflow/ralph/REFERENCE.md +6 -1
  45. package/skills/workflow/ralph/scripts/prune-worktrees.mjs +185 -10
  46. package/skills/workflow/run-pipeline-stage/playbooks/review.md +5 -2
  47. package/skills/workflow/score-bead/FORMAT.md +73 -0
  48. package/skills/workflow/score-bead/SKILL.md +112 -0
  49. package/skills/workflow/score-bead/scripts/rice.mjs +664 -0
  50. package/skills/workflow/using-agent-skills/SKILL.md +6 -1
  51. package/token-map.README.md +14 -2
  52. package/token-map.json +17 -3
@@ -0,0 +1,122 @@
1
+ # The boundary re-rank
2
+
3
+ A session that answers one item at a time drifts: the next item is whichever one was nearest, not
4
+ whichever one matters most. This file defines the unit a session works in, and the one comparison
5
+ it makes when that unit finishes.
6
+
7
+ ## The unit of work
8
+
9
+ | Term | Meaning |
10
+ |---|---|
11
+ | **Theme** | The current epic. One theme at a time, and its children are the items it needs. |
12
+ | **Item** | One thing the theme needs from a human: a decision answered, a plan shaped, a handoff written, a review given. |
13
+ | **Boundary** | The completion of one item. The point where the session stops and checks whether the theme is still the right place to be. |
14
+
15
+ The theme and its trail are the session's memory, not the window: a clear drops the window, and
16
+ `bd show <epic-id>` still holds what was decided and why. [RECOMMEND.md](RECOMMEND.md) carries the
17
+ one-item session start; this file carries what happens after that item is done.
18
+
19
+ ## The decision at every boundary
20
+
21
+ One trade-off, three outcomes, and no fourth:
22
+
23
+ | Outcome | When it is right | Read from the scores? |
24
+ |---|---|---|
25
+ | `stay` | Continue in the theme. The theme's next item still leads the queue. | Yes |
26
+ | `switch` | Leave the theme, because higher-priority work waits elsewhere. | Yes |
27
+ | `move` | Leave the theme for one item, because a break improves the next item. | No — a judgement, so it carries its own reason |
28
+
29
+ The first two are readable from the two totals. A `move` is not: it is about what the next item
30
+ needs, so it is always the human's reason and never the queue's.
31
+
32
+ ## The block
33
+
34
+ ```text
35
+ Boundary · theme tst-t · strategy v2
36
+ recommendation: switch — the queue's top item scores 8.0 against the theme's next 4.2, so higher-priority work waits elsewhere
37
+ theme next tst-a · total 4.2 · Decide the theme question
38
+ queue top tst-b · total 8.0 · Decide the outside question
39
+ next: stay, switch or move is the human's call — nothing is recorded until they answer
40
+ ```
41
+
42
+ **Both scores are always printed**, and the reason names both. That is the whole rule: an agent
43
+ that leaves a theme without showing what it left for has asserted a priority it never displayed.
44
+ A switch with no comparison on screen is a defect, not a summary.
45
+
46
+ The recommendation is derived from the two stored totals and nothing else. The totals, the
47
+ components and both multipliers are the queue's; this comparison computes no score, so the number
48
+ a reader checks is the number the queue ranked by. [SKILL.md](SKILL.md) owns that arithmetic.
49
+
50
+ ## The record
51
+
52
+ ```bash
53
+ node <skill-scripts>/boundary.mjs boundary --theme <epic-id>
54
+ node <skill-scripts>/boundary.mjs boundary --theme <epic-id> --decide switch
55
+ node <skill-scripts>/boundary.mjs boundary --theme <epic-id> --decide move --reason "<what the break buys>"
56
+ ```
57
+
58
+ A run with no `--decide` prints the comparison and writes nothing. A run that names a decision
59
+ writes one trail entry with `bd note` on the **theme bead** — the epic that owns the items — and
60
+ prints it back:
61
+
62
+ ```text
63
+ trail: tst-t · [2026-11-15T09:30:00.000Z] boundary: switch · theme next tst-a total 4.2 vs queue top tst-b total 8.0 · reason: the queue's top item scores 8.0 against the theme's next 4.2, so higher-priority work waits elsewhere
64
+ ```
65
+
66
+ Three parts, and all three are required: the **timestamp**, **both scores**, and the **reason**.
67
+ A later session reads `bd show tst-t` and sees why the theme was kept or left, without reading a
68
+ transcript. An entry with a reason but no numbers cannot be checked, and an entry with numbers but
69
+ no reason says nothing about intent.
70
+
71
+ ## Recommends, never switches
72
+
73
+ - **The human decides.** `--decide` is the recording step, and it is passed after an answer, never
74
+ instead of asking for one. Nothing switches on its own.
75
+ - **A decision against the recommendation needs `--reason`.** A `move` always does, and so does a
76
+ `stay` or `switch` that contradicts the two scores. The refusal is the point: an unexplained
77
+ override is the case the trail exists to catch.
78
+ - **The boundary changes what to do next, never what outranks what.** The order is the queue's and
79
+ the rubric is the strategy's. A wish for a different order is a `prioritise-work` change, not a
80
+ boundary decision.
81
+
82
+ ## Which item is compared
83
+
84
+ `--theme <epic-id>` names the theme. The theme's next item is the **highest-ranked item under that
85
+ theme** in the queue, so the comparison cannot be steered by naming a weak one. `--next <id>` names
86
+ another item when the session knows better, and the queue's top item is rank 1 either way.
87
+
88
+ ## The states that are stated instead of guessed
89
+
90
+ | First line | What it means | The step it offers |
91
+ |---|---|---|
92
+ | `No boundary · the queue is empty` | No open `execution:hitl` bead exists | File the theme's next item, or lift a deferral |
93
+ | `No boundary · theme <id> has no ranked item` | Nothing scored sits under that theme | Name the item with `--next`, or score it with `score-bead` |
94
+ | `No boundary · <id> is not in the queue` | The named item is not an open scored `execution:hitl` bead | Name one from the queue, or score that bead |
95
+
96
+ None of them guesses an item and none is a failure of the run: exit `0` means an answer was
97
+ printed, whichever answer it was.
98
+
99
+ | Option | Effect |
100
+ |---|---|
101
+ | `--theme <epic-id>` | The theme; required, because a boundary belongs to one |
102
+ | `--next <id>` | The theme's next item, when the session names it instead |
103
+ | `--decide <outcome>` | `stay`, `switch` or `move` — record the human's decision |
104
+ | `--reason "<text>"` | Why that decision; required when it contradicts the recommendation |
105
+ | `--file <path>` | Strategy file (default `.agent-cortex/working-docs/strategy.md`, relative to the repository root) |
106
+ | `--include-ideas` | Rank `kind:idea` beads too, as the queue does |
107
+ | `--cwd <dir>` | Directory the strategy path and `bd` resolve from |
108
+ | `--json` | Print the answer as JSON, including the decision and the trail entry |
109
+
110
+ Exit `1` means a `bd` call failed and exit `2` means a malformed call — a missing `--theme`, an
111
+ outcome outside the three, or a decision against the scores with no reason. `BD_PATH` pins the `bd`
112
+ binary.
113
+
114
+ ## Red Flags
115
+
116
+ - Red flag: leaving a theme without the two scores on screen, so the reader has to trust the agent.
117
+ - Red flag: recording a decision with no reason, or a reason with no numbers in the trail entry.
118
+ - Red flag: switching because the agent judged the priority itself, instead of reading the queue.
119
+ - Red flag: recomputing a total here, so the comparison and the queue can disagree.
120
+ - Red flag: recording a decision the human has not given, so the session switches on its own.
121
+ - Red flag: writing the trail entry to another scope, so a theme's history lands somewhere its
122
+ owner will not read.
@@ -0,0 +1,59 @@
1
+ # Deadlines
2
+
3
+ A `--due` date is the one deadline field, and `bd` already stores it. The queue multiplies the
4
+ total by the factor of the narrowest tier the remaining time fits inside. The table is the
5
+ strategy's to tune, the boundary is arithmetic, and the row prints what it applied.
6
+
7
+ ## The shipped table
8
+
9
+ | Time left | Factor |
10
+ |---|---|
11
+ | more than a week | 1 |
12
+ | within a week | 1.5 |
13
+ | within two days | 2 |
14
+ | within a day | 4 |
15
+ | overdue | 8 |
16
+
17
+ Those numbers are the **shipped default**: a strategy with no `## Deadline tiers` section ranks on
18
+ this table, and so does a run whose header says `strategy unknown`.
19
+
20
+ ## A strategy's table
21
+
22
+ The strategy's optional `## Deadline tiers` section carries the table a repository tunes, so
23
+ moving a tier is a strategy edit and a `bump`, never a code change. A row reads
24
+ `| <when> | <factor> |`, narrowest first, and `<when>` is `within <n><m|h|d>`,
25
+ `more than <n><m|h|d>` or `overdue`.
26
+
27
+ A table that is present must carry exactly one `overdue` row, exactly one `more than` row and at
28
+ least one `within` row, and `validate` exits 1 naming every row it cannot read — a malformed table
29
+ never falls back to the default in silence.
30
+
31
+ ## Where a boundary falls
32
+
33
+ A boundary falls on the side that names it: with exactly one day left a bead earns 4, and a
34
+ millisecond more earns 2. A bead whose deadline is exactly now has not slipped yet, so it is not
35
+ overdue. A bead with no due date sits outside the tiers and keeps the factor 1, so tuning a row
36
+ never lifts undated work by accident.
37
+
38
+ ## The deadline clause in a row
39
+
40
+ A ranked row shows the deadline, the time left and the factor, and an overdue bead is flagged
41
+ rather than lifted in silence:
42
+
43
+ ```text
44
+ 2 bd-2 8.0 rice 4.2 = R4 · I3 · C0.7 · E2 ×1.00 dependents(0) ×1.0 deadline ×8 OVERDUE by 1d (due 2026-11-14T08:59Z)
45
+ ```
46
+
47
+ An unscored row has no total to multiply, so it shows the due moment and `OVERDUE` with no factor
48
+ at all:
49
+
50
+ ```text
51
+ - bd-6 — unscored — no rice metadata OVERDUE by 2d 11h (due 2026-11-13T00:00Z)
52
+ ```
53
+
54
+ ## Deferral
55
+
56
+ `--defer` is bd's own field and bd's own rule, so the queue reads it rather than inventing a second
57
+ one. `bd ready` wakes a bead whose defer date has passed, while `bd list` keeps reporting the stale
58
+ `deferred` status it was parked in, so the queue applies that same wake rule to `defer_until`. A
59
+ bead deferred into the future is absent and counted; a bead whose defer date has passed is listed.
@@ -0,0 +1,89 @@
1
+ # One recommendation
2
+
3
+ The queue is a list; a session that has to decide says one item and stops. `recommend.mjs` prints
4
+ that one row — the same total, components and multipliers the queue computed, plus the line of the
5
+ strategy that justifies it — and states a condition instead of choosing whenever it cannot justify
6
+ a row.
7
+
8
+ Every run ends in one of five answers: the block, or one of the four conditions that replace it.
9
+
10
+ It ranks nothing. The bead is `rows[0]` of the queue, or the bead the human named, and every number
11
+ on the block is the row's own.
12
+
13
+ ## The three commands
14
+
15
+ ```bash
16
+ node <skill-scripts>/../../prioritise-work/scripts/strategy.mjs validate # prints the rubric
17
+ node <skill-scripts>/recommend.mjs recommend --json # the top row, structured
18
+ node <skill-scripts>/recommend.mjs recommend --why "<one line of the rubric>"
19
+ ```
20
+
21
+ `validate` first, because the printed rubric is the only text a justification may be quoted from.
22
+ `--json` second, to read the row's id and totals. `--why` last, once the line that justifies that
23
+ bead has been chosen from the rubric.
24
+
25
+ ## The quote rule
26
+
27
+ `--why` names a line, or part of one, from the strategy file. The script finds that line in the
28
+ file, prints it verbatim with the section it sits under, and refuses the run (exit `2`) when no line
29
+ contains it. Guidance comments in the file are not quotable: they are instructions for whoever
30
+ writes the rubric, not the owner's own words.
31
+
32
+ ```text
33
+ why: "shorter review turnaround for human-gated work." · Current themes
34
+ ```
35
+
36
+ A quote the file does not hold is a refused run rather than a weaker reason, so an invented
37
+ justification cannot reach the human.
38
+
39
+ ## The block
40
+
41
+ ```text
42
+ Recommendation · tst-a · total 10.0 · strategy v2
43
+ Ship the decision queue
44
+ rice 4.2 = R4 · I3 · C0.7 · E2 ×2.39 dependents(3) ×1.0
45
+ unblocks tst-c, tst-d, tst-e
46
+ why: "shorter review turnaround for human-gated work." · Current themes
47
+ ```
48
+
49
+ Five lines: the bead and its total, its title, the four components with the unblocking multiplier
50
+ and the work-in-progress multiplier, the beads the answer releases, and the strategy line. One
51
+ recommendation, never the list the row came from.
52
+
53
+ ## When the human names a bead
54
+
55
+ `--bead <id>` recommends the bead the human named instead of the top row. The block is the same,
56
+ and one line is added when the queue put a different bead first:
57
+
58
+ ```text
59
+ queue top: tst-a · total 10.0 · Ship the decision queue
60
+ ```
61
+
62
+ That line is the whole of the disagreement. The human's choice stands, and a wish to see it first
63
+ is a strategy change through `prioritise-work`, never a silent override.
64
+
65
+ ## The stated conditions
66
+
67
+ Each one leads with `No recommendation`, names the condition, and offers the one step that clears
68
+ it. None of them guesses a bead, and none of them is a failure of the run: exit `0` means an answer
69
+ was printed, whichever answer it was.
70
+
71
+ | First line | What it means | The step it offers |
72
+ |---|---|---|
73
+ | `No recommendation · no usable strategy` | The file is absent, or `validate` rejected it; every defect is listed | Write or fix it with `prioritise-work` |
74
+ | `No recommendation · nothing is scored` | The queue holds beads, and not one carries a `rice` record | Score one bead with `score-bead` |
75
+ | `No recommendation · the queue is empty` | No open `execution:hitl` bead exists; the excluded idea and deferred counts are printed | File the decision as an `execution:hitl` bead, or lift a deferral |
76
+ | `No recommendation · <id> is not in the queue` | The bead the human named is not an open `execution:hitl` bead | Check it with `bd show`, then name one from the queue |
77
+
78
+ | Option | Effect |
79
+ |---|---|
80
+ | `--why "<line>"` | The strategy line that justifies the choice; required before a block is printed |
81
+ | `--bead <id>` | Recommend the bead the human named, noting the queue's own top choice |
82
+ | `--file <path>` | Strategy file (default `.agent-cortex/working-docs/strategy.md`, relative to the repository root) |
83
+ | `--include-ideas` | Rank `kind:idea` beads too, as the queue does |
84
+ | `--cwd <dir>` | Directory the strategy path and `bd` resolve from |
85
+ | `--json` | Print the answer as JSON, including the state name |
86
+
87
+ Exit `1` means a `bd` call failed, and exit `2` means a malformed call — an unknown option, or a
88
+ `--why` the strategy does not contain. `BD_PATH` pins the `bd` binary. The script makes no writes:
89
+ the tracker calls are `bd list` and `bd dep list`, nothing else.
@@ -0,0 +1,118 @@
1
+ # Scopes
2
+
3
+ The scope list says which bd workspaces the queue reads, and which one it may write. It is a
4
+ **file**, never code: a path in a script would name one person's machine, and a scope list does
5
+ not.
6
+
7
+ ## The file
8
+
9
+ | Item | Value |
10
+ |---|---|
11
+ | Default | `.agent-cortex/scopes.json`, relative to the repository root |
12
+ | User level | `<AGENT_CORTEX_HOME>/scopes.json`, then `~/.agent-cortex/scopes.json` |
13
+ | Override | `--scopes <path>` |
14
+ | Fallback | no file found: one scope, named `code`, for the current workspace, writable |
15
+
16
+ The project list is read first, so a repository can commit the scopes its work spans. The user
17
+ list is the personal one: it travels with the person, not the checkout. With neither, the queue
18
+ behaves as it did before scopes existed — one workspace, one list.
19
+
20
+ ```json
21
+ {
22
+ "scopes": [
23
+ { "name": "code", "path": ".", "kind": "code", "readOnly": false },
24
+ { "name": "notes", "path": "~/personal", "kind": "personal", "readOnly": true },
25
+ { "name": "ops", "path": "../ops", "kind": "ops" }
26
+ ]
27
+ }
28
+ ```
29
+
30
+ | Field | Required | Meaning |
31
+ |---|---|---|
32
+ | `name` | yes | The tag every row from this scope carries. Unique within the file. |
33
+ | `path` | yes | The workspace. `~` is the home directory; a relative path resolves against the repository root of the list itself, never the directory the run started in. The queue reports the resolved absolute path, never the text this field holds. |
34
+ | `kind` | no | `code`, `personal` or `ops`. Default `code`. A `personal` scope is the one a shared invocation withholds. |
35
+ | `readOnly` | no | Default `true`. A scope you did not mark writable is read-only. |
36
+
37
+ ## One writable scope
38
+
39
+ The **current workspace** — the nearest ancestor of the run's directory that carries its own
40
+ `.beads` — is the only scope a command may write to. A scope is writable only when it is not
41
+ marked read-only *and* its resolved path is that workspace, so a list copied onto another machine
42
+ cannot widen the writable set: the same entry that is writable in your checkout is read-only in
43
+ mine.
44
+
45
+ The queue writes nothing today — its tracker calls are `bd list` and `bd dep list`. The rule is
46
+ enforced anyway, at the one function every tracker call for a scope passes through, so a later
47
+ change cannot quietly write to the wrong workspace:
48
+
49
+ ```js
50
+ guardRunner(scope, bd) // refuses any call that is not one of the two reads
51
+ ```
52
+
53
+ ## Availability
54
+
55
+ A scope is read only when it can be:
56
+
57
+ - **the directory exists**, and
58
+ - **it carries its own `.beads`**, because bd resolves a workspace by walking *up* from the
59
+ current directory. A configured directory with no tracker of its own would otherwise read the
60
+ enclosing workspace's beads and tag them with the wrong scope, which is a privacy failure and a
61
+ correctness one.
62
+
63
+ Anything else is reported `unavailable` with the reason, above the list, and skipped. A `bd` call
64
+ that fails marks its own scope unavailable and leaves the others alone, so one broken workspace
65
+ never costs the whole queue. Exit code stays `0`.
66
+
67
+ ## The daily scope note
68
+
69
+ Above the ranked list the queue prints one line: which scopes the day belongs to, and the
70
+ strategy line that says so.
71
+
72
+ ```
73
+ today · personal, code — "daily: personal, code — Monday and Tuesday are the personal objectives" (strategy v3, "## Current themes", scope notes)
74
+ ```
75
+
76
+ The line is read from the **personal scope's** own strategy, at the documented default path
77
+ inside that workspace, so the note is personal strategy text and never a copy of it. Write it as
78
+ one bullet under `## Current themes`:
79
+
80
+ ```markdown
81
+ - daily: personal, code — Monday and Tuesday are the personal objectives
82
+ ```
83
+
84
+ The scope names before the em dash are what the note leads with; the rest is the reason, quoted
85
+ verbatim. The citation names the strategy version, the section the line sat under, and the scope
86
+ it was read from. When no personal scope is configured, or none carries a `daily:` line, the note
87
+ says that and names what to add — it never invents one.
88
+
89
+ ## The privacy boundary
90
+
91
+ - **A read-only scope receives no write.** Enforced by `guardRunner`, tested with a mutation.
92
+ - **A shared invocation reads no personal scope at all.** `--shared`, or
93
+ `AGENT_CORTEX_QUEUE_SHARED=1`, marks output that will leave this machine — a CI log, a pasted
94
+ report, a handoff to another agent. Personal scopes are then `withheld`: not read, not ranked,
95
+ not quoted, and counted in the header so nothing disappears silently. **A withheld scope
96
+ publishes neither its name nor its path**, because both identify a workspace the reader may not
97
+ see: the header prints the count, and `--json` prints `null` for both fields.
98
+ - **A withheld scope publishes no `name` and no `path`.** Both identify the workspace the reader
99
+ may not see — a path encodes the home directory, and a name is whatever the owner called it —
100
+ so `--json` carries `null` for both. `kind`, `readOnly` and `writable` remain, because the
101
+ header already says a personal scope was withheld.
102
+ - **A personal row appears only in a local invocation.** Local is the default, because the person
103
+ reading their own queue on their own machine is the common case.
104
+ - **Nothing personal is written anywhere.** The queue copies no bead text into another workspace
105
+ because it writes no bead at all, and the daily line is quoted, never re-filed.
106
+
107
+ ## Reading the queue
108
+
109
+ ```bash
110
+ node <skill-scripts>/queue.mjs queue # every configured scope
111
+ node <skill-scripts>/queue.mjs queue --scopes ./list.json
112
+ node <skill-scripts>/queue.mjs queue --shared # output that leaves this machine
113
+ node <skill-scripts>/queue.mjs queue --json # scope statuses and the note, structured
114
+ ```
115
+
116
+ `--json` carries the same answer with every derived field: each scope's `status`, `reason`,
117
+ `readOnly` and `writable`, the daily note, and the withheld counts. A withheld scope has `null`
118
+ for `name` and `path`.
@@ -0,0 +1,150 @@
1
+ ---
2
+ name: hitl-queue
3
+ description: Ranks the open execution:hitl beads across every configured bd workspace into one list ordered by RICE, transitively blocked dependents, work in progress and the time left to each due date, prints what each answer unblocks and which scope each row came from, notes which scope the day belongs to, and recommends one item from that list with the line of the strategy that justifies it. Use when deciding which human decision to answer next, when a session cold-starts and must say one item, when a planning session starts, or when asked "what needs my decision", "show the queue", "what should we look at" or "what should I answer first".
4
+ ---
5
+
6
+ # HITL Queue
7
+
8
+ Owns one output: **the ranked list of beads waiting for a human answer**, read from every configured workspace and tagged with the scope each row came from. Each row carries its own arithmetic, so the owner can check *why* one decision outranks another instead of trusting a number.
9
+
10
+ A queue is not a priority. The RICE score is `score-bead`'s judgement, the band it implies is reviewed there, and this skill only orders beads by a number that already exists. Where no score exists, the queue says so and ranks nothing: inventing an order would hide the gap a person has to fill.
11
+
12
+ ## When to use
13
+
14
+ - A planning session starts and the owner needs to know which decision comes first.
15
+ - "What needs my decision?", "show the queue", "what should I answer first?".
16
+ - "What should we look at?" — a cold start that must say one item rather than print the list. See [RECOMMEND.md](RECOMMEND.md).
17
+ - Before dispatching work from a backlog of HITL beads: the answer unblocks the work, so the order of answers is the order of the work.
18
+ - A bead was scored or re-scored and the order should follow the new number.
19
+
20
+ ## When NOT to use
21
+
22
+ - Judging one bead's components — use `score-bead`. This skill reads a score, it never makes one.
23
+ - Writing or bumping the rubric the score rests on — use `prioritise-work`.
24
+ - Choosing what to *build* next with an agent — `ralph` drains `execution:afk` beads, and ideas are ranked by `flesh-out-idea`.
25
+ - Recording a new idea — use `record-idea`.
26
+
27
+ ## The formula
28
+
29
+ ```
30
+ total = rice × (1 + ln(1 + dependents)) × (in progress ? 1.5 : 1) × deadline
31
+ ```
32
+
33
+ | Term | Meaning |
34
+ |---|---|
35
+ | `rice` | The stored `score` from the bead's `rice` metadata, written by `score-bead`. Never recomputed here. |
36
+ | `dependents` | Distinct beads that wait on this answer, **transitively**. |
37
+ | `1.5` | Work in progress outranks equal work not started, so the queue drains WIP first. |
38
+ | `deadline` | The strategy's tier factor for the time left until the bead's `--due`; `1` when it has no due date. |
39
+
40
+ The dependent count is the load-bearing term. A bead blocking A, which blocks B, which blocks C, unblocks **three**. The walk follows `bd dep list <id> --direction up` from bead to bead, and collects **beads, not paths**: when the graph reconverges (a diamond — one bead reached by two routes), it is counted once, because counting paths would measure the shape of the graph instead of the work an answer releases.
41
+
42
+ Two edges of the walk are deliberate: only `blocks` edges count, because a related or duplicate edge is not something anyone waits on; and the walk passes through every bead while counting only live ones, because a closed bead is still a link in the chain but finished work cannot be unblocked. `1 + ln(1 + n)` is logarithmic on purpose: unblocking thirty chores must not drown the list under one row, and zero dependents scores `1`, so a bead that unblocks nothing is not penalised — it is simply not lifted.
43
+
44
+ ## Deadlines
45
+
46
+ A `--due` date is the one deadline field, and `bd` already stores it. The queue multiplies the total by the factor of the narrowest tier the time left fits inside; those factors are the **shipped default**, and a strategy's optional `## Deadline tiers` section replaces them, so moving a tier is a strategy edit and a `bump`, never a code change. A bead with no due date keeps the factor 1. [DEADLINES.md](DEADLINES.md) carries the shipped table, the row syntax, the `validate` rule, the boundary and the defer rule.
47
+
48
+ ## Scopes
49
+
50
+ A scope is one bd workspace. The queue reads every one and writes to none; the current workspace is the only writable scope, so every other is read-only, and a missing workspace is `unavailable` and skipped. A shared invocation (`--shared`, or `AGENT_CORTEX_QUEUE_SHARED=1`) withholds every personal scope and the daily note, and prints the count. [SCOPES.md](SCOPES.md) carries the list format, the writable rule, the daily note and the boundary.
51
+
52
+ ## The report
53
+
54
+ One flat list, no sections, ranked first and unscored last:
55
+
56
+ ```
57
+ HITL decision queue · 3 ranked, 1 unscored · 3 scopes, 1 unavailable · strategy v2
58
+ total = rice × (1 + ln(1 + dependents)) × 1.5 in-progress × deadline tier · ties break on rice, then scope, then id · unscored last
59
+ excluded: 3 kind:idea beads (--include-ideas ranks them)
60
+ today · personal, code — "daily: personal, code — Monday and Tuesday are the personal objectives" (strategy v3, "## Current themes", scope notes)
61
+ unavailable: ops (/srv/ops) — workspace does not exist
62
+
63
+ 1 code bd-7 10.0 rice 4.2 = R4 · I3 · C0.7 · E2 ×2.39 dependents(3) ×1.0
64
+ Ship the queue — unblocks bd-8, bd-9, bd-10
65
+ 2 notes bd-2 8.0 rice 4.2 = R4 · I3 · C0.7 · E2 ×1.00 dependents(0) ×1.0 deadline ×8 OVERDUE by 1d (due 2026-11-14T08:59Z)
66
+ Decide the API shape — unblocks nothing
67
+ - code bd-4 — unscored — no rice metadata (score it with score-bead)
68
+ Decide the rollout — unblocks nothing
69
+ ```
70
+
71
+ Every row carries its rank, scope, id, total, the four components the score was computed from, all three multipliers, a deadline clause when the bead has a due date, the title, and one clause naming what the answer unblocks — the scope tag keeps two workspaces that reuse a bead id apart. An unscored row keeps its place at the end of the same list with the reason: no `rice` metadata, no score inside a `rice` record, or scored against an older strategy version (that last one is ranked and marked `scored at strategy v2, current v3`). `--json` prints the same answer with every derived field, including each scope's status and the daily note, for a caller that needs to act on it.
72
+
73
+ ### One item, not the list
74
+
75
+ A session that must decide says one row and stops. `recommend.mjs` prints the top row with the line of the strategy that justifies it, and a stated condition with one next step when it cannot justify a row. It ranks nothing: the total, the components and the multipliers are the row's own. [RECOMMEND.md](RECOMMEND.md) carries the four stated conditions, the `--why` rule and the `--bead` form for a bead the human named. When that item is done, `boundary.mjs` compares the theme's next item against the queue's top item and prints both scores, and [BOUNDARY.md](BOUNDARY.md) carries the block, the three outcomes and the options.
76
+
77
+ ```bash
78
+ node <skill-scripts>/recommend.mjs recommend --json # the top row, structured
79
+ node <skill-scripts>/recommend.mjs recommend --why "<line>" # the block to say
80
+ ```
81
+
82
+ ## Ordering rules
83
+
84
+ - **Ranked by total, descending.** The total is rounded to one decimal *before* ranking, so the number a reader sees is the number the order was decided by.
85
+ - **Ties break on rice, then scope, then id.** `ln` flattens, so different dependent counts can reach the same one-decimal total; a fixed tie-break means two runs over one backlog print byte-identical output. The scope breaks the tie before the id because two workspaces may hold the same bead id.
86
+ - **Unscored beads never earn a rank.** They are listed, not placed, and never compared by title or by priority.
87
+
88
+ ## Workflow
89
+
90
+ 1. **Check the strategy is readable.** The queue compares each score's `strategyVersion` against the file to mark stale scores, and reads its deadline tiers. Run `strategy.mjs validate` first. A missing or invalid strategy does not stop the queue — the scores are already on the beads — but the header then reports `strategy unknown`, no staleness, and the shipped deadline default.
91
+
92
+ 2. **Run the queue.** This is the hand-run form: no planner, no agent, one command.
93
+
94
+ ```bash
95
+ node <skill-scripts>/queue.mjs queue
96
+ ```
97
+
98
+ 3. **Report it as printed**, then name the top item plainly: id, title, and what answering it unblocks. Do not group by priority, re-sort, or drop the unscored rows — the flat list is the answer.
99
+
100
+ 4. **Score what is unscored, one bead at a time.** Load `score-bead`, judge the four components against the strategy, and record the score. Re-run the queue; the bead takes its place.
101
+
102
+ ```bash
103
+ node <skill-scripts>/queue.mjs queue --file <path> --include-ideas
104
+ ```
105
+
106
+ | Option | Effect |
107
+ |---|---|
108
+ | `--scopes <path>` | Scope list. Default `.agent-cortex/scopes.json` from the repository root, then `~/.agent-cortex/scopes.json`, then the current workspace alone. |
109
+ | `--shared` | Output that leaves this machine: personal scopes are not read, and the daily note is withheld. |
110
+ | `--file <path>` | Strategy file. Default `.agent-cortex/working-docs/strategy.md`, relative to the repository root. |
111
+ | `--include-ideas` | Rank `kind:idea` beads too. They are excluded by default — see below. |
112
+ | `--cwd <dir>` | Directory the current workspace, its strategy path and `bd` resolve from. |
113
+ | `--json` | Print the report as JSON, including each scope's status and the daily note, for a caller that needs to act on it. |
114
+
115
+ `BD_PATH` pins the `bd` binary. Exit `0` means the queue was built, including a run that ranked nothing or skipped an unavailable scope; exit `1` means an internal failure, and exit `2` a malformed argument or a scope list that cannot be read. The script makes no writes: the tracker calls are `bd list` and `bd dep list`, nothing else, and a read-only scope receives no other call.
116
+
117
+ ## What the queue leaves out
118
+
119
+ - **Ideas, by default.** `kind:idea` beads are HITL by convention but deliberately unshaped: a RICE score on an idea measures a guess about a guess, and the idea backlog is ranked by `flesh-out-idea` instead. An idea that outranks a ripe decision would send the owner into an interview they did not choose. The count is printed so nothing is dropped silently; `--include-ideas` ranks them when the backlog is what the owner is working.
120
+ - **Deferred and closed beads.** A bead deferred into the future stays out of the queue until that date passes, and the count is printed; the queue never adds a second deferral concept. Finished work waits on nothing.
121
+
122
+ ## Red Flags
123
+
124
+ - Red flag: writing to a scope the list did not mark writable, so personal work lands in a code workspace.
125
+ - Red flag: reporting only the scopes that answered, so a missing workspace looks like an empty backlog — or inventing a daily note instead of quoting the strategy line.
126
+ - Red flag: scoring a bead inside this skill, so the queue's order rests on an unreviewed number.
127
+ - Red flag: ranking an unscored bead by its priority or its title, so the list looks complete and hides the gap.
128
+ - Red flag: counting dependency paths instead of distinct beads, so a diamond inflates one row above its real value.
129
+ - Red flag: re-sorting or grouping the flat list before reporting it, so the order the owner reads is not the order that was computed.
130
+ - Red flag: hardcoding a deadline factor in the script, so the owner cannot tune the rise without a release.
131
+ - Red flag: excluding ideas or deferrals without printing how many were excluded.
132
+
133
+ ## Verification checklist
134
+
135
+ - [ ] The report is one flat list: ranked rows first, unscored rows last, no sections.
136
+ - [ ] Every row is tagged with its scope, every unavailable scope is named with its reason, and the daily note above the list quotes the strategy line with its version and section.
137
+ - [ ] Each row shows the rank, scope, id, total, the four components, all three multipliers, the title and what the answer unblocks.
138
+ - [ ] A bead blocking three others ranks above an equal bead blocking none; an in-progress bead ranks above an equal not-started one.
139
+ - [ ] A bead due in three days ranks above an otherwise identical bead with no due date; an overdue bead is flagged `OVERDUE` and carries the top tier of the table in force. Every row with a due date shows the due moment and the time left, only a ranked row shows a factor, and a changed tier moves the rank with no code change.
140
+ - [ ] With no scores, the header says nothing can be ranked and every candidate is listed unscored with a reason.
141
+ - [ ] Two identical runs printed byte-identical output, and the excluded idea and deferred counts were reported, or the header said there were none.
142
+ - [ ] A session that had to decide said one block: the bead, its components, both multipliers, the unblocked beads and the quoted strategy line — or one stated condition with its next step.
143
+
144
+ ## See Also
145
+
146
+ - [SCOPES.md](SCOPES.md) — the scope list: its file, its default, the writable rule and the privacy boundary.
147
+ - [score-bead](../score-bead/SKILL.md) — owns the `rice` record this queue reads, and the band proposal.
148
+ - [prioritise-work](../prioritise-work/SKILL.md) — owns the strategy file and its version.
149
+ - [bd-tool](../../productivity/bd-tool/SKILL.md) — the tracker commands, and where operational state lives.
150
+ - [hitl-collab](../hitl-collab/SKILL.md) — the handoff document for a decision that needs more than an answer.