@lambdacurry/arbor 0.24.16 → 0.24.18

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 (2) hide show
  1. package/dist/arbor.js +99 -16
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -7657,13 +7657,16 @@ var threads = sqliteTable("threads", {
7657
7657
  openQuestions: text("open_questions", { mode: "json" }).$type().notNull().default([]),
7658
7658
  expectedOutput: text("expected_output").notNull().default(""),
7659
7659
  number: integer2("number"),
7660
- createdAt: ts("created_at").notNull()
7660
+ createdAt: ts("created_at").notNull(),
7661
+ lastActivityAt: ts("last_activity_at")
7661
7662
  }, (t) => ({
7662
7663
  spaceNumberUq: uniqueIndex("threads_space_number_uq").on(t.spaceId, t.number),
7663
7664
  topicIdx: index("threads_topic_idx").on(t.topicId),
7664
7665
  spaceIdx: index("threads_space_idx").on(t.spaceId),
7665
7666
  lifecycleTypeIdx: index("threads_lifecycle_type_idx").on(t.lifecycleType),
7666
- topicLifecycleRankIdx: index("threads_topic_lifecycle_rank_idx").on(t.topicId, t.lifecycleType, t.rank)
7667
+ topicLifecycleRankIdx: index("threads_topic_lifecycle_rank_idx").on(t.topicId, t.lifecycleType, t.rank),
7668
+ topicLabelRankIdx: index("threads_topic_label_rank_idx").on(t.topicId, t.lifecycleLabel, t.rank, t.lastActivityAt),
7669
+ topicActivityIdx: index("threads_topic_activity_idx").on(t.topicId, t.lastActivityAt, t.id)
7667
7670
  }));
7668
7671
  var computerConfigs = sqliteTable("computer_configs", {
7669
7672
  id: text("id").primaryKey(),
@@ -8040,6 +8043,29 @@ var computerSnapshots = sqliteTable("computer_snapshots", {
8040
8043
  runIdx: index("computer_snapshots_run_idx").on(t.runId, t.createdAt),
8041
8044
  parentIdx: index("computer_snapshots_parent_idx").on(t.parentSnapshotId)
8042
8045
  }));
8046
+ var computerCheckpointOperations = sqliteTable("computer_checkpoint_operations", {
8047
+ operationId: text("operation_id").primaryKey(),
8048
+ computerId: text("computer_id").notNull().references(() => threadComputers.id),
8049
+ payload: text("payload").notNull(),
8050
+ payloadDigest: text("payload_digest").notNull(),
8051
+ workspaceGeneration: text("workspace_generation").notNull(),
8052
+ captureMutationVersion: integer2("capture_mutation_version").notNull(),
8053
+ expectedHeadSnapshotId: text("expected_head_snapshot_id"),
8054
+ state: text("state").$type().notNull(),
8055
+ failureCode: text("failure_code"),
8056
+ nativeSnapshotId: text("native_snapshot_id"),
8057
+ capturedAt: ts("captured_at"),
8058
+ expiresAt: ts("expires_at"),
8059
+ portableProviderRef: text("portable_provider_ref"),
8060
+ publishedSnapshotId: text("published_snapshot_id"),
8061
+ restoreSessionId: text("restore_session_id"),
8062
+ restoreState: text("restore_state").$type(),
8063
+ restoredAt: ts("restored_at"),
8064
+ createdAt: ts("created_at").notNull(),
8065
+ updatedAt: ts("updated_at").notNull()
8066
+ }, (t) => ({
8067
+ computerIdx: index("computer_checkpoint_operations_computer_idx").on(t.computerId, t.createdAt)
8068
+ }));
8043
8069
  var computerSnapshotEvidence = sqliteTable("computer_snapshot_evidence", {
8044
8070
  snapshotId: text("snapshot_id").primaryKey().references(() => computerSnapshots.id),
8045
8071
  purpose: text("purpose").$type().notNull(),
@@ -9199,11 +9225,7 @@ var assigneeColumns = {
9199
9225
  color: profiles.color,
9200
9226
  emoji: profiles.emoji
9201
9227
  };
9202
- var lastActivityExpr = sql`coalesce(
9203
- (select max(${contributions.createdAt}) from ${contributions}
9204
- where ${contributions.threadId} = ${threads.id}),
9205
- ${threads.createdAt}
9206
- )`;
9228
+ var lastActivity = sql`${threads.lastActivityAt}`;
9207
9229
 
9208
9230
  // ../core/src/ops/space.ts
9209
9231
  var GUIDANCE_LIMITS = {
@@ -9320,6 +9342,8 @@ var BASE_MS = Date.parse("2026-07-20T15:00:00.000Z");
9320
9342
  var PAIRING_TTL_MS = 15 * 60 * 1000;
9321
9343
  // ../core/src/ops/space-visit.ts
9322
9344
  var VISIT_THROTTLE_MS = 5 * 60 * 1000;
9345
+ // ../core/src/ops/computer-checkpoint-operations.ts
9346
+ var CHECKPOINT_OPERATION_TTL_SECONDS = 7 * 24 * 60 * 60;
9323
9347
  // ../core/src/ops/package-cache.ts
9324
9348
  var PACKAGE_CACHE_PENDING_TTL_MS = 15 * 60 * 1000;
9325
9349
  var PACKAGE_CACHE_FINAL_TTL_MS = 30 * 24 * 60 * 60 * 1000;
@@ -9472,6 +9496,24 @@ var adminCloseOutputSchema = strictObject({
9472
9496
  reasonCode: literal("run.admin_closed_abandoned"),
9473
9497
  actorProfileId: string2()
9474
9498
  });
9499
+ var adminForceStopOutputSchema = strictObject({
9500
+ mode: literal("admin_force"),
9501
+ outcome: _enum(["stopped", "absent"]),
9502
+ computerId: string2(),
9503
+ computerSessionId: string2(),
9504
+ reason: string2(),
9505
+ generation: strictObject({
9506
+ providerGeneration: number2().int().nonnegative(),
9507
+ workspaceGeneration: string2().nullable()
9508
+ }),
9509
+ settledRunIds: array(string2()),
9510
+ skippedRuns: array(strictObject({ runId: string2(), reason: string2() })),
9511
+ stoppedAt: string2().optional(),
9512
+ terminatedProcessIds: array(string2()).optional(),
9513
+ recoveryRebased: boolean2().optional(),
9514
+ replayed: boolean2().optional(),
9515
+ note: string2().optional()
9516
+ });
9475
9517
  function buildOutputSchemas() {
9476
9518
  const id = string2();
9477
9519
  const timestamp = string2();
@@ -10603,9 +10645,26 @@ function buildOutputSchemas() {
10603
10645
  workflow: workflowSummary.optional(),
10604
10646
  threads: array(thread).optional(),
10605
10647
  promotedArtifacts: array(artifact).optional(),
10606
- total: number2().int().min(0),
10648
+ total: number2().int().min(0).optional(),
10607
10649
  nextCursor: string2().optional(),
10608
- computerConfig: resolvedComputerConfig.nullable().optional()
10650
+ computerConfig: resolvedComputerConfig.nullable().optional(),
10651
+ counts: looseObject({
10652
+ total: number2().int().min(0),
10653
+ byStatus: record(string2(), number2().int().min(0)),
10654
+ byLabel: record(string2(), number2().int().min(0))
10655
+ }).optional(),
10656
+ canEditGuidance: boolean2().optional()
10657
+ }).superRefine((value, ctx) => {
10658
+ if (value.threads !== undefined && value.total === undefined) {
10659
+ ctx.addIssue({
10660
+ code: "custom",
10661
+ path: ["total"],
10662
+ message: "a Thread roster requires total"
10663
+ });
10664
+ }
10665
+ if (value.threads === undefined && value.counts === undefined) {
10666
+ ctx.addIssue({ code: "custom", path: ["counts"], message: "a header requires counts" });
10667
+ }
10609
10668
  }),
10610
10669
  goal: looseObject({
10611
10670
  id: id.optional(),
@@ -13061,7 +13120,7 @@ var ACTION_DEFINITIONS = [
13061
13120
  {
13062
13121
  name: "thread_list",
13063
13122
  title: "List assigned threads or a Space's threads",
13064
- description: "List Threads you are responsible for (default), another profile's or jointly several, unassigned in one Space/Topic, or every Thread in a Space (`assignee=any` + spaceId) — default current work; status widens; order=activity is last-activity DESC (the aggregate board). `inbox` remains what you owe.",
13123
+ description: "List Threads you are responsible for (default), another profile's or jointly several, unassigned in one Space/Topic, or every Thread in a Space or Topic (`assignee=any` + spaceId or one topicId) — default current work; status widens; order=activity is last-activity DESC (the aggregate board). `inbox` remains what you owe.",
13065
13124
  inputSchema: {
13066
13125
  assignee: union([string2(), array(string2()).min(1).max(5)]).optional().describe("`me` (default), a profile id (prof_…), a list (assigned to ALL of them), or `any` (every Thread in the required spaceId)"),
13067
13126
  unassigned: boolean2().optional().describe("threads with no assignee — requires spaceId or topicId"),
@@ -13094,8 +13153,9 @@ var ACTION_DEFINITIONS = [
13094
13153
  "archived"
13095
13154
  ])).min(1).max(8)
13096
13155
  ]).optional().describe("default current = active + needs-review + stuck; all includes backlog/standing/resolved/canceled/archived; or a list of statuses to keep (current/all only alone)"),
13097
- order: _enum(["assigned", "activity"]).optional().describe("default assigned = newest assignment first; activity = last_activity_at DESC (aggregate board order)"),
13098
- limit: number2().int().min(1).max(100).optional().describe("page size (default 20, max 100)"),
13156
+ order: _enum(["assigned", "activity", "column"]).optional().describe("default assigned = newest assignment first; activity = last_activity_at DESC (default page 50); column = one Topic Board column, ranked then by recency (needs assignee=any, one topicId, lifecycleLabel)"),
13157
+ lifecycleLabel: string2().min(1).optional().describe("order=column only: the Board column's lifecycle label key"),
13158
+ limit: number2().int().min(1).max(100).optional().describe("page size (default 20; 50 for order=activity; max 100)"),
13099
13159
  cursor: string2().optional().describe("keyset cursor from a prior page's nextCursor")
13100
13160
  },
13101
13161
  surfaces: ["mcp", "cli"],
@@ -13696,10 +13756,31 @@ var ACTION_DEFINITIONS = [
13696
13756
  description: "Deprecated by AD-306: finishing the last active shared Run with computer_run_finish performs the final checkpoint and stops the parent. Still checkpoints and stops the parent for a shared write Run (runId) or a legacy computerSessionId, refusing teardown when durability fails or a background process is running.",
13697
13757
  inputSchema: {
13698
13758
  runId: string2().optional().describe("an active shared write Run whose parent to checkpoint and stop, run_…"),
13699
- computerSessionId: string2().optional().describe("legacy alternative to runId: a computerSessionId on that Computer, cms_…")
13759
+ computerSessionId: string2().optional().describe("legacy alternative to runId: a computerSessionId on that Computer, cms_…"),
13760
+ mode: literal("save").optional().describe("save stop (checkpoint, then stop); omission preserves existing behavior")
13700
13761
  },
13701
13762
  surfaces: ["computer-cli"],
13702
13763
  toolset: "loop",
13764
+ variantDiscriminator: "mode",
13765
+ privilegedVariants: [
13766
+ {
13767
+ tag: "admin_force",
13768
+ requires: "active-org-admin",
13769
+ inputSchema: {
13770
+ mode: literal("admin_force").describe("active same-org owner/admin only (AD-358): kill the parent's processes and release it WITHOUT saving; its last checkpoint stays the restore point"),
13771
+ computerSessionId: string2().describe("admin_force: the exact computerSessionId of the Computer to stop, cms_…"),
13772
+ acceptDataLoss: boolean2().refine((value) => value === true, {
13773
+ message: "admin_force requires acceptDataLoss: true"
13774
+ }).describe("admin_force: must be true; running processes and unsaved work are lost"),
13775
+ reason: string2().trim().min(1).max(500).describe("admin_force: why the Computer is being force-stopped (recorded)"),
13776
+ expectedProviderGeneration: number2().int().nonnegative().describe("admin_force: the exact provider generation to stop"),
13777
+ expectedWorkspaceGeneration: string2().min(1).nullable().describe("admin_force: the exact workspace generation; null (CLI: the value null) for a Computer with none")
13778
+ },
13779
+ omitInputs: ["runId"],
13780
+ description: "Checkpoint and stop the parent for a shared write Run (deprecated by AD-306 in favor of computer_run_finish). Organization owner/admin only: mode=admin_force kills the parent's processes and releases it without saving, by exact computerSessionId and both expected generations, with acceptDataLoss and a reason; its shared Runs settle only on control's confirmed stop of that generation.",
13781
+ outputSchema: adminForceStopOutputSchema
13782
+ }
13783
+ ],
13703
13784
  run: forward("computer_runtime.stop")
13704
13785
  },
13705
13786
  {
@@ -14517,11 +14598,13 @@ var ACTION_DEFINITIONS = [
14517
14598
  {
14518
14599
  name: "topic_get",
14519
14600
  title: "Read a topic",
14520
- description: "Read a Topic's durable context, guidance, the room's standing ways to help (`contributionLanes`), selected workflow summary, open requests, promoted artifacts, and a paged Thread roster (default 50; `total` is the full roster size). Continue with `cursor`, or use `all=true` / `--all` only for intentional complete enumeration; for a concrete question in a large Topic, prefer Topic-scoped `recall`.",
14601
+ description: "Read a Topic's durable context, guidance, the room's standing ways to help (`contributionLanes`), selected workflow summary, open requests, promoted artifacts, and a paged Thread roster (default 50; `total` is the full roster size). Continue with `cursor`, or use `all=true` / `--all` only for intentional complete enumeration; for a concrete question in a large Topic, prefer Topic-scoped `recall`. `threads=none` is the header alone.",
14521
14602
  inputSchema: {
14522
14603
  topicId: string2().min(1).describe("the topic id"),
14604
+ threads: _enum(["page", "none"]).optional().describe("page (default) includes the Thread roster page; none = header only — counts by status/label, participants, open-request count (no limit/cursor/all); page its Threads with thread_list assignee=any + topicId"),
14523
14605
  ...PAGINATION_INPUT
14524
14606
  },
14607
+ externalReadDefaults: { unpagedWhen: { field: "threads", value: "none" } },
14525
14608
  surfaces: ["mcp", "cli"],
14526
14609
  toolset: "loop",
14527
14610
  run: forward("topic.get")
@@ -15526,7 +15609,7 @@ var ACTIONS = ACTION_DEFINITIONS.map((action) => {
15526
15609
  });
15527
15610
 
15528
15611
  // ../actions/src/retention-entry.ts
15529
- var ARBOR_VERSION = "0.24.16";
15612
+ var ARBOR_VERSION = "0.24.18";
15530
15613
  var historyPolicySchema = _enum(["full", "checkpoint"]).optional().describe("text Artifacts: future history retention policy; full retains every source snapshot, checkpoint keeps metadata for every revision and source only when explicitly retained");
15531
15614
  var retainSourceSchema = boolean2().optional().describe("edit: in checkpoint mode, retain this newly minted content revision's source");
15532
15615
  var checkpointSchema = boolean2().optional().describe("edit: retain the exact current version source without incrementing content version");
@@ -16410,7 +16493,7 @@ function dispositionFilename(value) {
16410
16493
  // package.json
16411
16494
  var package_default = {
16412
16495
  name: "@lambdacurry/arbor",
16413
- version: "0.24.16",
16496
+ version: "0.24.18",
16414
16497
  description: "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
16415
16498
  keywords: [
16416
16499
  "agents",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.24.16",
3
+ "version": "0.24.18",
4
4
  "description": "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
5
5
  "keywords": [
6
6
  "agents",