@retasc/cli 1.33.0 → 1.34.1

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/CHANGELOG.md CHANGED
@@ -6,6 +6,35 @@ release commits and the issues they reference.
6
6
 
7
7
  Dates are the npm publish date. Each entry names the RTSC issue behind it.
8
8
 
9
+ ## 1.34.1 (2026-08-25)
10
+
11
+ - **RTSC-741** — a rejected write no longer costs you the lease. The watchdog decided
12
+ when to stop heartbeating an issue by looking at the request you sent, never at whether
13
+ the server accepted it. So a `save_issue` that came back an error still dropped the
14
+ issue from the heartbeat map while you were still holding it. Nothing renewed it after
15
+ that, it ran out its half hour, and the reclaimer handed your work to another agent
16
+ while you were in the middle of it, with no sign anything had gone wrong. Every drop
17
+ now requires the call to have actually succeeded. The trigger is the new server-side
18
+ rule that moving an issue into `review` must carry a handoff: a rejection on that write
19
+ is the expected first attempt for any agent that has not learned the field yet, so a
20
+ rare edge became a common one.
21
+
22
+ ## 1.34.0 (2026-08-24)
23
+
24
+ - **RTSC-731** — `bind` stops asking whether you want to join an org you are already in.
25
+ A teammate given access to a second project was shown "Join Retasc, or start your own
26
+ workspace?", with the second option one keystroke away from creating a duplicate
27
+ organization that cannot be deleted from the terminal. Invites that only add projects
28
+ to a membership you already have are no longer treated as onboarding, and no longer
29
+ suppress the single-org shortcut. Your agent still hears about them, and
30
+ `setup_status` now asks about them in its own words, naming the project and the
31
+ organization so "Retasc the org" and "Retasc the project" can't be confused.
32
+ - **RTSC-731** — the invite questions hand back a value your agent can actually use.
33
+ Both onboarding questions told the agent to pass the chosen answer to `accept_invite`'s
34
+ `org` flag, then offered "join" as that answer — so an agent doing exactly what it was
35
+ told got "no invite to join is waiting for you", while one that ignored the instruction
36
+ and read the prose succeeded. The accept option now carries the organization itself.
37
+
9
38
  ## 1.33.0 (2026-08-23)
10
39
 
11
40
  - **RTSC-722** — the setup questions arrive as a matrix your agent can actually render.
@@ -728,7 +728,17 @@ export async function bindAction(opts) {
728
728
  if (!orgId) {
729
729
  const me = (await api.me());
730
730
  const orgs = me.orgs ?? [];
731
- const pendingInvites = me.pendingInvites ?? [];
731
+ // RTSC-731 JOIN invites only. RTSC-730 widened what `me.pendingInvites` returns to
732
+ // include invites that merely add projects to a membership somebody already has, and
733
+ // this block asks "join this org, or start your own workspace?" — a question whose
734
+ // premise is false for an existing member, and whose second option creates a SECOND
735
+ // org on the billing rail with no CLI-callable delete (RTSC-297). A widening also
736
+ // must not suppress the single-org shortcut below.
737
+ //
738
+ // Widenings are NOT dropped from the product, only from THIS question: the notice
739
+ // rider still relays them, `whoami` still lists them, `setup_status` asks about them
740
+ // with its own wording, and `accept_invite` still takes them.
741
+ const pendingInvites = (me.pendingInvites ?? []).filter((i) => !i.widensExisting);
732
742
  if (isInteractive()) {
733
743
  const chosen = await pick("Select an org", orgs, (o) => `${o.name} (${o.slug})`);
734
744
  if (chosen) {
@@ -18,6 +18,9 @@ function idOf(issue) {
18
18
  * - next_batch(claim) response → { issues:[{id, claimToken}] } → register each
19
19
  * - release_issue request → drop that issue's lease
20
20
  * - save_issue(status: done|canceled) request → drop that issue's lease
21
+ *
22
+ * Every drop requires the call to have SUCCEEDED (RTSC-741) — a rejected write leaves
23
+ * the lease in place, because the agent still holds the issue server-side.
21
24
  */
22
25
  export function applyObservation(leases, o) {
23
26
  const r = o.result;
@@ -37,7 +40,24 @@ export function applyObservation(leases, o) {
37
40
  }
38
41
  }
39
42
  // Releases / terminal status drop the lease — the issue is named in the REQUEST.
40
- const id = typeof o.args?.identifier === "string" ? o.args.identifier : undefined;
43
+ //
44
+ // RTSC-741: but ONLY if the call actually succeeded. These branches read the REQUEST
45
+ // shape, so a REJECTED write used to drop the lease of an issue the agent still holds
46
+ // server-side. Nothing then renews it, it runs out the bare 30-minute TTL, and the
47
+ // reclaimer hands the issue to someone else while the agent is still working on it.
48
+ // `shouldReapOnClose` below already applies exactly this check for the same reason.
49
+ //
50
+ // It matters now because RTSC-741 made `save_issue status:"review"` REJECTABLE
51
+ // (HANDOFF_REQUIRED): a rejected review write is the expected first attempt for any
52
+ // agent that hasn't learned the field yet, and for every already-running session whose
53
+ // cached tool schema predates the deploy. What was a rare edge is briefly the norm.
54
+ //
55
+ // Erring toward KEEPING the lease is the safe direction, and the module already relies
56
+ // on it: a lease held after the server released it just fails its next heartbeat and
57
+ // self-heals (see the send-back note below), whereas a lease dropped too early is
58
+ // silent and costs the agent its work.
59
+ const succeeded = !!o.result && !isToolError(o.result);
60
+ const id = succeeded && typeof o.args?.identifier === "string" ? o.args.identifier : undefined;
41
61
  if (id && o.toolName === "release_issue")
42
62
  leases.delete(id);
43
63
  // RTSC-321: moving to `review` (RTSC-257) hands the lease back server-side (the
@@ -49,7 +69,7 @@ export function applyObservation(leases, o) {
49
69
  // failed-heartbeat path instead.)
50
70
  if (id && o.toolName === "save_issue" && o.args?.status === "review")
51
71
  leases.delete(id);
52
- const closeId = terminalCloseId(o);
72
+ const closeId = succeeded ? terminalCloseId(o) : undefined;
53
73
  if (closeId)
54
74
  leases.delete(closeId);
55
75
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@retasc/cli",
3
- "version": "1.33.0",
4
- "description": "Retasc CLI \u2014 the issue tracker AI agents pull work from. Sign in with GitHub or Google, create projects, mint agent API keys, and wire your agent to the Retasc MCP server in one command.",
3
+ "version": "1.34.1",
4
+ "description": "Retasc CLI the issue tracker AI agents pull work from. Sign in with GitHub or Google, create projects, mint agent API keys, and wire your agent to the Retasc MCP server in one command.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "retasc": "dist/index.js"