passalong 1.4.0 → 1.5.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
@@ -51,10 +51,6 @@ passalong archive <id> off the board and out of the free tier's count
51
51
  passalong rm <id> delete it
52
52
  passalong attach <file> upload a picture or file and print the markdown that points at it
53
53
  passalong work [--once] [--agent CMD] run an agent on each piece of ready work here, in turn
54
- passalong work --watch the runner, in a repo or a folder of repos: work a person marked safe
55
- to run alone, up to 3 at once, each in its own worktree, finished
56
- as a pull request; each agent's steps show in the hub. When Claude's
57
- usage runs out it pauses, and carries on once it is back
58
54
  passalong now what this worktree holds and what is waiting
59
55
  passalong hub open the hub in the browser
60
56
  passalong export [dir] every piece of work as plain markdown
package/bin/passalong CHANGED
@@ -22,8 +22,6 @@
22
22
  // passalong rm <id> delete it
23
23
  // passalong attach <file> upload a picture or a file and print the markdown that points at it
24
24
  // passalong work [--once] [--agent CMD] run an agent on each piece of ready work here, one after another
25
- // passalong work --watch [--every SECS] the runner, in a repo or a folder of repos: keep taking work marked safe to run alone,
26
- // up to 3 at once, each in its own worktree and branch, finished as a pull request
27
25
  // passalong hub open the hub in the browser
28
26
  // passalong export [dir] dump every piece of work as plain markdown (default ./passalong-export)
29
27
  // passalong admin create <email> make an account that runs Passalong (owner only)
@@ -61,7 +59,6 @@ import * as api from "../src/api.js";
61
59
  import { workScaffold } from "../src/capture.js";
62
60
  import { parse, serialize } from "../src/work.js";
63
61
  import * as passalong from "../src/passalong.js";
64
- import { otherCopies } from "../src/runner.js";
65
62
  import * as store from "../src/store.js";
66
63
 
67
64
  const PKG = resolve(dirname(fileURLToPath(import.meta.url)), "..");
@@ -252,79 +249,6 @@ async function statusLine() {
252
249
  }
253
250
  }
254
251
 
255
- /**
256
- * `passalong work --watch`: the runner (src/runner.js). Each piece of work marked safe to run alone
257
- * gets its own worktree, branch and Claude Code; what it does arrives as a pull request.
258
- */
259
- async function runner(f) {
260
- const every = Number(f.every) || 60;
261
- let idle = false;
262
- /** "a, b and 4 more": the repos a runner serves, short enough for one line. */
263
- const some = (repos) =>
264
- repos.length <= 3 ? repos.join(", ") : `${repos.slice(0, 3).join(", ")} and ${repos.length - 3} more`;
265
- await passalong
266
- .watch({
267
- agent: typeof f.agent === "string" ? f.agent : undefined,
268
- every,
269
- cli: fileURLToPath(import.meta.url),
270
- signals: true,
271
- // Said only once the folder checked out: a runner that cannot run says why, not what it will do.
272
- onStart: ({ repos, skipped }) => {
273
- console.error(
274
- `Runner for ${repos.length === 1 ? repos[0] : `${repos.length} repos: ${some(repos)}`}.\n` +
275
- "It takes work marked safe to run alone, up to 3 at once, and finishes each " +
276
- "as a pull request. You can watch each agent here and on the work's page in the hub. " +
277
- "Stop it with Ctrl-C: agents running then stop too.",
278
- );
279
- if (skipped.length)
280
- console.error(`Skipped ${skipped.length} checkout${skipped.length === 1 ? "" : "s"} with no origin remote: ${some(skipped)}`);
281
- // Another copy on PATH (npm's beside pnpm's): updating one leaves the other running.
282
- const mine = JSON.parse(readFileSync(join(PKG, "package.json"), "utf8")).version;
283
- const { others, shadowed } = otherCopies(fileURLToPath(import.meta.url));
284
- for (const o of others)
285
- console.error(
286
- `! Another passalong${o.version ? ` (${o.version})` : ""} is installed at ${o.path}` +
287
- (shadowed && o === others[0]
288
- ? `, and it is the one \`passalong\` runs in a new terminal, not this ${mine}.`
289
- : `, beside this ${mine}.`) +
290
- " Keep one: `npm uninstall -g passalong` or `pnpm remove -g passalong`, whichever installed it.",
291
- );
292
- },
293
- onTask: (t, { dir, branch, repo }) => {
294
- idle = false;
295
- console.error(`\n→ ${t.id} ${t.title}\n ${repo}, on ${branch} in ${dir}`);
296
- },
297
- onStep: (t, text) => console.error(` ${t.id} · ${text}`),
298
- onIdle: (repos) => {
299
- if (!idle)
300
- console.error(
301
- `waiting for work marked safe to run alone in ${some(repos)}. ` +
302
- "Work with no repo needs one picked on its page in the hub.",
303
- );
304
- idle = true;
305
- },
306
- onPaused: (t, { until }) =>
307
- console.error(
308
- `‖ ${t.id} paused: Claude's usage ran out. ` +
309
- (until
310
- ? `It carries on at ${new Date(until).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" })}`
311
- : "It tries again every 15 minutes") +
312
- ", and takes nothing new until then.",
313
- ),
314
- onFinished: (t, { branch, log }) => console.error(`✓ ${t.id} finished on ${branch} (log: ${log})`),
315
- onWaiting: (t, { question }) =>
316
- console.error(`? ${t.id} is waiting on you: "${question.split("\n")[0]}" (answer it in the hub)`),
317
- onResumed: (t, { afterPause }) =>
318
- console.error(
319
- `\n→ ${t.id} ${t.title} (${afterPause ? "carrying on where it stopped" : "answered: carrying on"})`,
320
- ),
321
- onPassed: (t, { dir, log }) =>
322
- console.error(`✗ ${t.id} went back to its author, unfinished. Its worktree: ${dir} (log: ${log})`),
323
- onTrouble: (err, t) => console.error(`! ${t ? `${t.id}: ` : ""}${err?.message || err}`),
324
- })
325
- .catch((e) => die(e.message));
326
- }
327
-
328
252
  const commands = {
329
253
  /**
330
254
  * Write work down: a sentence becomes its title, summary and text, or a file is sent as it is. At
@@ -519,7 +443,14 @@ const commands = {
519
443
  * files without asking — which is yours to decide, not this command's.
520
444
  */
521
445
  async work(f) {
522
- if (f.watch) return runner(f);
446
+ // The runner `--watch` started was removed (2026-11-07). Saying so beats running the queue
447
+ // instead, which is a different thing from what whoever typed `--watch` asked for.
448
+ if (f.watch) {
449
+ console.error(
450
+ "The runner has been removed from Passalong. Open a Claude Code session in your repo and ask it to take work from Passalong instead.",
451
+ );
452
+ process.exit(1);
453
+ }
523
454
  const run = await passalong
524
455
  .work({
525
456
  agent: typeof f.agent === "string" ? f.agent : undefined,
@@ -939,7 +870,22 @@ if (typeof argv.as === "string") {
939
870
  // both are caught here, with `version`, before dispatch. Only the number goes to stdout, so
940
871
  // `passalong -v` can be read by a script comparing it against the registry.
941
872
  if (cmd === "-v" || cmd === "version" || (cmd === "help" && argv.version === true)) {
942
- console.log(JSON.parse(readFileSync(join(PKG, "package.json"), "utf8")).version);
873
+ const mine = JSON.parse(readFileSync(join(PKG, "package.json"), "utf8")).version;
874
+ console.log(mine);
875
+ // Another copy on PATH (npm's beside pnpm's) is the usual reason the version is not the one
876
+ // expected: updating one leaves the other answering. Said on stderr, so stdout stays the number.
877
+ try {
878
+ const { otherCopies } = await import("../src/update.js");
879
+ const { others, shadowed } = otherCopies(fileURLToPath(import.meta.url));
880
+ for (const o of others)
881
+ console.error(
882
+ `! Another passalong${o.version ? ` (${o.version})` : ""} is installed at ${o.path}` +
883
+ (shadowed && o === others[0]
884
+ ? `, and it is the one \`passalong\` runs in a new terminal, not this ${mine}.`
885
+ : `, beside this ${mine}.`) +
886
+ " Keep one: `npm uninstall -g passalong` or `pnpm remove -g passalong`, whichever installed it.",
887
+ );
888
+ } catch {}
943
889
  } else if (cmd === "--help" || cmd === "-h" || cmd === "help") commands.help();
944
890
  // A command this build does not have used to print the help page and exit 0, which reads as "that
945
891
  // command exists and did nothing" — and the usual cause is an older passalong, where the command is
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "passalong",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Work, projects, documents and files for a team and its agents: take work, hand it in with evidence, and keep what the team knows in its projects.",
5
5
  "mcpName": "io.github.codellyson/passalong",
6
6
  "keywords": [
package/src/api.js CHANGED
@@ -357,11 +357,6 @@ export const setStatus = (id, status) =>
357
357
  export const remove = (id) => call(`/v1/work/${id}`, { method: "DELETE" });
358
358
  export const tasks = () => call("/v1/tasks");
359
359
  export const nextTask = (body) => call("/v1/tasks/next", { method: "POST", body });
360
- /** The runner saying how it is, for the hub: what it is on, today's count, or that it stopped. */
361
- export const runnerStatus = (body) => call("/v1/runner", { method: "PUT", body });
362
- /** What a runner's agent did since the last report, a line each, for the hub to show. */
363
- export const workSteps = (id, steps) =>
364
- call(`/v1/work/${encodeURIComponent(id)}/steps`, { method: "POST", body: { steps } });
365
360
  export const reopen = (id, why) =>
366
361
  call(`/v1/work/${encodeURIComponent(id)}/reopen`, { method: "POST", body: { why } });
367
362
  /** Take work back from whoever holds it. */
package/src/checks.js CHANGED
@@ -50,8 +50,8 @@ export const CHECK_TIMEOUT_MS = 10 * 60 * 1000;
50
50
  export const OUTPUT_MAX = 4000;
51
51
 
52
52
  /**
53
- * The tail of what a command printed, because that is where a runner puts what went wrong. A head
54
- * would hold the banner and the first hundred passing lines.
53
+ * The tail of what a command printed, because that is where a test runner puts what went wrong. A
54
+ * head would hold the banner and the first hundred passing lines.
55
55
  */
56
56
  function tail(out, max = OUTPUT_MAX) {
57
57
  const s = String(out ?? "").replace(/\s+$/, "");