runline 0.17.0 → 0.18.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.
@@ -55,4 +55,43 @@ export function registerCycleActions(rl) {
55
55
  return data.cycleUpdate?.cycle;
56
56
  },
57
57
  });
58
+ // Archive is the only way to remove a single cycle: Linear has no
59
+ // per-cycle delete mutation. Issues are unlinked from the cycle first,
60
+ // they are not archived with it.
61
+ rl.registerAction("cycle.archive", {
62
+ access: "write",
63
+ description: "Archive one cycle. Issues assigned to it are unlinked from the cycle first, not archived. This is the per-cycle removal; Linear has no single-cycle delete.",
64
+ inputSchema: t.Object({
65
+ id: t.String({ description: "The identifier of the cycle to archive" }),
66
+ }),
67
+ async execute(input, ctx) {
68
+ requireUnscoped(ctx, "cycles.*");
69
+ const { id } = input;
70
+ const data = await gql(key(ctx), `mutation($id: String!) { cycleArchive(id: $id) { success } }`, { id });
71
+ return data.cycleArchive;
72
+ },
73
+ });
74
+ // Deliberately NOT named cycle.delete.
75
+ //
76
+ // Linear's teamCyclesDelete takes a *team* id and wipes every cycle that
77
+ // team has, disabling the cycles feature entirely. Exposing it as
78
+ // `cycle.delete({ id })` would read as "delete this one cycle" and let an
79
+ // agent destroy a team's whole cycle history by analogy with every other
80
+ // `*.delete` action in this plugin. The name and the parameter both say
81
+ // team, and the description leads with the blast radius.
82
+ rl.registerAction("team.cyclesDeleteAll", {
83
+ access: "write",
84
+ description: "DESTRUCTIVE: delete ALL cycle data for a team and disable the cycles feature. Removes every cycle and its issue associations, not just one. To remove a single cycle use cycle.archive.",
85
+ inputSchema: t.Object({
86
+ teamId: t.String({
87
+ description: "The identifier of the TEAM whose cycles will all be deleted",
88
+ }),
89
+ }),
90
+ async execute(input, ctx) {
91
+ requireUnscoped(ctx, "cycles.*");
92
+ const { teamId } = input;
93
+ const data = await gql(key(ctx), `mutation($id: String!) { teamCyclesDelete(id: $id) { success } }`, { id: teamId });
94
+ return data.teamCyclesDelete;
95
+ },
96
+ });
58
97
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runline",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "Code mode for agents — turn any API or command into a callable action",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",