@allocator-one/harness-cli 1.15.1 → 1.16.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.
@@ -14,6 +14,8 @@ import {
14
14
  MCP_SURFACE,
15
15
  OUTCOME_MAX_CHARACTERS,
16
16
  PLAN_EXECUTORS,
17
+ PLAN_LIST_MAX_LIMIT,
18
+ PLAN_STATUSES,
17
19
  RELATION_CREATE_TYPES,
18
20
  RELATION_UPDATE_TYPES,
19
21
  STEER_MAX_CHARACTERS,
@@ -61,6 +63,7 @@ import {
61
63
  planCreate,
62
64
  planEdit,
63
65
  planHold,
66
+ planList,
64
67
  planRelease,
65
68
  planShow,
66
69
  prepareRun,
@@ -96,7 +99,7 @@ import {
96
99
  upload,
97
100
  userList,
98
101
  workflowStates
99
- } from "./chunk-L2OWOZ4N.js";
102
+ } from "./chunk-GVTZKAXC.js";
100
103
  import {
101
104
  CLI_VERSION,
102
105
  invokedName,
@@ -115,7 +118,7 @@ function context() {
115
118
  if (resolved.kind === "error") throw new NeedsLoginError(resolved.message);
116
119
  if (resolved.kind === "needs-login") {
117
120
  throw new NeedsLoginError(
118
- `Not signed in to ${resolved.baseUrl}. Run \`${invokedName()} login\` in a terminal (or set HARNESS_API_TOKEN for headless use) \u2014 the MCP server never opens a browser itself.`
121
+ `Not signed in to ${resolved.baseUrl}${resolved.org === void 0 ? "" : ` for organization ${resolved.org}`}. Run \`${invokedName()} login\` in a terminal (or set HARNESS_API_TOKEN for headless use) \u2014 the MCP server never opens a browser itself.`
119
122
  );
120
123
  }
121
124
  return { client: new Client(resolved.config), config: resolved.config };
@@ -196,9 +199,11 @@ var planDocument = z.object({
196
199
  parent: z.string().optional().describe("an existing issue to file the root under, e.g. IO-12"),
197
200
  retry_budget: z.number().int().min(0).optional().describe("retries per failed Operator step (default 2)"),
198
201
  spend_budget_cents: z.number().int().min(0).nullable().optional().describe("needed to release a plan with Operator steps"),
199
- steps: z.array(planStep).min(1).describe("at most 99 steps besides the root")
202
+ steps: z.array(planStep).min(1).describe(
203
+ "with the root, at most the organization's max plan steps (default 1000, at most 2000), and at most 100 Operator steps"
204
+ )
200
205
  }).passthrough();
201
- var planId = z.string().uuid().describe("plan UUID, from plan_create");
206
+ var planId = z.string().describe("the plan's UUID, or its root issue's identifier (e.g. FR-1, any casing): plan_list or issue_show's plan.root");
202
207
  var planStepEdit = z.object({
203
208
  step: z.string().optional().describe("the step's key; give this or issue"),
204
209
  issue: z.string().optional().describe("the step's issue identifier; give this or step"),
@@ -406,7 +411,7 @@ var TOOLS = [
406
411
  },
407
412
  {
408
413
  name: "issue_show",
409
- description: "Full issue detail: fields, relations, children, comments. blockers gives each unresolved blocker's state_type and archived flag: only a completed blocker resolves, so a cancelled or archived one still blocks. waiting_on_condition and conditions say which wait conditions (not_before, gate, event) still hold it; tick a gate with gate_set. images=true downloads attached images to the local cache and includes their paths as local_images.",
414
+ description: "Full issue detail: fields, relations, children, comments. blockers gives each unresolved blocker's state_type and archived flag: only a completed blocker resolves, so a cancelled or archived one still blocks. waiting_on_condition and conditions say which wait conditions (not_before, gate, event) still hold it; tick a gate with gate_set. plan is the plan governing the issue (the nearest rooted at it or an ancestor), or null: its id, root identifier (which the plan tools take), status, held, the revision number it runs, in_revision (whether that revision lists the issue: an Operator step outside it waits for plan_release, a person's step does not) and the issue's executor. images=true downloads attached images to the local cache and includes their paths as local_images.",
410
415
  readOnly: true,
411
416
  shape: { id: identifier, images: z.boolean().optional() },
412
417
  handler: (ctx, args) => show(ctx, args["id"], { images: args["images"] === true })
@@ -480,7 +485,7 @@ var TOOLS = [
480
485
  },
481
486
  {
482
487
  name: "issue_claim",
483
- description: "Atomically claim an issue: assigns it and moves it to the team's first started state. A conflict names its reason: someone else holds it, or it is not claimable (e.g. agent_step, waiting_on_condition).",
488
+ description: "Atomically claim an issue: assigns it and moves it to the team's first started state. A conflict names its reason: someone else holds it, or it is not claimable (e.g. agent_step, waiting_on_condition). A refusal that comes from a plan (agent_step, plan_not_released, not_in_plan_revision, edited_since_release) names the plan by its root: the release that fixes it when it is the one plan governing the issue (plan_release takes the root), the nearest plan to look at when several do. A person never claims an agent_step, an Operator step.",
484
489
  readOnly: false,
485
490
  shape: { id: identifier },
486
491
  handler: (ctx, args) => update(ctx, args["id"], { claim: true })
@@ -912,9 +917,20 @@ var TOOLS = [
912
917
  handler: (ctx) => stats(ctx)
913
918
  },
914
919
  // ── Plans and gates ──
920
+ {
921
+ name: "plan_list",
922
+ description: `A team's plans, newest first: each plan's id, root (its root issue's identifier, which the other plan tools take in place of the id), title, status, held, revision (null before its first release), released_at and inserted_at. One list of at most ${PLAN_LIST_MAX_LIMIT}, no pages: a second text item says when it came back full. issue_show's plan names the plan an issue belongs to.`,
923
+ readOnly: true,
924
+ shape: {
925
+ team: z.string().optional().describe("team key whose issues root the plans; defaults to HARNESS_TEAM"),
926
+ status: z.enum(PLAN_STATUSES).optional().describe("only plans in this status"),
927
+ limit: z.number().int().min(1).max(PLAN_LIST_MAX_LIMIT).optional().describe("maximum plans (default 50)")
928
+ },
929
+ handler: (ctx, args) => planList(ctx, { team: args["team"], status: args["status"], limit: args["limit"] })
930
+ },
915
931
  {
916
932
  name: "plan_create",
917
- description: "Create a plan: a root issue and up to 99 steps, created in one transaction or not at all, and held until a person releases it (plan_release). Steps refer to each other by key: parent (containment) and blocked_by (dependencies). executor operator files a step in the organization's Operator team, where only the plan driver claims it; a person's step goes to its team (or the plan's). conditions are wait conditions (not_before, gate, event); a gate may carry a key (gate: <key> is shorthand) and an owner, who alone ticks it. An invalid plan writes nothing and the error lists every violation by step key. Reuse idempotency_key when retrying. Once released, the changes an Operator step proposes need a person's approval in the app, as plan_release says.",
933
+ description: "Create a plan: a root issue and its steps, created in one transaction or not at all, and held until a person releases it (plan_release). Steps refer to each other by key: parent (containment) and blocked_by (dependencies). executor operator files a step in the organization's Operator team, where only the plan driver claims it; a person's step goes to its team (or the plan's). conditions are wait conditions (not_before, gate, event); a gate may carry a key (gate: <key> is shorthand) and an owner, who alone ticks it. An invalid plan writes nothing and the error lists every violation by step key; too_many_steps says which cap the plan is over: the organization's max plan steps (default 1000, which a Harness admin raises in Harness settings \u2192 Plans, up to 2000) or the fixed 100 Operator steps of the delegated grant. Reuse idempotency_key when retrying. Once released, the changes an Operator step proposes need a person's approval in the app, as plan_release says.",
918
934
  readOnly: false,
919
935
  shape: {
920
936
  team: z.string().optional().describe("team key for the root and people's steps; defaults to HARNESS_TEAM"),
@@ -925,14 +941,14 @@ var TOOLS = [
925
941
  },
926
942
  {
927
943
  name: "plan_show",
928
- description: "A plan's status, budgets, current revision and spend estimate, and its whole tree root first: each step's key, executor, parent, state, ready flag, held flag (edited since release), in_revision, wait conditions (a gate's key and owner) and waiting_for (each open gate's owner and holders, the people who can tick it: [] when nobody can, null when unowned or not known), plus the blocks edges between steps.",
944
+ description: "A plan, by its id or its root issue's identifier: status, budgets, current revision and spend estimate, and its whole tree root first: each step's key, executor, parent, state, ready flag, held flag (changed since the release: only an Operator step waits for the next release, a person's stays ready), in_revision, wait conditions (a gate's key and owner) and waiting_for (each open gate's owner and holders, the people who can tick it: [] when nobody can, null when unowned or not known), plus the blocks edges between steps.",
929
945
  readOnly: true,
930
946
  shape: { id: planId },
931
947
  handler: (ctx, args) => planShow(ctx, args["id"])
932
948
  },
933
949
  {
934
950
  name: "plan_edit",
935
- description: "Change step executors and keys (each step named by its key or issue identifier) and the plan's budgets. Editing a released step holds it until the plan is released again; a budget edit needs the plan held. Descriptions, parents and edges are edited with issue_update and relation_add/relation_rm; conditions are set at plan_create, and gate_set ticks a gate. Once released, the changes an Operator step proposes need a person's approval in the app, as plan_release says.",
951
+ description: "Change step executors and keys (each step named by its key or issue identifier) and the plan's budgets. Editing a released Operator step, or handing one to a person, holds it until the plan is released again; a person's step stays workable, and the next release takes the change in. A budget edit needs the plan held. Descriptions, parents and edges are edited with issue_update and relation_add/relation_rm; conditions are set at plan_create, and gate_set ticks a gate. Once released, the changes an Operator step proposes need a person's approval in the app, as plan_release says.",
936
952
  readOnly: false,
937
953
  shape: {
938
954
  id: planId,
@@ -947,7 +963,7 @@ var TOOLS = [
947
963
  },
948
964
  {
949
965
  name: "plan_release",
950
- description: "Release a held plan (or one that needs attention) as the caller: freezes its next revision and lets its ready steps run. A plan with Operator steps needs a spend budget and the caller's right to run Operator; collaborators join its plan room. Each Operator step runs as a job (jobs_list names its plan_step), and the changes a job proposes need a person's approval in the app: give them the job's approval_url. No tool approves.",
966
+ description: "Release a held plan (or one that needs attention) as the caller: freezes its next revision, which takes in the steps added or edited since the last one, and lets its ready steps run. A plan over a step cap is refused with too_many_steps, naming the cap as plan_create does. A plan with Operator steps needs a spend budget and the caller's right to run Operator; collaborators join its plan room. Each Operator step runs as a job (jobs_list names its plan_step), and the changes a job proposes need a person's approval in the app: give them the job's approval_url. No tool approves.",
951
967
  readOnly: false,
952
968
  shape: {
953
969
  id: planId,
@@ -970,7 +986,7 @@ var TOOLS = [
970
986
  },
971
987
  {
972
988
  name: "gate_set",
973
- description: "Satisfy (satisfied true) or un-satisfy (false) a gate wait condition on an issue, found by its key, label or condition id (condition_list and issue_show list conditions). Needs staff standing in the organization or a place in its plan's room; only an owned gate's owner ticks it, and its owner or staff untick it. Anyone else gets a 403 naming the owner. An outside expert's pxc_ credential ticks the gates it owns on a step assigned to it (assignment_list); any other step is 404. An Operator-only login (operator-cli) is refused here, as on every tool outside Operator's, even for a person in the plan's room.",
989
+ description: "Satisfy (satisfied true) or un-satisfy (false) a gate wait condition on an issue, found by its key, label or condition id (condition_list and issue_show list conditions). A condition id writes directly, without a staff-only conditions lookup; a key or label needs that lookup. Needs staff standing in the organization or a place in its plan's room; only an owned gate's owner ticks it, and its owner or staff untick it. Anyone else gets a 403 naming the owner. An outside expert's pxc_ credential ticks the gates it owns on a step assigned to it (assignment_list); any other step is 404. An Operator-only login (operator-cli) is refused here, as on every tool outside Operator's, even for a person in the plan's room.",
974
990
  readOnly: false,
975
991
  shape: {
976
992
  issue: identifier,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allocator-one/harness-cli",
3
- "version": "1.15.1",
3
+ "version": "1.16.0",
4
4
  "description": "CLI and MCP server for Harness, allocator.one's issue tracker",
5
5
  "type": "module",
6
6
  "license": "MIT",