Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
{
"name": "human-fsm",
"source": "./plugins/human-fsm",
"description": "Slash commands for the human's side of the issue→PR pipeline FSM: read the next ai:ready PR and check the vetter's verdict against the diff and the issue it closes, read the next ai:close-candidate flag and check the producer's reason against the issue and the code it claims about, read the next ai:design PR and check the raised question against the issue and the code it is about, read the next FSM leak and locate which of three defects left the PR in no modeled state, then rule on a close-candidate, reject, rule a design question, or keep an issue open. Every input comes from pr-review-report; none writes GitHub state itself.",
"version": "0.14.0",
"description": "Slash commands for the human's side of the issue→PR pipeline FSM: read the next ai:ready PR and check the vetter's verdict against the diff and the issue it closes, read the next ai:close-candidate flag and check the producer's reason against the issue and the code it claims about, read the next ai:design PR and check the raised question against the issue and the code it is about, read the next FSM leak and locate which of three defects left the PR in no modeled state, then rule on a close-candidate, send work back as needs-work, rule a design question, or keep an issue open. Every input comes from pr-review-report; none writes GitHub state itself.",
"version": "0.15.0",
"author": { "name": "Rain Open Source Software Ltd" },
"keywords": [
"rainlanguage",
Expand Down
85 changes: 44 additions & 41 deletions CLAUDE.md

Large diffs are not rendered by default.

240 changes: 123 additions & 117 deletions README.md

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions campaign-prompt.txt

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/human-fsm/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "human-fsm",
"displayName": "Human FSM transitions",
"version": "0.14.0",
"version": "0.15.0",
"description": "Slash commands for the human's side of the rainlanguage issue→PR pipeline finite state machine: the reads that precede a ruling and the transitions that make it. Every input arrives from pr-review-report — each ruling as one subcommand, /nr, /ncc, /nd and /nm as typed MCP reads — and the guards (vocabulary, mandatory note, provenance anchor, stranded-flag refusal, subject type, terminal-is-moot, idempotence) live in that binary, not here.",
"author": {
"name": "Rain Open Source Software Ltd",
Expand Down
4 changes: 2 additions & 2 deletions plugins/human-fsm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ JSON-RPC frame, a Python filter over the response, and two raw `gh` calls.
| `/nm [1-3]` | `next_leak` + `pr_context` + `pr_checkout` + `clone_release` (MCP) and the `audit` skill — the next FSM-conformance leak, and which of three places the defect is in: the PR's state record, the machine's vocabulary, or the classifier. Writes no GitHub state |
| `/close-candidate <owner/repo#n> uphold "…"` | `human-close` — rule, retire `ai:close-candidate`, close. Issue **or** PR, resolved by lookup |
| `/close-candidate <owner/repo#n> reject "…"` | `record-close-candidate-verdict … reject` — drop the flag, back to the producer (issue-only) |
| `/reject <owner/repo#n> "…"` | `human-rule … reject --rework` / `human-rule-issue … reject --rework` — the send-back: `ai:reject` (PR) plus the trusted `Rework note` work order, one call, pinned to the head sha or the issue. `--rework` is REQUIRED on either subject; there is no parked reject |
| `/design <owner/repo#n> "…"` | `human-rule … design --rework` / `human-rule-issue … design --rework` — the answer, delegated as a work order: `ai:reject` on a PR (the same send-back a rejection is, #219), comment-only on an issue. `--rework` is REQUIRED; there is no parked spelling |
| `/needs-work <owner/repo#n> "…"` | `human-rule … needs-work --rework` / `human-rule-issue … needs-work --rework` — the send-back: `ai:needs-work` (PR) plus the trusted `Rework note` work order, one call, pinned to the head sha or the issue. `--rework` is REQUIRED on either subject; there is no parked needs-work |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Document the issue-side state explicitly.

The /needs-work row names human-rule-issue but documents only ai:needs-work, which applies to pull requests. State that the issue path writes human:needs-work, consistent with plugins/human-fsm/commands/needs-work.md.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/human-fsm/README.md` at line 19, Update the /needs-work documentation
row to distinguish the issue path from the pull-request path: retain
ai:needs-work for pull requests and explicitly state that human-rule-issue
writes human:needs-work, matching the behavior documented in needs-work.md.

| `/design <owner/repo#n> "…"` | `human-rule … design --rework` / `human-rule-issue … design --rework` — the answer, delegated as a work order: `ai:needs-work` on a PR (the same send-back a needs-work is, #219), comment-only on an issue. `--rework` is REQUIRED; there is no parked spelling |
| `/keep-open <owner/repo#n> "…"` | `human-rule-issue … keep-open` — the sacred "never re-flag this" (issue-only) |

Names collide across plugins; `/human-fsm:close-candidate` disambiguates.
Expand Down
4 changes: 2 additions & 2 deletions plugins/human-fsm/commands/close-candidate.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ issue to the producer's uncovered backlog, a PR to the vet queue — either free
to be re-flagged on better evidence. It judges a producer FLAG on either subject
type; the one PR it refuses is the one whose label is the vetter's own `close`
verdict (no producer claim exists there to judge — that PR is yours to `uphold`
above, or to send back with `/reject`), and the refusal says so and names the
moves that do apply.
above, or to send back with `/needs-work`), and the refusal says so and names
the moves that do apply.

If you mean "this must **never** be flagged again" rather than "not on this
evidence", that is the sacred ruling `/keep-open`, not this.
Expand Down
8 changes: 4 additions & 4 deletions plugins/human-fsm/commands/design.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description: Rule design on a PR or an issue — record the answer and send it straight back to the producer, the same send-back a rejection is.
description: Rule design on a PR or an issue — record the answer and send it straight back to the producer, the same send-back a needs-work is.
argument-hint: <owner/repo#n> <note…>
allowed-tools: Bash(pr-review-report human-rule:*), Bash(pr-review-report human-rule-issue:*)
---
Expand All @@ -15,10 +15,10 @@ Refuse and say why if SUBJECT is not `owner/repo#n` or NOTE is empty. **Never
infer an owner or a repo.**

A design ruling IS its answer, and the answer is producer work — the same
send-back a rejection is (#219). There is no parked spelling: a question still
send-back a needs-work is (#219). There is no parked spelling: a question still
open is already the `ai:design` state, so if you do not have the answer yet
there is nothing to rule — wait until you do. The work order is required,
exactly as it is on `/reject`:
exactly as it is on `/needs-work`:

```text
pr-review-report human-rule <slug> <n> design <NOTE> --rework <WORK ORDER>
Expand All @@ -30,7 +30,7 @@ note and the order are genuinely the same sentence, use it for both. When you
cannot tell what the producer should DO, ask — that one question is cheaper than
delegating a placeholder.

On a PR this lands `ai:reject` (every other `ai:*` cleared, `ai:design`
On a PR this lands `ai:needs-work` (every other `ai:*` cleared, `ai:design`
included) plus a `👤 human` comment pinned to the **head sha** recording the
ruling word `design`, plus the `Rework note @<sha>: …` work order in the exact
trusted form the producer's `trusted-comments --marker 'Rework note'`
Expand Down
4 changes: 2 additions & 2 deletions plugins/human-fsm/commands/keep-open.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ pr-review-report human-rule-issue <slug> <n> keep-open <NOTE>

`keep-open` is **issue-only**: it answers a producer close-candidate flag with
"no", and a PR has no such flag to answer — `human:keep-open` on a PR is a label
the lane classifier buckets nowhere, so the PR would silently leave the
human-decisions lane entirely. The tool refuses it there and says so.
the lane classifier buckets nowhere, so the ruling would record nothing at all.
The tool refuses it there and says so.

This is the one ruling that **clears** an `ai:*` label: `keep-open` contradicts
`ai:close-candidate` outright, so the flag goes with it. The comment pins to the
Expand Down
14 changes: 7 additions & 7 deletions plugins/human-fsm/commands/nd.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ deliverables, and the whole job is telling them apart:
consult, or resting on a false premise about what the code currently does. The
finding is the misroute, stated with **what the correct state would have
been** — a verdict the vetter could have recorded, producer work that needed
no permission, or a reject with the defect named.
no permission, or a needs-work with the defect named.

Name the finding before you argue it. A presentation that drifts between the
three is the reprint this command exists to replace.
Expand Down Expand Up @@ -156,12 +156,12 @@ settled matter costs a human decision anyway.
## The exit: an answer is a send-back

The ruling this read precedes is the design ruling, and answering IS routing:
the answer lands the PR back with the producer as `ai:reject` with the answer as
the trusted work order, posted in the same call at the same anchor — a design
ruling is the same act a rejection is, and the producer is the next mover from
the moment it is written. There is no parked spelling and no waiting state: a
design ruling without an executable answer is not a ruling yet, and the machine
holds no state for half of one.
the answer lands the PR back with the producer as `ai:needs-work` with the
answer as the trusted work order, posted in the same call at the same anchor — a
design ruling is the same act a needs-work is, and the producer is the next
mover from the moment it is written. There is no parked spelling and no waiting
state: a design ruling without an executable answer is not a ruling yet, and the
machine holds no state for half of one.

So every finding above ends in a producer work order, and the presentation
should make writing it cheap:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description:
Rule reject on a PR or an issue — a send-back, with the reason AND the work
order on the record in one call.
Rule needs-work on a PR or an issue — a send-back, with the reason AND the
work order on the record in one call.
argument-hint: <owner/repo#n> <note…>
allowed-tools: Bash(pr-review-report human-rule:*), Bash(pr-review-report human-rule-issue:*)
---
Expand All @@ -11,7 +11,7 @@ Arguments: `$ARGUMENTS`
- **SUBJECT** is the first word — an `owner/repo#n` reference. Split it on `#`
into `<slug>` and `<n>`.
- **NOTE** is everything after it, and it is required. It carries TWO records
the tool keeps distinct: the RULING (why this is rejected — provenance, pinned
the tool keeps distinct: the RULING (why this needs work — provenance, pinned
forever) and the WORK ORDER (what the producer must do — spent once executed).
Split the note accordingly: the reason stays the ruling note, the actionable
instruction goes in `--rework`. When the user gave one sentence that is both,
Expand All @@ -23,20 +23,20 @@ infer an owner or a repo.**
Run:

```text
pr-review-report human-rule <slug> <n> reject <RULING NOTE> --rework <WORK ORDER>
pr-review-report human-rule <slug> <n> needs-work <RULING NOTE> --rework <WORK ORDER>
```

On a PR that applies **`ai:reject`** — the ONE reject state, whoever ruled — and
posts TWO comments pinned to the **head sha**: the `👤 human` ruling (authority:
it is what makes this a human's ruling rather than the vetter's, and what the
vetter reads when it re-judges the rework) and the `Rework note @<sha>: …` work
order, in the exact trusted form the producer's
On a PR that applies **`ai:needs-work`** — the ONE send-back state, whoever
ruled — and posts TWO comments pinned to the **head sha**: the `👤 human` ruling
(authority: it is what makes this a human's ruling rather than the vetter's, and
what the vetter reads when it re-judges the rework) and the
`Rework note @<sha>: …` work order, in the exact trusted form the producer's
`trusted-comments --marker 'Rework note'` verification accepts. One call does
both — there is no second `gh` command, and a mistyped marker is impossible.

`--rework` is REQUIRED on a reject: a reject IS a send-back, so there is no
parked spelling here (or anywhere — `/design` is the same send-back, #219). If
the rework is not worth doing at all, that is a different ruling —
`--rework` is REQUIRED on a needs-work: it IS a send-back, so there is no parked
spelling here (or anywhere — `/design` is the same send-back, #219). If the
rework is not worth doing at all, that is a different ruling —
`/close-candidate` for a decided close, `human-close` to close now — and the
tool's refusal names them.

Expand All @@ -57,15 +57,15 @@ exact command for the other subject. Run that one, with the same NOTE and the
same `--rework`:

```text
pr-review-report human-rule-issue <slug> <n> reject <RULING NOTE> --rework <WORK ORDER>
pr-review-report human-rule-issue <slug> <n> needs-work <RULING NOTE> --rework <WORK ORDER>
```

The issue ruling writes `human:reject` — an issue has no vetter-side reject for
it to be one half of — and pins to the issue as filed instead of a head sha; the
work order rides with it the same way. Note that on an issue carrying a **live**
producer close-candidate flag this is refused on purpose, because a
`human:reject` there would strand the flag for ever. That refusal names all four
legal moves.
The issue ruling writes `human:needs-work` — an issue has no vetter-side
send-back for it to be one half of — and pins to the issue as filed instead of a
head sha; the work order rides with it the same way. Note that on an issue
carrying a **live** producer close-candidate flag this is refused on purpose,
because a `human:needs-work` there would strand the flag for ever. That refusal
names all four legal moves.

Any other refusal: relay it verbatim and stop. Do not reach for `gh` — a
hand-applied label binds to no anchor, records no reason, and a hand-typed
Expand Down
12 changes: 6 additions & 6 deletions plugins/human-fsm/commands/nm.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ deliverable of this command is naming which:
label went missing or was hand-mangled. The finding is the state it belongs
in, and the ONE command that files it there, written out in full so the human
can type it:
- `/human-fsm:reject <owner/repo#n> <note>` — work is owed on it; the note is
the work order, and the producer is the next mover.
- `/human-fsm:needs-work <owner/repo#n> <note>` — work is owed on it; the note
is the work order, and the producer is the next mover.
- `/human-fsm:design <owner/repo#n> <note>` — the note is the ANSWER to a
question the PR raises, which is itself producer work.
- `/human-fsm:close-candidate <owner/repo#n> uphold <note>` — the PR is
Expand Down Expand Up @@ -180,8 +180,8 @@ The rulings this command precedes are the existing ones and it invents none —
these five are the whole shipped set, and a command named outside them cannot be
typed:

- `/human-fsm:reject <owner/repo#n> <note>` — files the PR into rework with the
order on the record.
- `/human-fsm:needs-work <owner/repo#n> <note>` — files the PR into rework with
the order on the record.
- `/human-fsm:design <owner/repo#n> <note>` — the note is the answer, and the
answer travels to the producer as its work order in the same act.
- `/human-fsm:close-candidate <owner/repo#n> uphold <note>` — ends what is
Expand Down Expand Up @@ -221,8 +221,8 @@ population is the LANE CLASSIFIER's own verdict — the same call that decides
every other PR's state — so this command, the `human-queue` array and the
dashboard box cannot hold three opinions about which PRs escaped the machine.
That is not decoration: while the enumeration was a second reading of the labels
(`no ai:* label`) it swept in every PR parked in the human-decisions lane, which
are in a modeled state, waiting on exactly the human running this command.
(`no ai:* label`) it swept in every PR then parked in a modeled `human:*` state,
waiting on exactly the human running this command.

The queue is **oldest first**. A leak is in nobody's queue — not the producer's,
not the vetter's, no human inbox but this one — so nothing else will ever
Expand Down
5 changes: 3 additions & 2 deletions plugins/human-fsm/commands/nr.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,9 @@ rule of the document it was handed to.
The grant is four typed calls plus `Skill` and `Read`, and `Read` applies to the
`pr_checkout` tree and nothing else. All four typed calls are reads except
`clone_release`, which disposes of what this command itself created and writes
no GitHub state. The rulings remain `/reject`, `/design`, `/close-candidate`,
`/keep-open`, and the merge is the human's, on a PR they named.
no GitHub state. The rulings remain `/needs-work`, `/design`,
`/close-candidate`, `/keep-open`, and the merge is the human's, on a PR they
named.

That list is a **declaration, not a sandbox**: measured on Claude Code 2.1.220,
a command granting only `Read` still ran a `Bash` call with no permission
Expand Down
Loading
Loading