slack-term 1.40.0 → 1.41.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.
package/README.md CHANGED
@@ -123,11 +123,15 @@ slack react "<permalink>" eyes --remove # take a reaction back
123
123
 
124
124
  # Ask a question with its choices pre-seeded as 1️⃣..🔟 reactions — answering is
125
125
  # one tap on an existing pill, no emoji picker. Same two-step confirm gate as send.
126
+ # A ❓ "その他 (other)" pill always follows the choices: pressing it means "none of
127
+ # these" and the answer comes as a reply (exit 5), not as the ❓ itself.
128
+ # The instructions are posted in ja or en: --lang / SLACK_TERM_LANG, else the
129
+ # answerers' Slack locale, else the question's own language, else $LANG, else ja.
126
130
  slack ask "@bob" "本番に出してよい?" "出してよい" "待って"
127
131
  # --wait blocks until answered and prints ONLY the answer on stdout, so it composes:
128
132
  ANS=$(slack ask "@bob" "本番に出してよい?" "出してよい" "待って" --code=<code> --wait)
129
133
  # exit 0 = answered, 2 = timed out (--timeout, default 3600s), 3 = transport failure,
130
- # 4 = a reply matched several choices, 5 = a free-text reply that picked NO choice —
134
+ # 4 = a reply matched several choices, 6 = the question was voided, 5 = a free-text reply that picked NO choice —
131
135
  # the reply text is on stdout, it is not a decision, and the question stays open.
132
136
  #
133
137
  # The question must say WHO may answer — only their reaction/reply is taken as the
@@ -138,8 +142,20 @@ slack ask "#eng" "@here 誰か見れる?" "見る" "あとで" # anyo
138
142
  #
139
143
  # With no choices the question asks for a free-text reply and the reply is the answer.
140
144
  # In a DM a plain reply counts; in a channel only reactions and thread replies do.
141
- # Once answered, the question is edited to "✅ …回答済み > <answer>" and the unpressed
142
- # seeds are removed, leaving the chosen pill visible.
145
+ # Once answered, the question is edited to "✅ …回答済み > <answer>" — the body/background
146
+ # and the CHOSEN option line stay; the other options, ❓ line and instructions go. The
147
+ # unpressed seeds are removed, leaving the chosen pill visible.
148
+ #
149
+ # Thread notes (audience replies that are not the answer, even after ✅) go to
150
+ # stderr; --json puts {answer, notes[], cursor} on stdout. Feed cursor back as --after:
151
+ # slack ask --waitFor='<permalink>' --timeout 0 --json --after=<cursor>
152
+ #
153
+ # Retire a question that expired / stopped meaning anything (無効化) — waits on it exit 6:
154
+ # slack ask --void='<permalink>' --reason 'head moved' --superseded-by '<new permalink>'
155
+ # Change one: slack ask --edit='<permalink>' ["new question" [choices…]] [--body …]
156
+ # (options only while unanswered; after that: --void='<permalink>' --reask …)
157
+ # List mine with live state: slack ask --ls [--stale 24h] [--state all] [--json]
158
+ # (`slack edit` refuses an edit that would break an ask/poll; --force overrides.)
143
159
  #
144
160
  # WITHOUT --wait, stdout is the command that collects the answer later:
145
161
  RESUME=$(slack ask "@bob" "本番に出してよい?" "出してよい" "待って" --code=<code>)
package/SKILL.md CHANGED
@@ -162,11 +162,19 @@ without losing clicks. A reaction is durable state anyone can read back later.
162
162
  the other party counts automatically.
163
163
  - **Answer paths**: a pill, or free text. In a DM a plain reply counts; in a channel only
164
164
  reactions and thread replies do (a channel carries unrelated traffic).
165
+ - **❓ is the standing "other" choice.** Every question with choices lists it last
166
+ (`1️⃣ … 2️⃣ … 3️⃣ … ❓ その他 — スレッドで返信`) and seeds it after the keycaps. Pressing it
167
+ is not an answer — `--wait` notes it on stderr and keeps waiting for the reply, which
168
+ arrives as free text (exit `5`).
169
+ - **The instructions are posted in `ja` or `en`.** `--lang` (or `SLACK_TERM_LANG`) decides;
170
+ otherwise the answerers' Slack locale when they all share one, else the language the
171
+ question is written in, else the system locale, else `ja`. The confirm gate prints the
172
+ choice and why (`Language: en (answerers' Slack locale; …)`). `--waitFor` reads either.
165
173
  - **Two pills pressed = no answer.** Changing your mind leaves both reactions in place, so
166
174
  `ask` says so in the thread once and keeps waiting rather than guessing.
167
175
  - **Exit codes** are the contract: `0` answered (the answer alone on stdout), `2` nobody
168
176
  replied, `3` transport/config failure, `4` a reply matched several choices (stdout
169
- empty), `5` a **free-text reply** that picked none of the offered choices — the reply
177
+ empty), `6` the question was **voided** (stop waiting), `5` a **free-text reply** that picked none of the offered choices — the reply
170
178
  text is on stdout. Everything human-facing goes to stderr, so
171
179
  `ANS=$(slack ask … --wait)` is safe.
172
180
  - **A reply that chooses nothing is delivered, but is not a decision.** When choices were
@@ -177,6 +185,46 @@ without losing clicks. A reaction is durable state anyone can read back later.
177
185
  so a pill pressed later still decides it: re-wait past the delivered reply with
178
186
  `slack ask --waitFor='<permalink>' --after=<reply ts>` (stderr prints this line).
179
187
 
188
+ **Thread notes ride along with the answer.** A reply from the audience that is not the
189
+ answer (「あと cswap ls も見て」 next to a pressed pill) is a *note*. Notes are read even when
190
+ a pill answered, and again on every `--waitFor` of a ✅ question, so a note written after
191
+ the answer still reaches you. Plain mode: stdout is still the answer alone, and the notes go
192
+ to stderr. `--json`: stdout is one object
193
+ `{status, answer, how, who, notes:[{ts,user,text,permalink}], cursor, permalink}`, with the same
194
+ exit codes. Pass `cursor` back as `--after` on your next `--waitFor --timeout 0` and you
195
+ never get the same note twice. Only the question's audience counts; the asker, bots and
196
+ bystanders are never notes.
197
+
198
+ **Answering keeps the context.** The ✅ rewrite keeps the question's body (its background)
199
+ and the chosen option; only the options not chosen, the ❓ line and the instructions go.
200
+ The head is unchanged (`:white_check_mark:` prefix, question, stamp, quoted answer), so
201
+ anything that keys on the prefix or re-reads the answer works on old and new ✅ bodies alike.
202
+
203
+ **Voiding a question (無効化).** When a question has expired or stopped meaning anything
204
+ (the head it was pinned to moved, the decision was made elsewhere), retire it:
205
+ `slack ask --void='<permalink>' --reason '…' [--superseded-by '<new permalink>']`
206
+ (repeatable `--void=`; alias `slack ask void <link…>`; same `--code` gate; own questions
207
+ only, `--as-bot` for the bot's). The text becomes `:no_entry_sign:` + reason with the body
208
+ kept, our pills come off, and a 🚫 reaction is added. Three states, three prefixes:
209
+ `:question:` open, `:white_check_mark:` answered, `:no_entry_sign:` void. `--wait` /
210
+ `--waitFor` on a void question **exit 6** (`--json` → `status: "void"`): stop waiting.
211
+ Answered questions cannot be voided.
212
+
213
+ **Changing a question: `--edit`, not `slack edit`.**
214
+ `slack ask --edit='<permalink>' ["new question" [choices…]] [--body …]` rebuilds it with the
215
+ ask layout (same `--code` gate), so collect still reads it. Wording can change any time;
216
+ the **options** only while nobody has answered. After that, re-ask it:
217
+ `slack ask --void='<permalink>' --reask [--reason …] ["new question" [choices…]]` posts the
218
+ question again in the same place (old text/choices/body unless you give new ones) and voids
219
+ the old one as replaced by it — one gate for both. Plain `slack edit` refuses an edit that
220
+ would break an ask/poll (text no longer readable, or an answered/void question made open
221
+ again); edits that keep it readable — e.g. a script writing the ✅ form — pass as usual.
222
+
223
+ **What did I ask, and what became of it.** `slack ask --ls` lists your asks from the local
224
+ sent-log with their LIVE state (`--state open|answered|void|all`, default open; `--channel`;
225
+ `--json`). `--ls --stale 24h` = open and older than 24h, and prints the one `--void=` command
226
+ that would retire them all (behind the usual gate). Only asks sent from this machine.
227
+
180
228
  **Collecting an answer you did not block on.** Without `--wait`, stdout is a runnable
181
229
  `slack ask --waitFor='<permalink>'`. Run it any time — it re-reads the question from Slack
182
230
  and recovers everything it needs by parsing the message, so nothing is stored locally and