@bussolabs/closeyourit-cli 0.11.0 → 0.12.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.
@@ -0,0 +1,16 @@
1
+ import { BaseCommand } from '../../base';
2
+ export default class TicketsEligibility extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ allow: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ auto: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ block: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
+ reason: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ };
15
+ run(): Promise<unknown>;
16
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_1 = require("../../base");
5
+ const output_1 = require("../../lib/output");
6
+ class TicketsEligibility extends base_1.BaseCommand {
7
+ // Human override of the agent-eligibility gate (backend gates `tickets.edit`). A ticket reaches the
8
+ // autonomous agents only when it is `allowed`; the automatic verdict is produced by the backend.
9
+ // A human decision is sticky: re-evaluation never overwrites it, `--auto` is how you release it.
10
+ static description = 'Allow or block a ticket for autonomous agents (requires tickets.edit)';
11
+ static examples = [
12
+ '<%= config.bin %> tickets eligibility DRFL-3 --project acme-api --allow',
13
+ '<%= config.bin %> tickets eligibility DRFL-3 --project acme-api --block --reason "touches production data"',
14
+ '<%= config.bin %> tickets eligibility DRFL-3 --project acme-api --auto',
15
+ ];
16
+ static args = {
17
+ id: core_1.Args.string({ description: 'Ticket id or code (e.g. DRFL-3)', required: true }),
18
+ };
19
+ static flags = {
20
+ ...base_1.projectFlag,
21
+ allow: core_1.Flags.boolean({ description: 'Let autonomous agents work this ticket', exclusive: ['block', 'auto'] }),
22
+ auto: core_1.Flags.boolean({ description: 'Drop the human decision and re-evaluate automatically', exclusive: ['allow', 'block'] }),
23
+ block: core_1.Flags.boolean({ description: 'Keep this ticket for a human', exclusive: ['allow', 'auto'] }),
24
+ reason: core_1.Flags.string({ description: 'Why (shown next to the verdict; ignored with --auto)' }),
25
+ };
26
+ async run() {
27
+ const { args, flags } = await this.parse(TicketsEligibility);
28
+ // One decision per call, and it must be explicit: defaulting would let a typo silently open the
29
+ // gate on a ticket someone meant to keep.
30
+ const decision = [
31
+ flags.allow ? 'allowed' : null,
32
+ flags.block ? 'blocked' : null,
33
+ flags.auto ? 'auto' : null,
34
+ ].find(Boolean);
35
+ if (!decision)
36
+ this.error('Pick one of --allow, --block or --auto.');
37
+ const projectId = await this.resolveProjectId(flags.project);
38
+ const res = await this.api.put(`/cli/v1/projects/${projectId}/tickets/${args.id}/eligibility`, { eligibility: decision, ...(flags.reason ? { reason: flags.reason } : {}) });
39
+ if (!this.jsonEnabled()) {
40
+ this.log(`Ticket ${args.id} agent eligibility set to ${decision}:`);
41
+ this.log((0, output_1.renderRecord)(res.data ?? {}));
42
+ }
43
+ return res;
44
+ }
45
+ }
46
+ exports.default = TicketsEligibility;
@@ -3,6 +3,7 @@ export default class TicketsList extends BaseCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static flags: {
6
+ 'agent-eligibility': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
6
7
  page: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
7
8
  project: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
8
9
  };
@@ -1,21 +1,44 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
3
4
  const base_1 = require("../../base");
4
5
  const output_1 = require("../../lib/output");
6
+ // Agent-eligibility gate: a ticket reaches the autonomous agents only when it is `allowed`.
7
+ // Rendered short so the column stays scannable next to CODE.
8
+ const AGENTS_MARK = {
9
+ allowed: 'yes',
10
+ blocked: 'no',
11
+ pending: '?',
12
+ };
5
13
  class TicketsList extends base_1.BaseCommand {
6
14
  static description = 'List tickets for a project';
7
- static examples = ['<%= config.bin %> tickets list --project acme-api', '<%= config.bin %> tickets list -p acme-api --json'];
8
- static flags = { ...base_1.projectFlag, ...base_1.pageFlag };
15
+ static examples = [
16
+ '<%= config.bin %> tickets list --project acme-api',
17
+ '<%= config.bin %> tickets list -p acme-api --agent-eligibility pending',
18
+ '<%= config.bin %> tickets list -p acme-api --json',
19
+ ];
20
+ static flags = {
21
+ ...base_1.projectFlag,
22
+ ...base_1.pageFlag,
23
+ 'agent-eligibility': core_1.Flags.string({
24
+ description: 'Filter by agent eligibility',
25
+ options: ['pending', 'allowed', 'blocked'],
26
+ }),
27
+ };
9
28
  async run() {
10
29
  const { flags } = await this.parse(TicketsList);
11
30
  const projectId = await this.resolveProjectId(flags.project);
12
- const res = await this.api.get(`/cli/v1/projects/${projectId}/tickets?page=${flags.page}`);
31
+ const query = new URLSearchParams({ page: String(flags.page) });
32
+ if (flags['agent-eligibility'])
33
+ query.set('agent_eligibility', flags['agent-eligibility']);
34
+ const res = await this.api.get(`/cli/v1/projects/${projectId}/tickets?${query.toString()}`);
13
35
  const tickets = res.data ?? [];
14
36
  if (!this.jsonEnabled()) {
15
- this.log((0, output_1.renderTable)(['CODE', 'TITLE', 'STATUS'], tickets.map((ticket) => [
37
+ this.log((0, output_1.renderTable)(['CODE', 'TITLE', 'STATUS', 'AGENTS'], tickets.map((ticket) => [
16
38
  String(ticket.code ?? ''),
17
39
  String(ticket.title ?? ''),
18
40
  (0, output_1.statusCell)(ticket.status, typeof ticket.status_color === 'string' ? ticket.status_color : undefined),
41
+ AGENTS_MARK[String(ticket.agent_eligibility ?? '')] ?? '',
19
42
  ])));
20
43
  }
21
44
  return res;
@@ -86,6 +86,11 @@ class TicketsShow extends base_1.BaseCommand {
86
86
  milestone: ticket.milestone,
87
87
  platforms: platforms || null,
88
88
  project_id: ticket.project_id,
89
+ // Agent-eligibility gate: whether the autonomous agents may work this ticket, and why.
90
+ // The reason is the part you act on — it is what tells you whether to override the verdict.
91
+ agent_eligibility: ticket.agent_eligibility,
92
+ agent_eligibility_source: ticket.agent_eligibility_source,
93
+ agent_eligibility_reason: ticket.agent_eligibility_reason,
89
94
  created_at: ticket.created_at,
90
95
  updated_at: ticket.updated_at,
91
96
  }));