@songsid/agend 2.3.2-beta.13 → 2.3.2-beta.15

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.
Files changed (105) hide show
  1. package/dist/backend/codex-session-lookup.d.ts +15 -0
  2. package/dist/backend/codex-session-lookup.js +58 -0
  3. package/dist/backend/codex-session-lookup.js.map +1 -1
  4. package/dist/backend/codex.js +15 -4
  5. package/dist/backend/codex.js.map +1 -1
  6. package/dist/backend/kiro-classic-archive.d.ts +5 -0
  7. package/dist/backend/kiro-classic-archive.js +187 -9
  8. package/dist/backend/kiro-classic-archive.js.map +1 -1
  9. package/dist/backend/kiro-classic-links.d.ts +24 -0
  10. package/dist/backend/kiro-classic-links.js +135 -0
  11. package/dist/backend/kiro-classic-links.js.map +1 -0
  12. package/dist/backend/kiro-identity.d.ts +20 -3
  13. package/dist/backend/kiro-identity.js +26 -39
  14. package/dist/backend/kiro-identity.js.map +1 -1
  15. package/dist/backend/kiro-reconcile-store.d.ts +27 -0
  16. package/dist/backend/kiro-reconcile-store.js +344 -0
  17. package/dist/backend/kiro-reconcile-store.js.map +1 -0
  18. package/dist/backend/kiro-v2-store-worker.js +17 -3
  19. package/dist/backend/kiro-v2-store-worker.js.map +1 -1
  20. package/dist/backend/kiro-v2-store.d.ts +23 -1
  21. package/dist/backend/kiro-v2-store.js +22 -12
  22. package/dist/backend/kiro-v2-store.js.map +1 -1
  23. package/dist/backend/kiro.d.ts +4 -0
  24. package/dist/backend/kiro.js +25 -3
  25. package/dist/backend/kiro.js.map +1 -1
  26. package/dist/channel/mcp-tools.js +3 -1
  27. package/dist/channel/mcp-tools.js.map +1 -1
  28. package/dist/cli.js +17 -4
  29. package/dist/cli.js.map +1 -1
  30. package/dist/fleet-manager.d.ts +9 -1
  31. package/dist/fleet-manager.js +100 -11
  32. package/dist/fleet-manager.js.map +1 -1
  33. package/dist/general-instance.d.ts +24 -0
  34. package/dist/general-instance.js +53 -0
  35. package/dist/general-instance.js.map +1 -1
  36. package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +2 -0
  37. package/dist/general-knowledge/skills/web-appearance/SKILL.md +2 -0
  38. package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +6 -4
  39. package/dist/general-knowledge/skills/web-dashboard/SKILL.md +6 -4
  40. package/dist/kiro-migrate.d.ts +4 -3
  41. package/dist/kiro-migrate.js +13 -8
  42. package/dist/kiro-migrate.js.map +1 -1
  43. package/dist/kiro-reconcile.d.ts +21 -0
  44. package/dist/kiro-reconcile.js +80 -0
  45. package/dist/kiro-reconcile.js.map +1 -0
  46. package/dist/kiro-tui-forensic.d.ts +7 -0
  47. package/dist/kiro-tui-forensic.js +17 -3
  48. package/dist/kiro-tui-forensic.js.map +1 -1
  49. package/dist/locale.js +24 -0
  50. package/dist/locale.js.map +1 -1
  51. package/dist/log-service.js +1 -1
  52. package/dist/log-service.js.map +1 -1
  53. package/dist/office-share-page.d.ts +3 -1
  54. package/dist/office-share-page.js +7 -2
  55. package/dist/office-share-page.js.map +1 -1
  56. package/dist/office-share-service.d.ts +4 -3
  57. package/dist/office-share-service.js +6 -6
  58. package/dist/office-share-service.js.map +1 -1
  59. package/dist/office-share.d.ts +17 -6
  60. package/dist/office-share.js +28 -11
  61. package/dist/office-share.js.map +1 -1
  62. package/dist/outbound-handlers.js +20 -1
  63. package/dist/outbound-handlers.js.map +1 -1
  64. package/dist/outbound-schemas.d.ts +6 -0
  65. package/dist/outbound-schemas.js +6 -0
  66. package/dist/outbound-schemas.js.map +1 -1
  67. package/dist/quickstart-api.d.ts +25 -1
  68. package/dist/quickstart-api.js +53 -6
  69. package/dist/quickstart-api.js.map +1 -1
  70. package/dist/service-installer.d.ts +13 -0
  71. package/dist/service-installer.js +15 -0
  72. package/dist/service-installer.js.map +1 -1
  73. package/dist/service-owner.d.ts +25 -0
  74. package/dist/service-owner.js +43 -2
  75. package/dist/service-owner.js.map +1 -1
  76. package/dist/setup-form.js +17 -3
  77. package/dist/setup-form.js.map +1 -1
  78. package/dist/setup-i18n.js +2 -0
  79. package/dist/setup-i18n.js.map +1 -1
  80. package/dist/tool-permissions.js +1 -0
  81. package/dist/tool-permissions.js.map +1 -1
  82. package/dist/ui/fleet-office-layout.js +14 -6
  83. package/dist/ui/fleet-office-pack.d.ts +4 -0
  84. package/dist/ui/fleet-office-pack.js +15 -5
  85. package/dist/ui/fleet-office-store.js +18 -3
  86. package/dist/ui/fleet-office-view.js +8 -0
  87. package/dist/ui/fleet-office-zones.js +10 -2
  88. package/dist/ui/fleet-office.js +36 -4
  89. package/dist/ui/office-share-dialog.js +31 -7
  90. package/dist/ui/panel-log.js +2 -2
  91. package/dist/ui/settings-strings.js +2 -0
  92. package/dist/ui/settings-wizard.js +15 -4
  93. package/dist/ui/shared/app.css +6 -0
  94. package/dist/ui/shared/setup-host-text.js +2 -0
  95. package/dist/web-api.js +74 -4
  96. package/dist/web-api.js.map +1 -1
  97. package/dist/web-office-pack-tools.d.ts +10 -1
  98. package/dist/web-office-pack-tools.js +36 -5
  99. package/dist/web-office-pack-tools.js.map +1 -1
  100. package/dist/web-office-skins.js +6 -0
  101. package/dist/web-office-skins.js.map +1 -1
  102. package/dist/web-office-store.d.ts +22 -3
  103. package/dist/web-office-store.js +44 -8
  104. package/dist/web-office-store.js.map +1 -1
  105. package/package.json +1 -1
@@ -464,6 +464,7 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
464
464
  private pendingNonceButtons;
465
465
  /** #2598 B2: the kiro moves waiting on a fleet admin's Confirm in General, by prompt nonce. */
466
466
  private pendingKiroMigrations;
467
+ private pendingKiroReconciliations;
467
468
  private kiroMigrationRuns;
468
469
  /** #1386 "Needs you": the list, its live chat messages and Acknowledge. Started with the fleet (finishStartup). */
469
470
  private needsYou;
@@ -827,6 +828,13 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
827
828
  }>;
828
829
  /** A fleet admin's Confirm or Cancel on a kiro move. Any fleet admin (the default nonce authorization), in General. */
829
830
  private handleKiroMigrateCallback;
831
+ private kiroReconcileDeps;
832
+ requestKiroReconciliation(name: string, keep: string, archive: string, rollbackReceipt?: string): Promise<{
833
+ ok: boolean;
834
+ text?: string;
835
+ error?: string;
836
+ }>;
837
+ private handleKiroReconcileCallback;
830
838
  private handleSettingsChangeCallback;
831
839
  startSettingsConfirmationControl(): Promise<void>;
832
840
  private get webToken();
@@ -1476,7 +1484,7 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1476
1484
  */
1477
1485
  resumePaused?: boolean,
1478
1486
  /** Phase 2a: the caller's transition, for a start made from inside a restart or wake. */
1479
- transition?: TransitionHandle, execution?: SettingsExecution): Promise<void>;
1487
+ transition?: TransitionHandle, execution?: SettingsExecution, kiroMigration?: symbol): Promise<void>;
1480
1488
  /** A boot's observation cannot settle a replacement boot or a newer attempt of the same instance. */
1481
1489
  private trackStartupInstance;
1482
1490
  private publishStartupStatus;
@@ -1,5 +1,5 @@
1
1
  import { getCachedKiroCliCompatibility, kiroV1DbPath, kiroV2SessionsDir } from "./backend/kiro.js";
2
- import { listKiroV1Sessions } from "./backend/kiro-identity.js";
2
+ import { listKiroV1Sessions, readKiroClassicLinks } from "./backend/kiro-identity.js";
3
3
  import { readKiroV1SavedModel } from "./backend/kiro-retired-model.js";
4
4
  import { sharedKiroV2StoreLane } from "./backend/kiro-v2-store.js";
5
5
  import { SEPARATE_FEATURE_KEYS, hasLegacyOffice, normalizeOfficeStorage } from "./dashboard-permissions.js";
@@ -28,7 +28,7 @@ import { PUBLIC_PREVIEW_FRAME_SRC, PUBLIC_PREVIEW_TUNNEL_DIR, PublicPreview, pub
28
28
  import { CloudflaredProvider } from "./tunnel/cloudflared.js";
29
29
  import { ensureCloudflared } from "./tunnel/cloudflared-install.js";
30
30
  import { OFFICE_SHARE_TUNNEL_DIR, OfficeShareService } from "./office-share-service.js";
31
- import { ALL_OFFICES } from "./office-share.js";
31
+ import { ALL_OFFICES, WHOLE_FLEET } from "./office-share.js";
32
32
  import { TunnelPurposeLane } from "./tunnel/purpose-lane.js";
33
33
  import { ManagedTunnel } from "./tunnel/manager.js";
34
34
  import { withinBudget } from "./monotonic-budget.js";
@@ -47,6 +47,7 @@ import { join, dirname, basename, delimiter, isAbsolute, relative, resolve as re
47
47
  import { fileURLToPath } from "node:url";
48
48
  import { isDeepStrictEqual } from "node:util";
49
49
  import { getAgendHome, ensureWorkspaceGit } from "./paths.js";
50
+ import { planKiroReconciliation, applyKiroReconciliation, kiroReconciliationPrompt } from "./kiro-reconcile.js";
50
51
  import { applyKiroMigration, kiroMigrationPrompt, planKiroMigration } from "./kiro-migrate.js";
51
52
  import { fleetLabel } from "./fleet-label.js";
52
53
  import { beginFullRestartProgress as persistFullRestartProgress, beginUpdateProgress as persistUpdateProgress, clearUpdateMarker, isUpdateInProgress, readUpdateProgress, sameUpdateMarker, setUpdateProgressStage, updateMarkerIdentity, updateProgressOperation, updateReceiptOf, } from "./update-marker.js";
@@ -254,7 +255,7 @@ import { manualCleanupMessage, reapStaleTunnel } from "./tunnel/lease.js";
254
255
  import { buildToolPermissionsNotice } from "./tool-permissions-notice.js";
255
256
  import { NeedsYouHub } from "./needs-you-hub.js";
256
257
  import { WEB_CHAT_NOTICE, claimNotice, hasWebChat, releaseNotice, upgradeNoticesPath } from "./upgrade-notices.js";
257
- import { GENERAL_PAUSE_ERROR, isGeneralInstance } from "./general-instance.js";
258
+ import { GENERAL_NAME, GENERAL_PAUSE_ERROR, adoptGeneralByName, freeGeneralName, isGeneralInstance } from "./general-instance.js";
258
259
  import { buildOrgChart } from "./web-org.js";
259
260
  import { topMemoryHogs } from "./memory-hogs.js";
260
261
  import { GENERAL_POINTING_REFUSALS, SNOWFLAKE, hasPlaceRefs, placeRef, webRoute, webTextLinks, placeSuffix, renderPlaceRefs, stripPlaceRefs, topicUrl, worldPlaceOf } from "./topic-link.js";
@@ -499,6 +500,7 @@ const HANG_CALLBACK_PREFIX = "hang:";
499
500
  const CLEAR_CONFIRM_CALLBACK_PREFIX = "clear-confirm:";
500
501
  /** #2598 B2: a kiro classic → TUI move's Confirm in General. "kiro-migrate:" (13) + 32 hex + ":confirm" (8) = 53 bytes. */
501
502
  const KIRO_MIGRATE_CALLBACK_PREFIX = "kiro-migrate:";
503
+ const KIRO_RECONCILE_CALLBACK_PREFIX = "kiro-reconcile:";
502
504
  /** #2692: a fleet admin's Approve / Reject on an agent's pending skin-pack change, in General. */
503
505
  const OFFICE_PACK_CALLBACK_PREFIX = "office-pack:";
504
506
  /** #2692: the skin-pack tools' IPC types (answered as web theme tools). */
@@ -931,6 +933,7 @@ export class FleetManager {
931
933
  pendingNonceButtons = new Map();
932
934
  /** #2598 B2: the kiro moves waiting on a fleet admin's Confirm in General, by prompt nonce. */
933
935
  pendingKiroMigrations = new Map();
936
+ pendingKiroReconciliations = new Map();
934
937
  kiroMigrationRuns = new Map();
935
938
  /** #1386 "Needs you": the list, its live chat messages and Acknowledge. Started with the fleet (finishStartup). */
936
939
  needsYou = null;
@@ -1236,7 +1239,7 @@ export class FleetManager {
1236
1239
  * `share` null with `count`: "Revoke all".
1237
1240
  */
1238
1241
  officeShareNotice(event, who, share, count) {
1239
- const office = !share ? "" : share.office === ALL_OFFICES ? t("office_share.all") : this.officeStore.list().offices.find(o => o.id === share.office)?.name ?? share.office;
1242
+ const office = !share ? "" : share.office === ALL_OFFICES ? t("office_share.all") : share.office === WHOLE_FLEET ? t("office_share.whole") : this.officeStore.list().offices.find(o => o.id === share.office)?.name ?? share.office;
1240
1243
  const minutes = share ? Math.round((share.expiresAt - share.createdAt) / 60_000) : 0;
1241
1244
  const text = event === "created" ? t("office_share.created_notice", who, office, minutes < 60 ? `${minutes} min` : `${Math.round(minutes / 60)} h`)
1242
1245
  : share ? t("office_share.revoked_notice", who, office) : t("office_share.revoked_all_notice", who, count);
@@ -2001,7 +2004,10 @@ export class FleetManager {
2001
2004
  finally {
2002
2005
  writePausedMarker(this.getInstanceDir(name), Date.now(), "error");
2003
2006
  } },
2004
- readClassicStore: (workingDirectory, credentialProfile) => listKiroV1Sessions(workingDirectory, kiroV1DbPath(credentialProfile)),
2007
+ readClassicStore: async (workingDirectory, credentialProfile) => {
2008
+ const dbPath = kiroV1DbPath(credentialProfile);
2009
+ return listKiroV1Sessions(workingDirectory, dbPath, await readKiroClassicLinks(workingDirectory, dbPath));
2010
+ },
2005
2011
  };
2006
2012
  }
2007
2013
  /**
@@ -2009,7 +2015,7 @@ export class FleetManager {
2009
2015
  * here; the move runs on the Confirm (handleKiroMigrateCallback), judged again then.
2010
2016
  */
2011
2017
  async requestKiroMigration(name, startFresh) {
2012
- const judged = planKiroMigration(this.kiroMigrateDeps(), name, startFresh);
2018
+ const judged = await planKiroMigration(this.kiroMigrateDeps(), name, startFresh);
2013
2019
  if (!judged.ok)
2014
2020
  return judged;
2015
2021
  const general = this.findGeneralInstance();
@@ -2062,6 +2068,76 @@ export class FleetManager {
2062
2068
  this.notifyInstanceTopic(plan.name, outcome.text);
2063
2069
  return true;
2064
2070
  }
2071
+ kiroReconcileDeps() {
2072
+ return { ...this.kiroMigrateDeps(), store: async (input, plan, actor, rollbackReceipt) => {
2073
+ const reply = await sharedKiroV2StoreLane.read({ keys: [], sessionsDir: input.sessionsDir, reconciliation: { input, plan, actor, rollbackReceipt } });
2074
+ if (reply.kind !== "ok" || !reply.reconciliation)
2075
+ throw new Error(reply.kind === "unreadable" ? reply.detail : t("kiro_reconcile.changed"));
2076
+ return reply.reconciliation;
2077
+ } };
2078
+ }
2079
+ async requestKiroReconciliation(name, keep, archive, rollbackReceipt) {
2080
+ try {
2081
+ if (!this.eventLog)
2082
+ return { ok: false, error: t("kiro_reconcile.audit_failed") };
2083
+ const plan = await planKiroReconciliation(this.kiroReconcileDeps(), name, keep, archive, rollbackReceipt);
2084
+ const general = this.findGeneralInstance(), adapterId = general ? this.getInstanceAdapterId(general) : undefined;
2085
+ const adapter = general ? this.getAdapterForInstance(general) : undefined, chatId = general ? this.getGroupIdForInstance(general) : undefined;
2086
+ const topic = general ? String(this.fleetConfig?.instances[general]?.topic_id ?? "") : "";
2087
+ if (!general || !adapterId || !adapter || !chatId)
2088
+ return { ok: false, error: t("kiro_migrate.no_general") };
2089
+ const nonce = await this.postNonceButtonPromptOrThrow({ prefix: KIRO_RECONCILE_CALLBACK_PREFIX, alertType: "clear_confirm", instanceName: name,
2090
+ adapter, adapterId, chatId, ...(topic ? { threadId: topic } : {}), message: kiroReconciliationPrompt(plan),
2091
+ choices: [{ action: "confirm", label: t("kiro_migrate.confirm_button") }, { action: "cancel", label: t("kiro_migrate.cancel_button") }],
2092
+ expiredText: t("kiro_migrate.expired", name), timeoutMs: KIRO_MIGRATE_TIMEOUT_MS });
2093
+ this.pendingKiroReconciliations.set(nonce, plan);
2094
+ setTimeout(() => this.pendingKiroReconciliations.delete(nonce), KIRO_MIGRATE_TIMEOUT_MS + 60_000).unref?.();
2095
+ this.eventLog?.insert(name, "kiro_reconcile", { phase: "requested", keep, archive, rollbackReceipt, message: kiroReconciliationPrompt(plan) });
2096
+ return { ok: true, text: t("kiro_migrate.requested") };
2097
+ }
2098
+ catch (error) {
2099
+ return { ok: false, error: error instanceof SyntaxError ? "Malformed reconciliation data" : error.message };
2100
+ }
2101
+ }
2102
+ async handleKiroReconcileCallback(data, adapterId, adapter) {
2103
+ const claimed = this.consumeNonceCallback(KIRO_RECONCILE_CALLBACK_PREFIX, /^kiro-reconcile:([0-9a-f]{32}):(confirm|cancel)$/, data, adapterId, adapter);
2104
+ if (claimed === null)
2105
+ return false;
2106
+ if (claimed === "consumed")
2107
+ return true;
2108
+ const { entry, action } = claimed;
2109
+ const nonce = data.callbackData.slice(KIRO_RECONCILE_CALLBACK_PREFIX.length, KIRO_RECONCILE_CALLBACK_PREFIX.length + 32);
2110
+ const plan = this.pendingKiroReconciliations.get(nonce);
2111
+ this.pendingKiroReconciliations.delete(nonce);
2112
+ if (action === "cancel" || !plan) {
2113
+ await this.retireNonceButtons(entry, entry.messageId ?? data.messageId, t(plan ? "kiro_migrate.cancelled" : "kiro_migrate.expired", entry.instanceName));
2114
+ this.eventLog?.insert(entry.instanceName, "kiro_reconcile", { phase: "cancelled_or_expired", userId: data.userId });
2115
+ return true;
2116
+ }
2117
+ let outcome;
2118
+ try {
2119
+ if (!this.eventLog)
2120
+ throw new Error(t("kiro_reconcile.audit_failed"));
2121
+ this.eventLog.insert(plan.name, "kiro_reconcile", { phase: "confirmed", userId: data.userId, keep: plan.input.sessionId, archive: plan.input.archiveId });
2122
+ }
2123
+ catch {
2124
+ await this.retireNonceButtons(entry, entry.messageId ?? data.messageId, t("kiro_reconcile.audit_failed"));
2125
+ this.notifyFleetError(t("kiro_reconcile.audit_failed"));
2126
+ return true;
2127
+ }
2128
+ await this.retireNonceButtons(entry, entry.messageId ?? data.messageId, t("kiro_migrate.applying", plan.name));
2129
+ outcome = await applyKiroReconciliation(this.kiroReconcileDeps(), plan, `${adapterId}:${data.userId}`);
2130
+ try {
2131
+ this.eventLog.insert(plan.name, "kiro_reconcile", { phase: outcome.ok ? "completed" : "failed", userId: data.userId, receipt: outcome.receipt, message: outcome.text });
2132
+ }
2133
+ catch {
2134
+ this.logger.error({ name: plan.name, receipt: outcome.receipt }, "Kiro reconciliation final Log entry failed; confirmed intent remains in the audit and archive");
2135
+ }
2136
+ this.logger.info({ name: plan.name, ok: outcome.ok, receipt: outcome.receipt }, "Kiro explicit reconciliation");
2137
+ this.notifyFleetError(outcome.text);
2138
+ this.notifyInstanceTopic(plan.name, outcome.text);
2139
+ return true;
2140
+ }
2065
2141
  async handleSettingsChangeCallback(data, adapterId, adapter) {
2066
2142
  const result = this.consumeNonceCallback("settings-confirm:", /^settings-confirm:([0-9a-f]{32}):(confirm|reject)$/, data, adapterId, adapter, undefined, (userId, entry) => entry.confirmationAdmin?.(userId) === true);
2067
2143
  if (!result)
@@ -5639,7 +5715,10 @@ export class FleetManager {
5639
5715
  */
5640
5716
  resumePaused = false,
5641
5717
  /** Phase 2a: the caller's transition, for a start made from inside a restart or wake. */
5642
- transition, execution) {
5718
+ transition, execution, kiroMigration) {
5719
+ const migration = this.kiroMigrationRuns?.get(name);
5720
+ if (migration && migration.token !== kiroMigration)
5721
+ throw new Error(t("kiro_migrate.in_progress"));
5643
5722
  execution?.assert();
5644
5723
  if (this.sessionOomStopped(name)) {
5645
5724
  if (resumePaused)
@@ -6507,7 +6586,8 @@ export class FleetManager {
6507
6586
  return { backend, profile: credentialHomeSpec(backend) ? instanceCredentialProfile(config, this.fleetConfig?.defaults, backend) : null };
6508
6587
  });
6509
6588
  const topicMode = this.fleetConfig?.channel?.mode === "topic";
6510
- await this.startAfterRestart(name, wasPaused, pausedAt, pauseReason, () => this.startInstance(name, config, topicMode ?? false, "fleet-topic", false, transition));
6589
+ await this.startAfterRestart(name, wasPaused, pausedAt, pauseReason, () => opts?.kiroMigration ? this.startInstance(name, config, topicMode ?? false, "fleet-topic", false, transition, undefined, opts.kiroMigration)
6590
+ : this.startInstance(name, config, topicMode ?? false, "fleet-topic", false, transition));
6511
6591
  this.stormWindow.markRecovered(name);
6512
6592
  return;
6513
6593
  }
@@ -8301,8 +8381,8 @@ export class FleetManager {
8301
8381
  const channelConfigs = fleet.channels ?? (fleet.channel ? [fleet.channel] : []);
8302
8382
  this.warnUnboundGeneralChannelIds(fleet);
8303
8383
  const primaryAdapterId = channelConfigs[0] ? (channelConfigs[0].id ?? channelConfigs[0].type) : undefined;
8384
+ let generalsCreated = adoptGeneralByName(fleet, this.logger, dir => insideManagedWorkspaces(dir) || resolvePath(dir) === join(getAgendHome(), GENERAL_NAME));
8304
8385
  const generalInstances = Object.entries(fleet.instances).filter(([, inst]) => inst.general_topic === true);
8305
- let generalsCreated = false;
8306
8386
  // Collect unbound generals (no channel_id set) for auto-assignment
8307
8387
  const unboundGenerals = generalInstances.filter(([, inst]) => !inst.channel_id);
8308
8388
  // Track which adapters still need a general
@@ -8362,9 +8442,16 @@ export class FleetManager {
8362
8442
  }
8363
8443
  // Phase 3: Create new generals for any remaining adapters
8364
8444
  for (const need of needsGeneral) {
8365
- const name = channelConfigs.length > 1 ? `general-${need.adapterId}` : "general";
8366
- if (fleet.instances[name])
8445
+ let name = channelConfigs.length > 1 ? `general-${need.adapterId}` : GENERAL_NAME;
8446
+ if (fleet.instances[name]?.general_topic)
8367
8447
  continue;
8448
+ if (fleet.instances[name]) {
8449
+ // M-2069: the name is an agent's that is not the General (adoptGeneralByName left it: it works in a project
8450
+ // of the user's) — the fleet still gets its General, under a free name, never none.
8451
+ const taken = name;
8452
+ name = freeGeneralName(fleet.instances, taken);
8453
+ this.logger.warn({ taken, name }, "An agent is named like the General but is not one — creating the General under a free name; rename that agent to clear this");
8454
+ }
8368
8455
  this.logger.warn({ adapter: need.adapterId, name }, "No general instance for adapter — auto-creating");
8369
8456
  const generalDir = join(getAgendHome(), name);
8370
8457
  mkdirSync(generalDir, { recursive: true, mode: 0o700 });
@@ -14755,6 +14842,8 @@ export class FleetManager {
14755
14842
  return true;
14756
14843
  if (await this.handleKiroMigrateCallback(data, adapterId, adapter))
14757
14844
  return true;
14845
+ if (await this.handleKiroReconcileCallback(data, adapterId, adapter))
14846
+ return true;
14758
14847
  if (await this.handleOfficePackCallback(data, adapterId, adapter))
14759
14848
  return true;
14760
14849
  if (await this.handleDashboardCallback(data, adapterId, adapter))