@gaia-ai/conductor 0.11.0 → 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.
@@ -71,23 +71,25 @@ export declare class Conductor {
71
71
  */
72
72
  private finalizeDoneRuns;
73
73
  /**
74
- * Reconcile finished tickets against their herdr worktrees and tear down any
74
+ * Reconcile closed tickets against their herdr worktrees and tear down any
75
75
  * whose workspace still lingers (GAIA-89). Driven by the durable `cleaned_up`
76
- * flag via {@link GaiaRemote.fetchUncleanedTickets}: every ticket that is
77
- * finished (state=done OR closed) but not yet cleaned. The SAME reconciliation
78
- * runs on every tick AND standalone as `gaia conductor reap`, and the query is
76
+ * flag via {@link GaiaRemote.fetchUncleanedTickets}: every ticket the server
77
+ * has already closed but not yet cleaned. The SAME reconciliation runs on
78
+ * every tick AND standalone as `gaia conductor reap`, and the query is
79
79
  * scoped to THIS conductor (GAIA-121) — so it catches the orphans a
80
80
  * live-tick-only path structurally cannot (the conductor was down when the
81
- * ticket hit `done`, or crashed mid-cleanup) for its OWN tickets. A foreign
81
+ * ticket closed, or crashed mid-cleanup) for its OWN tickets. A foreign
82
82
  * (non-gaia) worktree has no gaia ticket, so it is never on the work list; a
83
83
  * ticket assigned to another conductor is filtered out at the query — both are
84
84
  * left untouched with no host enumeration.
85
85
  *
86
- * Per ticket, close is DECOUPLED from teardown (no withholding): a done ticket
87
- * is closed at once as a lifecycle step, independent of whether its worktree
88
- * teardown then succeeds. `cleaned_up` is withheld unless the teardown is
89
- * ACCOUNTED FOR (GAIA-141 RC-2), which `removeWorktree` reports as one of
90
- * three outcomes (GAIA-293):
86
+ * The conductor is structurally UNABLE to close a ticket (GAIA-451): closing
87
+ * is a server-side projection of terminality written by
88
+ * `GaiaTicket::preSave()` on any save of a terminal, unclosed ticket, so it
89
+ * holds for every write path and cannot be withheld by a teardown hiccup —
90
+ * the reap reasons about `cleaned_up` alone. `cleaned_up` is withheld unless
91
+ * the teardown is ACCOUNTED FOR (GAIA-141 RC-2), which `removeWorktree`
92
+ * reports as one of three outcomes (GAIA-293):
91
93
  * - `removed` — gone because this host tore it down → flag cleaned;
92
94
  * - `already_absent` — nothing was there to tear down. A FINISHED teardown,
93
95
  * not a failure: it is recorded in this log AND on the run record, then
@@ -330,23 +330,25 @@ export class Conductor {
330
330
  }
331
331
  }
332
332
  /**
333
- * Reconcile finished tickets against their herdr worktrees and tear down any
333
+ * Reconcile closed tickets against their herdr worktrees and tear down any
334
334
  * whose workspace still lingers (GAIA-89). Driven by the durable `cleaned_up`
335
- * flag via {@link GaiaRemote.fetchUncleanedTickets}: every ticket that is
336
- * finished (state=done OR closed) but not yet cleaned. The SAME reconciliation
337
- * runs on every tick AND standalone as `gaia conductor reap`, and the query is
335
+ * flag via {@link GaiaRemote.fetchUncleanedTickets}: every ticket the server
336
+ * has already closed but not yet cleaned. The SAME reconciliation runs on
337
+ * every tick AND standalone as `gaia conductor reap`, and the query is
338
338
  * scoped to THIS conductor (GAIA-121) — so it catches the orphans a
339
339
  * live-tick-only path structurally cannot (the conductor was down when the
340
- * ticket hit `done`, or crashed mid-cleanup) for its OWN tickets. A foreign
340
+ * ticket closed, or crashed mid-cleanup) for its OWN tickets. A foreign
341
341
  * (non-gaia) worktree has no gaia ticket, so it is never on the work list; a
342
342
  * ticket assigned to another conductor is filtered out at the query — both are
343
343
  * left untouched with no host enumeration.
344
344
  *
345
- * Per ticket, close is DECOUPLED from teardown (no withholding): a done ticket
346
- * is closed at once as a lifecycle step, independent of whether its worktree
347
- * teardown then succeeds. `cleaned_up` is withheld unless the teardown is
348
- * ACCOUNTED FOR (GAIA-141 RC-2), which `removeWorktree` reports as one of
349
- * three outcomes (GAIA-293):
345
+ * The conductor is structurally UNABLE to close a ticket (GAIA-451): closing
346
+ * is a server-side projection of terminality written by
347
+ * `GaiaTicket::preSave()` on any save of a terminal, unclosed ticket, so it
348
+ * holds for every write path and cannot be withheld by a teardown hiccup —
349
+ * the reap reasons about `cleaned_up` alone. `cleaned_up` is withheld unless
350
+ * the teardown is ACCOUNTED FOR (GAIA-141 RC-2), which `removeWorktree`
351
+ * reports as one of three outcomes (GAIA-293):
350
352
  * - `removed` — gone because this host tore it down → flag cleaned;
351
353
  * - `already_absent` — nothing was there to tear down. A FINISHED teardown,
352
354
  * not a failure: it is recorded in this log AND on the run record, then
@@ -371,13 +373,6 @@ export class Conductor {
371
373
  const tickets = await this.remote.fetchUncleanedTickets(this.id);
372
374
  for (const t of tickets) {
373
375
  try {
374
- // Lifecycle: close a done+unclosed ticket at once, decoupled from the
375
- // infra teardown below — a done ticket whose conductor was down was
376
- // never closed, and withholding the close on a teardown hiccup would
377
- // make a finished ticket look unfinished (the pre-GAIA-89 defect).
378
- if (t.state === 'done' && !t.closed) {
379
- await this.remote.closeTicket(t.ticketUuid);
380
- }
381
376
  // Infra teardown. The `after_done` hook runs in the worktree regardless
382
377
  // of executor kind (a non-persistent gitWorkspace still has an on-disk
383
378
  // worktree); only the workspace removal is gated on the persistent
@@ -116,12 +116,14 @@ export interface RunMetrics {
116
116
  user_prompt_words: number;
117
117
  }
118
118
  /**
119
- * A finished ticket whose worktree has not yet been torn down — the
119
+ * A closed ticket whose worktree has not yet been torn down — the
120
120
  * conductor's teardown work list, driven by the durable `cleaned_up` flag
121
- * (GAIA-89). "Finished" = reached `done` OR already `closed`; `cleaned_up=0`
122
- * means the herdr worktree still needs reclaiming. The reconciliation is NOT
123
- * scoped to a conductor's machine_id, so it also surfaces tickets whose
124
- * conductor was down at `done` or whose `conductor_id` was reassigned.
121
+ * (GAIA-89). Since GAIA-451 the server closes every terminal ticket on its own
122
+ * save, so "finished" collapses to `closed = 1`; `cleaned_up=0` (or never
123
+ * written at all) means the herdr worktree still needs reclaiming. The
124
+ * reconciliation is NOT scoped to a conductor's machine_id, so it also
125
+ * surfaces tickets whose conductor was down at close or whose `conductor_id`
126
+ * was reassigned.
125
127
  */
126
128
  export interface UncleanTicket {
127
129
  ticketUuid: string;
@@ -132,10 +134,6 @@ export interface UncleanTicket {
132
134
  * `worktree_path`), or '' when unresolved. The cwd the teardown runs in.
133
135
  */
134
136
  worktreePath: string;
135
- /** Workflow state (e.g. `coding`, `done`). */
136
- state: string;
137
- /** Whether the ticket's lifecycle has already been closed out. */
138
- closed: boolean;
139
137
  /**
140
138
  * UUID of the ticket's latest run — the one {@link worktreePath} came from —
141
139
  * or '' when the ticket has no run with a path. The record teardown notes are
@@ -215,22 +213,19 @@ export interface GaiaRemote {
215
213
  */
216
214
  finalizeRun(uuid: string, log: string, metrics?: RunMetrics): Promise<void>;
217
215
  /**
218
- * Finished tickets (state=done OR closed) whose worktree is not yet torn
219
- * down (cleaned_up=0) — the conductor's teardown work list (GAIA-89). Driven
220
- * by the durable `cleaned_up` flag AND scoped to the reaping conductor
221
- * (GAIA-121): only tickets assigned to `conductorId` are loaded, so every
222
- * ticket on the list is unambiguously this conductor's a missing worktree
223
- * means "already torn down on this host", not "belongs to another host". The
224
- * same query backs the live tick and the standalone `gaia conductor reap`.
225
- * Empty once every finished ticket this conductor owns is cleaned.
216
+ * Closed tickets (closed=1) whose worktree is not yet torn down
217
+ * (cleaned_up=0, or never written at all) — the conductor's teardown work
218
+ * list (GAIA-89). Since GAIA-451 the server closes every terminal ticket on
219
+ * its own save, so this asks one question closed but not cleaned up —
220
+ * with no workflow-state reasoning left in it. Driven by the durable
221
+ * `cleaned_up` flag AND scoped to the reaping conductor (GAIA-121): only
222
+ * tickets assigned to `conductorId` are loaded, so every ticket on the list
223
+ * is unambiguously this conductor's a missing worktree means "already torn
224
+ * down on this host", not "belongs to another host". The same query backs
225
+ * the live tick and the standalone `gaia conductor reap`. Empty once every
226
+ * closed ticket this conductor owns is cleaned.
226
227
  */
227
228
  fetchUncleanedTickets(conductorId: string): Promise<UncleanTicket[]>;
228
- /**
229
- * Close a ticket: set closed=true + closed_date. Ticket-lifecycle only, and
230
- * decoupled from teardown — a done ticket is closed even if its worktree
231
- * teardown later fails. No state change (the ticket is already done).
232
- */
233
- closeTicket(uuid: string): Promise<void>;
234
229
  /**
235
230
  * Mark a ticket's worktree torn down: set cleaned_up=true so it drops off the
236
231
  * {@link fetchUncleanedTickets} work list. Written ONLY after a verified
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gaia-ai/conductor",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
4
4
  "description": "GAIA conductor engine + CLI: registers, claims tickets via JSON:API, dispatches agents.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,7 +28,7 @@
28
28
  "directory": "gaia-cli/conductor"
29
29
  },
30
30
  "dependencies": {
31
- "@gaia-ai/core": "^0.11.0",
31
+ "@gaia-ai/core": "^0.11.2",
32
32
  "@dropsh/plugin-oauth2": "^0.6.1",
33
33
  "@dropsh/plugin-jsonapi-schema": "^0.6.1",
34
34
  "commander": "^12.1.0",