@gaia-ai/addon-remote-drupal 0.11.1 → 0.11.2

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.
@@ -24,7 +24,6 @@ export declare class DrupalGaiaRemote implements GaiaRemote {
24
24
  fetchFinalizableRuns(id: string): Promise<FinalizableRun[]>;
25
25
  finalizeRun(uuid: string, log: string, metrics?: RunMetrics): Promise<void>;
26
26
  fetchUncleanedTickets(id: string): Promise<UncleanTicket[]>;
27
- closeTicket(uuid: string): Promise<void>;
28
27
  markTicketCleanedUp(uuid: string): Promise<void>;
29
28
  /**
30
29
  * UUID + absolute worktree path of the ticket's latest run (highest run id
package/dist/src/index.js CHANGED
@@ -2,16 +2,6 @@ import { toUnixSeconds } from '@gaia-ai/core';
2
2
  import { resolveAuth } from 'dropsh';
3
3
  import { createHttpClient, createJsonApiClient } from 'dropsh/plugin';
4
4
  const ACTIVE = ['claimed', 'running'];
5
- /**
6
- * Terminal ticket states — the reap work list's state branch (GAIA-243).
7
- *
8
- * Mirrors the server's `TypeWorkflows::isTerminal()`, which derives terminality
9
- * from `gaia_core.workflows.yml` (a state no transition leaves). Every ticket
10
- * workflow there currently ends in exactly these two. When a workflow gains a
11
- * terminal state, this is the list to extend — and the access handler needs no
12
- * change, since it asks the workflow definition directly.
13
- */
14
- const TERMINAL = ['done', 'cancelled'];
15
5
  /**
16
6
  * The process-identity attributes a registration carries, if any (GAIA-232).
17
7
  *
@@ -347,54 +337,47 @@ export class DrupalGaiaRemote {
347
337
  }); // NO state — the run is already done.
348
338
  }
349
339
  async fetchUncleanedTickets(id) {
350
- // Finished tickets whose worktree is not yet torn down (cleaned_up=0),
351
- // driven by the durable `cleaned_up` flag (GAIA-89) AND scoped to this
340
+ // Closed tickets whose worktree is not yet torn down, scoped to this
352
341
  // conductor (GAIA-121): only tickets assigned to `id` are loaded, so a
353
- // ticket owned by another conductor never reaches the reaper loop.
354
- // "Finished" = reached a TERMINAL state (`done` or `cancelled` GAIA-243)
355
- // OR already `closed`. A cancelled ticket keeps closed=0, since nothing
356
- // server-side closes a ticket on a transition, so it needs the state branch
357
- // to reach it at all. The collection builder has no OR across DIFFERENT
358
- // fields, so state-or-closed stays two AND-queries merged + de-duped by
359
- // uuid; whereIn covers the several states within one of them, at no extra
360
- // round-trip. The `conductor_id` relationship carries the assigned
361
- // conductor's `machine_id` the same nested filter the sibling reaper
362
- // queries (`fetchFinalizableRuns` etc.) use.
363
- const fields = ['branch_name', 'state', 'closed'];
364
- const done = await this.api
342
+ // ticket owned by another conductor never reaches the reaper loop. Since
343
+ // GAIA-451 the server closes every terminal ticket on its own save
344
+ // (GaiaTicket::preSave()), so this asks one question closed but not
345
+ // cleaned up with no workflow-state reasoning left in it. `cleaned_up`
346
+ // is nullable and an unwritten Drupal boolean is NULL, and `NULL = 0`
347
+ // matches nothing in SQL, so the NULL twin is a second query rather than a
348
+ // looser operator (GAIA-364 D1, absorbed here). The collection builder has
349
+ // no OR across DIFFERENT conditions on the same field, so the two stay
350
+ // separate AND-queries merged + de-duped by uuid. The `conductor_id`
351
+ // relationship carries the assigned conductor's `machine_id` the same
352
+ // nested filter the sibling reaper queries (`fetchFinalizableRuns` etc.)
353
+ // use.
354
+ const fields = ['branch_name'];
355
+ const uncleaned = await this.api
365
356
  .collection('gaia_ticket')
366
357
  .where('conductor_id.conductor_id', '=', id)
367
- .whereIn('state', TERMINAL)
358
+ .where('closed', '=', '1')
368
359
  .where('cleaned_up', '=', '0')
369
360
  .fields(fields)
370
361
  .page(100)
371
362
  .list();
372
- const closed = await this.api
363
+ const neverWritten = await this.api
373
364
  .collection('gaia_ticket')
374
365
  .where('conductor_id.conductor_id', '=', id)
375
366
  .where('closed', '=', '1')
376
- .where('cleaned_up', '=', '0')
367
+ .notExists('cleaned_up')
377
368
  .fields(fields)
378
369
  .page(100)
379
370
  .list();
380
371
  const byUuid = new Map();
381
- for (const r of [...done, ...closed]) {
372
+ for (const r of [...uncleaned, ...neverWritten]) {
382
373
  byUuid.set(r.id, r);
383
374
  }
384
375
  return Promise.all([...byUuid.values()].map(async (r) => ({
385
376
  ticketUuid: r.id,
386
377
  branchName: r.attr('branch_name') ?? '',
387
- state: r.attr('state') ?? '',
388
- closed: r.attr('closed') ?? false,
389
378
  ...(await this.latestRun(r.id)),
390
379
  })));
391
380
  }
392
- async closeTicket(uuid) {
393
- const t = Math.floor(Date.now() / 1000);
394
- await this.api.update('gaia_ticket', uuid, {
395
- attributes: { closed: true, closed_date: t },
396
- }); // NO state — the ticket is already done.
397
- }
398
381
  async markTicketCleanedUp(uuid) {
399
382
  await this.api.update('gaia_ticket', uuid, {
400
383
  attributes: { cleaned_up: true },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gaia-ai/addon-remote-drupal",
3
- "version": "0.11.1",
3
+ "version": "0.11.2",
4
4
  "description": "GAIA conductor remote addon: the Drupal/JSON:API control-plane remote.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -23,7 +23,7 @@
23
23
  "dropsh": "^0.6.1"
24
24
  },
25
25
  "peerDependencies": {
26
- "@gaia-ai/conductor": "^0.11.1",
27
- "@gaia-ai/core": "^0.11.1"
26
+ "@gaia-ai/conductor": "^0.11.2",
27
+ "@gaia-ai/core": "^0.11.2"
28
28
  }
29
29
  }