@lambdacurry/arbor 0.24.3 → 0.24.4

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 +74 -57
  2. package/package.json +2 -3
package/dist/arbor.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // package.json
3
3
  var package_default = {
4
4
  name: "@lambdacurry/arbor",
5
- version: "0.24.3",
5
+ version: "0.24.4",
6
6
  description: "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
7
7
  keywords: [
8
8
  "agents",
@@ -29,7 +29,7 @@ var package_default = {
29
29
  access: "public"
30
30
  },
31
31
  scripts: {
32
- arbor: "tsx src/bin.ts",
32
+ arbor: "vpx src/bin.ts",
33
33
  build: "bun build ./src/bin.ts --target=node --outfile=dist/arbor.js",
34
34
  test: "vp test run --passWithNoTests",
35
35
  typecheck: "tsc -b",
@@ -40,7 +40,6 @@ var package_default = {
40
40
  "@arbor/core": "workspace:*",
41
41
  "@types/node": "^26.2.0",
42
42
  "just-bash": "3.4.2",
43
- tsx: "^4.20.6",
44
43
  typescript: "^5.8.0",
45
44
  "vite-plus": "catalog:",
46
45
  zod: "^4.4.3"
@@ -6580,10 +6579,20 @@ var spaces = sqliteTable("spaces", {
6580
6579
  defaultReviewDimensions: text("default_review_dimensions", { mode: "json" }).$type().notNull().default([]),
6581
6580
  stage: text("stage").$type().notNull().default("exploration"),
6582
6581
  systemKind: text("system_kind"),
6582
+ key: text("key"),
6583
6583
  createdAt: ts("created_at").notNull()
6584
6584
  }, (t) => ({
6585
6585
  orgIdx: index("spaces_org_idx").on(t.orgId),
6586
- systemKindUq: uniqueIndex("spaces_system_kind_uq").on(t.systemKind)
6586
+ systemKindUq: uniqueIndex("spaces_system_kind_uq").on(t.systemKind),
6587
+ orgKeyUq: uniqueIndex("spaces_org_key_uq").on(t.orgId, t.key)
6588
+ }));
6589
+ var spaceRetiredKeys = sqliteTable("space_retired_keys", {
6590
+ orgId: text("org_id").notNull().references(() => orgs.id),
6591
+ key: text("key").notNull(),
6592
+ spaceId: text("space_id").notNull().references(() => spaces.id),
6593
+ retiredAt: ts("retired_at").notNull()
6594
+ }, (t) => ({
6595
+ orgKeyUq: uniqueIndex("space_retired_keys_org_key_uq").on(t.orgId, t.key)
6587
6596
  }));
6588
6597
  var spaceMemberships = sqliteTable("space_memberships", {
6589
6598
  id: text("id").primaryKey(),
@@ -6713,8 +6722,10 @@ var threads = sqliteTable("threads", {
6713
6722
  waysToHelp: text("ways_to_help", { mode: "json" }).$type().notNull().default([]),
6714
6723
  openQuestions: text("open_questions", { mode: "json" }).$type().notNull().default([]),
6715
6724
  expectedOutput: text("expected_output").notNull().default(""),
6725
+ number: integer2("number"),
6716
6726
  createdAt: ts("created_at").notNull()
6717
6727
  }, (t) => ({
6728
+ spaceNumberUq: uniqueIndex("threads_space_number_uq").on(t.spaceId, t.number),
6718
6729
  topicIdx: index("threads_topic_idx").on(t.topicId),
6719
6730
  spaceIdx: index("threads_space_idx").on(t.spaceId),
6720
6731
  lifecycleTypeIdx: index("threads_lifecycle_type_idx").on(t.lifecycleType),
@@ -8218,6 +8229,36 @@ var ORG_ADMIN_CONTAINMENT_PERMISSIONS = new Set([
8218
8229
  "revoke"
8219
8230
  ]);
8220
8231
 
8232
+ // ../core/src/queries/artifact-base.ts
8233
+ var eventChronology = sql`_rowid_`;
8234
+ var SPACE_ARTIFACT_STATUSES = [
8235
+ "draft",
8236
+ "proposed",
8237
+ "active",
8238
+ "promoted",
8239
+ "needs-review",
8240
+ "superseded",
8241
+ "deprecated",
8242
+ "archived"
8243
+ ];
8244
+ var artifactUpdatedAt = sql`coalesce((select max(${events.createdAt}) from ${events} where ${events.objectType} = 'artifact' and ${events.objectId} = ${artifacts.id}), ${artifacts.createdAt})`;
8245
+ // ../core/src/queries/thread-assignment.ts
8246
+ var assigneeColumns = {
8247
+ threadId: threadAssignments.threadId,
8248
+ assignedAt: threadAssignments.createdAt,
8249
+ assignedByProfileId: threadAssignments.assignedByProfileId,
8250
+ id: profiles.id,
8251
+ kind: profiles.kind,
8252
+ displayName: profiles.displayName,
8253
+ color: profiles.color,
8254
+ emoji: profiles.emoji
8255
+ };
8256
+ var lastActivityExpr = sql`coalesce(
8257
+ (select max(${contributions.createdAt}) from ${contributions}
8258
+ where ${contributions.threadId} = ${threads.id}),
8259
+ ${threads.createdAt}
8260
+ )`;
8261
+
8221
8262
  // ../core/src/ops/space.ts
8222
8263
  var GUIDANCE_LIMITS = {
8223
8264
  maxItems: 12,
@@ -8290,20 +8331,6 @@ var COMPUTER_WORKSPACE_RECOVERY_ATTACH_DEADLINE_MS = 31 * 60 * 1000;
8290
8331
  var COMPUTER_WORKSPACE_RECOVERY_HEALTH_DEADLINE_MS = 2 * 60 * 1000;
8291
8332
  var COMPUTER_WORKSPACE_RECOVERY_HEADROOM_MS = 2 * 60 * 1000;
8292
8333
  var COMPUTER_WORKSPACE_RECOVERY_LEASE_MS = COMPUTER_WORKSPACE_RECOVERY_CHECKPOINT_DEADLINE_MS + COMPUTER_WORKSPACE_RECOVERY_ATTACH_DEADLINE_MS + COMPUTER_WORKSPACE_RECOVERY_HEALTH_DEADLINE_MS + COMPUTER_WORKSPACE_RECOVERY_HEADROOM_MS;
8293
-
8294
- // ../core/src/queries/artifact-base.ts
8295
- var eventChronology = sql`_rowid_`;
8296
- var SPACE_ARTIFACT_STATUSES = [
8297
- "draft",
8298
- "proposed",
8299
- "active",
8300
- "promoted",
8301
- "needs-review",
8302
- "superseded",
8303
- "deprecated",
8304
- "archived"
8305
- ];
8306
- var artifactUpdatedAt = sql`coalesce((select max(${events.createdAt}) from ${events} where ${events.objectType} = 'artifact' and ${events.objectId} = ${artifacts.id}), ${artifacts.createdAt})`;
8307
8334
  // ../core/src/ops/artifact-git-intent.ts
8308
8335
  var RETRYABLE_REPAIR = new Set([
8309
8336
  "pending_push_unconfirmed",
@@ -8321,22 +8348,6 @@ var EMOJI_RE = new RegExp("^\\p{RGI_Emoji}$", "v");
8321
8348
  var BASE_MS = Date.parse("2026-07-20T15:00:00.000Z");
8322
8349
  // ../core/src/ops/agent-pairing.ts
8323
8350
  var PAIRING_TTL_MS = 15 * 60 * 1000;
8324
- // ../core/src/queries/thread-assignment.ts
8325
- var assigneeColumns = {
8326
- threadId: threadAssignments.threadId,
8327
- assignedAt: threadAssignments.createdAt,
8328
- assignedByProfileId: threadAssignments.assignedByProfileId,
8329
- id: profiles.id,
8330
- kind: profiles.kind,
8331
- displayName: profiles.displayName,
8332
- color: profiles.color,
8333
- emoji: profiles.emoji
8334
- };
8335
- var lastActivityExpr = sql`coalesce(
8336
- (select max(${contributions.createdAt}) from ${contributions}
8337
- where ${contributions.threadId} = ${threads.id}),
8338
- ${threads.createdAt}
8339
- )`;
8340
8351
  // ../core/src/ops/package-cache.ts
8341
8352
  var PACKAGE_CACHE_PENDING_TTL_MS = 15 * 60 * 1000;
8342
8353
  var PACKAGE_CACHE_FINAL_TTL_MS = 30 * 24 * 60 * 60 * 1000;
@@ -8510,6 +8521,7 @@ var recallHit = looseObject({
8510
8521
  excerpt: string2(),
8511
8522
  space: spaceRef.nullable(),
8512
8523
  threadId: nullableString,
8524
+ shortId: nullableString.optional(),
8513
8525
  url: nullableString,
8514
8526
  createdAt: timestamp
8515
8527
  });
@@ -8995,6 +9007,7 @@ var orgMember = looseObject({
8995
9007
  });
8996
9008
  var thread3 = looseObject({
8997
9009
  id,
9010
+ shortId: nullableString.optional(),
8998
9011
  title: string2(),
8999
9012
  objective: string2(),
9000
9013
  status: string2().optional(),
@@ -9033,6 +9046,7 @@ var topic2 = looseObject({
9033
9046
  var space3 = looseObject({
9034
9047
  id,
9035
9048
  title: string2(),
9049
+ key: nullableString.optional(),
9036
9050
  purpose: nullableString.optional(),
9037
9051
  stage: string2().optional(),
9038
9052
  url: string2().optional()
@@ -11161,6 +11175,7 @@ var TLDRAW_EXEC_OPERATIONS_SCHEMA = array(TLDRAW_EXEC_OPERATION_SCHEMA).min(1).m
11161
11175
  // ../actions/src/index.ts
11162
11176
  var ARTIFACT_TYPE_DESCRIPTION = `semantic type (one of: ${ARTIFACT_TYPES.join(", ")})`;
11163
11177
  var ARBOR_FEEDBACK_INPUT_TYPES = [...ARBOR_FEEDBACK_TYPES, "friction"];
11178
+ var SPACE_KEY_INPUT = string2().min(1).refine((key) => key.trim().length > 0, "space key cannot be blank");
11164
11179
  var CONTRIBUTION_ADD_LINK_RELS = [
11165
11180
  "cites",
11166
11181
  "contests",
@@ -11747,7 +11762,7 @@ var ACTION_DEFINITIONS = [
11747
11762
  title: "Contribute to a thread",
11748
11763
  description: "Add one additive point to a Thread; use stamp for agreement, respond/mark_as_response for requests, and links for deliberate reply/contest edges. Pass idempotencyKey (CLI: --idempotency-key) for safe retries.",
11749
11764
  inputSchema: {
11750
- threadId: string2().describe("the thread id, e.g. thr_…"),
11765
+ threadId: string2().describe("the thread id, e.g. thr_…, or its short id, e.g. BUD-34"),
11751
11766
  type: _enum(CONTRIBUTION_TYPES).describe("the contribution type (AD-066 taxonomy)"),
11752
11767
  body: string2().min(1).describe(`the contribution markdown. ${CONTRIBUTION_BODY_GUIDANCE}`),
11753
11768
  idempotencyKey: string2().min(1).max(200).optional().describe("stable key for this ONE logical contribution (≤200 chars), e.g. cron-run/work-item + output slot; safe retries return the original contribution. Reusing it with different content is a conflict."),
@@ -11906,7 +11921,7 @@ var ACTION_DEFINITIONS = [
11906
11921
  title: "Edit a thread's title, objective, or topic",
11907
11922
  description: "Correct a Thread's title or objective, or move it under another Topic of the same Space, patching only supplied fields; use it to make done clear or refile misfiled work instead of archiving and reopening. Status moves stay with `transition_thread`, column order with `--rank`, and the temporary help list with `charter` ways_to_help.",
11908
11923
  inputSchema: {
11909
- threadId: string2().describe("the thread to edit, thr_…"),
11924
+ threadId: string2().describe("the thread to edit, thr_… or a short id like BUD-34"),
11910
11925
  title: string2().min(1).optional().describe("a new title — the question, outcome, investigation, instance, or standing concern"),
11911
11926
  objective: string2().min(1).optional().describe("a new objective — what this Thread should accomplish; for finite work, what done means"),
11912
11927
  topicId: string2().optional().describe("move the thread under this topic of the same space, top_…"),
@@ -11922,7 +11937,7 @@ var ACTION_DEFINITIONS = [
11922
11937
  description: "Make a Space member (yourself when profileId is omitted) responsible for moving a Thread, or remove that responsibility; assignment is immediate, idempotent, grants no permissions, and creates no Inbox item — a specific owed action is still a `request`. Assignees stay attached through every lifecycle move, so transfer responsibility by assigning the new owner and unassigning the old.",
11923
11938
  inputSchema: {
11924
11939
  verb: _enum(["assign", "unassign"]).describe("add or remove responsibility"),
11925
- threadId: string2().describe("the thread, thr_…"),
11940
+ threadId: string2().describe("the thread, thr_… or a short id like BUD-34"),
11926
11941
  profileId: string2().optional().describe("the member to (un)assign, prof_…; omit for yourself")
11927
11942
  },
11928
11943
  surfaces: ["mcp", "cli"],
@@ -12023,7 +12038,7 @@ var ACTION_DEFINITIONS = [
12023
12038
  title: "Replace a Thread computer override",
12024
12039
  description: "DESTRUCTIVE REPLACE: Replace this Thread's entire sparse Computer override; omitted fields are cleared from the Thread layer and inherit Topic/Space/organization policy. This is config only and allocates no runtime; an existing Computer cannot switch provider, and repeating the same full layer is idempotent.",
12025
12040
  inputSchema: {
12026
- threadId: string2().describe("the Thread, thr_…"),
12041
+ threadId: string2().describe("the Thread, thr_… or a short id like BUD-34"),
12027
12042
  backend: _enum(["worker-shell", "container"]).nullable().optional().describe("override execution tier, or null to inherit"),
12028
12043
  containerProfile: string2().nullable().optional().describe("logical container profile; bun-typescript-v1 guarantees Bash, Git, GitHub CLI (gh), Bun 1.4.2, bunx, Node 26.5.1, pnpm 10.33.0, Python 3.13.15 (python/python3), jq, and ripgrep (rg), or null to clear inherited profile"),
12029
12044
  setupScript: string2().nullable().optional().describe("optional strict Bash setup for a fresh base after repositories materialize; install scoped tools in /workspace/.local/bin so exec finds them and snapshots retain them"),
@@ -12039,7 +12054,7 @@ var ACTION_DEFINITIONS = [
12039
12054
  title: "Attach a Thread computer",
12040
12055
  description: "Deprecated by AD-306: computer_run_start(threadId) attaches durable identity itself, so use this only to mint protocol identity with no Run at all. Creates or reuses the Thread's stable Computer identity and an immutable collaborator receipt without starting provider runtime.",
12041
12056
  inputSchema: {
12042
- threadId: string2().describe("the Thread whose computer you are attaching, thr_…")
12057
+ threadId: string2().describe("the Thread whose computer you are attaching, thr_… or a short id like BUD-34")
12043
12058
  },
12044
12059
  surfaces: ["cli"],
12045
12060
  toolset: "loop",
@@ -12050,7 +12065,7 @@ var ACTION_DEFINITIONS = [
12050
12065
  title: "Open a Thread computer",
12051
12066
  description: "Deprecated by AD-306: start work with computer_run_start(threadId, mode) instead; this alias remains one release and boots the parent Thread Computer, returning a computerSessionId. An optional owned active runId records a successful session attach as Run retention activity. Use it only for a legacy client that still addresses the parent by cms_ id; unsafe recovery is refused and unresolved newer workspace state stays fail-closed.",
12052
12067
  inputSchema: {
12053
- threadId: string2().describe("the Arbor Thread whose stable computer to open, thr_…"),
12068
+ threadId: string2().describe("the Arbor Thread whose stable computer to open, thr_… or a short id like BUD-34"),
12054
12069
  runId: string2().optional().describe("optional owned active Run; successful open renews its retention deadline"),
12055
12070
  idempotencyKey: string2().trim().min(1).max(200).optional().describe("optional explicit key for ONE distinct logical open; omission reuses the durable profile/Thread/recipe identity; changed options require a distinct intent; retry unchanged after response loss and never mint a new key to bypass unresolved work"),
12056
12071
  vcpus: number2().int().min(1).max(4).optional().describe("optional container vCPU request"),
@@ -12065,7 +12080,7 @@ var ACTION_DEFINITIONS = [
12065
12080
  title: "Replace a Thread computer",
12066
12081
  description: "DESTRUCTIVE RECOVERY: Replace an incompatible active Computer generation from the Thread's effective recipe when Arbor reports structural recipe incompatibility. Preserves the old generation unless the successor restores supported state and passes health.",
12067
12082
  inputSchema: {
12068
- threadId: string2().describe("the Thread whose active Computer generation is replaced, thr_…"),
12083
+ threadId: string2().describe("the Thread whose active Computer generation is replaced, thr_… or a short id like BUD-34"),
12069
12084
  idempotencyKey: string2().min(1).max(200).describe("stable key for this ONE replacement request; reuse it unchanged for retries"),
12070
12085
  reason: string2().min(1).max(500).describe("concise auditable reason for replacing the active generation")
12071
12086
  },
@@ -12078,7 +12093,7 @@ var ACTION_DEFINITIONS = [
12078
12093
  title: "Start a run",
12079
12094
  description: `Start an isolated write Run or shared/read Run with one idempotencyKey; pending admission returns runStartId for receipt observation while the lifecycle owner continues independently. Save work outside the temporary Computer and finish the Run when done; first use: read the Computer guide at ${AGENT_GUIDE_URLS.computer}.`,
12080
12095
  inputSchema: {
12081
- threadId: string2().optional().describe("the Thread whose Computer this Run works in, thr_…; the canonical Run-first front door"),
12096
+ threadId: string2().optional().describe("the Thread whose Computer this Run works in, thr_… or a short id like BUD-34; the canonical Run-first front door"),
12082
12097
  computerSessionId: string2().optional().describe("legacy compatibility alternative to threadId: an existing parent computerSessionId, cms_…"),
12083
12098
  mode: _enum(["read", "write"]).describe("write for mutable work; read for shared inspection"),
12084
12099
  execution: _enum(["shared", "isolated"]).optional().describe("write Run placement; defaults to isolated. Use shared only for intentional live collaboration on the Thread Computer"),
@@ -12260,7 +12275,7 @@ var ACTION_DEFINITIONS = [
12260
12275
  title: "Capture public visual evidence",
12261
12276
  description: "Capture a 1280×720 screenshot of one public HTTPS URL as Thread evidence without opening the project runtime. Returns capture metadata plus ready-to-place attachments[].markdown; put that Markdown exactly where the image belongs and bind the matching attachmentIds, while localhost and authenticated pages remain unavailable and the capture does not judge correctness.",
12262
12277
  inputSchema: {
12263
- threadId: string2().describe("the Arbor Thread that will own the evidence, thr_…"),
12278
+ threadId: string2().describe("the Arbor Thread that will own the evidence, thr_… or a short id like BUD-34"),
12264
12279
  targetUrl: url().refine((value) => value.startsWith("https://"), "targetUrl must use HTTPS").describe("one public HTTPS URL to capture")
12265
12280
  },
12266
12281
  surfaces: ["computer-mcp", "computer-cli"],
@@ -12544,7 +12559,7 @@ var ACTION_DEFINITIONS = [
12544
12559
  title: "Read a Thread computer",
12545
12560
  description: "Inspect a Thread's provider-free durable Computer recipe/materialization state, compatibility, recoverySafety, lineage, recent receipts, Runs, and reprovision outcomes; setup content and credentials stay redacted. This read never contacts execution; use computer_status for live readiness.",
12546
12561
  inputSchema: {
12547
- threadId: string2().describe("the Thread, thr_…"),
12562
+ threadId: string2().describe("the Thread, thr_… or a short id like BUD-34"),
12548
12563
  lineageLimit: number2().int().min(1).max(100).optional().describe("recent receipts/lineage rows (default 20)")
12549
12564
  },
12550
12565
  surfaces: ["computer-mcp", "cli"],
@@ -12581,7 +12596,7 @@ var ACTION_DEFINITIONS = [
12581
12596
  title: "Set a thread's ways to help",
12582
12597
  description: "Set a thread's READ-ONLY 'ways to help' (AD-038) — a short, curated list of perspectives, skills, or concrete tasks orienting someone on how they could pitch in with THIS thread as it stands (e.g. 'a benchmark on cold-start latency'). It is thread-local and temporary: it is read inside `thread_get`, and it never rolls up into a space/topic orientation surface — a standing statement about what a room wants is the room's standing ways to help (`contributionLanes`, via `set_space_lanes`/`set_topic_lanes`, AD-222). Guidance you READ, NOT an obligation — that's `request`. Replaces the whole list; pass [] to clear.",
12583
12598
  inputSchema: {
12584
- threadId: string2().describe("the thread, thr_…"),
12599
+ threadId: string2().describe("the thread, thr_… or a short id like BUD-34"),
12585
12600
  waysToHelp: proseList("the full ways-to-help list — replaces the existing one; [] clears it")
12586
12601
  },
12587
12602
  surfaces: ["cli"],
@@ -12593,7 +12608,7 @@ var ACTION_DEFINITIONS = [
12593
12608
  title: "Move a thread's lifecycle",
12594
12609
  description: transitionThreadActionDescription(),
12595
12610
  inputSchema: {
12596
- threadId: string2().describe("the thread to move, thr_…"),
12611
+ threadId: string2().describe("the thread to move, thr_… or a short id like BUD-34"),
12597
12612
  to: string2().min(1).describe("label key, case-insensitive label name, or bare type (`resolved` still works as a type name)"),
12598
12613
  reason: string2().optional().describe("optional one-line why, recorded on the event"),
12599
12614
  rank: string2().max(THREAD_RANK_MAX).regex(THREAD_RANK_PATTERN).nullable().optional().describe("LexoRank in the destination column; omit to leave unchanged, null to restore recency. Combined with `--to` this is one atomic write — a bad rank moves nothing")
@@ -12679,7 +12694,7 @@ var ACTION_DEFINITIONS = [
12679
12694
  description: "Bind one Artifact to an existing same-Space Thread Live Preview, making the Artifact the durable entry point for that executable surface. Omit --thread-id to clear the binding; this changes no Artifact source/version and does not create or reconfigure a Computer.",
12680
12695
  inputSchema: {
12681
12696
  artifactId: string2().describe("the Artifact, art_…"),
12682
- threadId: string2().optional().describe("the configured Thread Live Preview to bind, thr_…; omit to clear")
12697
+ threadId: string2().optional().describe("the configured Thread Live Preview to bind, thr_… or a short id like BUD-34; omit to clear")
12683
12698
  },
12684
12699
  surfaces: ["cli"],
12685
12700
  toolset: "artifacts",
@@ -12759,7 +12774,7 @@ var ACTION_DEFINITIONS = [
12759
12774
  title: "Request a contribution or review",
12760
12775
  description: "Request a contribution or review on a Thread: omit aboutContributionId for a contribution answered via respond, or pass it for a review answered only by stamp; explicitly target yourself for a normal Inbox obligation, target other people, or leave it open. Choose completion/deadline and optionally opensAt/opensIn to keep it dormant until scheduled delivery; fulfill a self-target through respond or use cancel_request to retire it.",
12761
12776
  inputSchema: {
12762
- threadId: string2().describe("the thread the request is in, thr_…"),
12777
+ threadId: string2().describe("the thread the request is in, thr_… or a short id like BUD-34"),
12763
12778
  requestedAction: string2().optional().describe("a one-line 'what you're requesting'"),
12764
12779
  requestedType: _enum(CONTRIBUTION_TYPES).optional().describe("the contribution type you're HOPING for (e.g. evidence, decision) — a soft default on the responder's picker, never a constraint; omit for 'any contribution welcome'. Contribution asks only"),
12765
12780
  aboutContributionId: string2().optional().describe("PASS to request a REVIEW of this contribution (con_…, in the thread; met by a stamp, badges that card). OMIT to request a CONTRIBUTION on the thread (met by a respond)."),
@@ -12920,7 +12935,7 @@ var ACTION_DEFINITIONS = [
12920
12935
  title: "Read a thread",
12921
12936
  description: "Read one Thread as compact current context (distillate, requests, artifacts, recent tail, cursored unchanged checks) — not the durable transcript; pass view=full to read contribution bodies and attachments (including Markdown and authenticated URLs) and page history (contribLimit default 50) or all=true for the complete transcript. Read it before contributing so you can answer open requests correctly.",
12922
12937
  inputSchema: {
12923
- threadId: string2().describe("the thread id, e.g. thr_…"),
12938
+ threadId: string2().describe("the thread id, e.g. thr_…, or its short id, e.g. BUD-34"),
12924
12939
  view: _enum(["full", "compact"]).optional().describe("MCP/CLI/API default compact = bounded decision-ready context; full = transcript page"),
12925
12940
  cursor: string2().optional().describe("compact reads only: cursor from the previous compact response; if context is unchanged the response collapses to a tiny unchanged envelope"),
12926
12941
  recentLimit: number2().int().min(1).max(20).optional().describe("compact reads only: latest contributions to include (default 6, max 20)"),
@@ -13091,7 +13106,7 @@ var ACTION_DEFINITIONS = [
13091
13106
  title: "Link a thread to a goal",
13092
13107
  description: "Record that a thread contributes to a goal — the many-to-many link that surfaces the goal on the thread's space and lists the thread under the goal. Idempotent. Reach for this once a thread's work clearly serves a goal; use `list_goals` to find the goal id.",
13093
13108
  inputSchema: {
13094
- threadId: string2().describe("the contributing thread, thr_…"),
13109
+ threadId: string2().describe("the contributing thread, thr_… or a short id like BUD-34"),
13095
13110
  initiativeId: string2().describe("the goal it serves, ini_…")
13096
13111
  },
13097
13112
  surfaces: ["cli"],
@@ -13103,7 +13118,7 @@ var ACTION_DEFINITIONS = [
13103
13118
  title: "Unlink a thread from a goal",
13104
13119
  description: "Remove the link between a thread and a goal (the deliberate inverse of `link_thread_to_goal`). Idempotent. Reach for this when a thread no longer serves the goal it was attached to — the thread and the goal both stay; only the link is dropped.",
13105
13120
  inputSchema: {
13106
- threadId: string2().describe("the thread to unlink, thr_…"),
13121
+ threadId: string2().describe("the thread to unlink, thr_… or a short id like BUD-34"),
13107
13122
  initiativeId: string2().describe("the goal to unlink it from, ini_…")
13108
13123
  },
13109
13124
  surfaces: ["cli"],
@@ -13128,7 +13143,7 @@ var ACTION_DEFINITIONS = [
13128
13143
  description: "List compact goals attached to one Space, or a Thread's linked goals plus its available pick list. Space lists are compact cards; Thread lists page only the available `all` list and keep `linked` complete; view=summary returns 3 active goals; status pages named lifecycles before the page.",
13129
13144
  inputSchema: {
13130
13145
  spaceId: string2().optional().describe("a Space whose attached goals to list, spc_…"),
13131
- threadId: string2().optional().describe("a Thread whose linked and available goals to list, thr_…"),
13146
+ threadId: string2().optional().describe("a Thread whose linked and available goals to list, thr_… or a short id like BUD-34"),
13132
13147
  view: literal("summary").optional().describe("summary: Topics home — 3 most recently active goals (title + in-space linked Thread count). Ignores status. Omit for the attached list."),
13133
13148
  status: union([
13134
13149
  _enum(["active", "paused", "completed", "archived"]),
@@ -13182,6 +13197,7 @@ var ACTION_DEFINITIONS = [
13182
13197
  description: "Create a Space when work needs its own durable collaboration/governance boundary — its own membership, visibility, shared norms, and multiple durable areas; you become its first admin (org owner/admins always can, other members only when enabled), with open/private visibility and optional seeded members. If the work can live under an existing Space with the same people and governance, use a Topic instead.",
13183
13198
  inputSchema: {
13184
13199
  title: string2().min(1).describe("the space title"),
13200
+ key: SPACE_KEY_INPUT.optional().describe("thread short-id prefix (BUD in BUD-34): 1-10 letters/digits, starting with a letter, unique in the org; default: the title's first three letters"),
13185
13201
  purpose: string2().optional().describe("why this boundary exists and what it is around — commonly a Product/System, Program/Function, Portfolio/Network, or Practice/Community — plus its dominant work modes (Build, Operate, Coordinate, Discuss, Share) when that helps; plain prose, not metadata syntax"),
13186
13202
  visibility: _enum(["open", "private"]).optional().describe("open (default) or private (invite-only)"),
13187
13203
  memberProfileIds: array(string2()).optional().describe("org profile ids to seed as members — agents added directly, humans get a pending invite")
@@ -13198,6 +13214,7 @@ var ACTION_DEFINITIONS = [
13198
13214
  spaceId: string2().describe("the space, spc_…"),
13199
13215
  purpose: string2().optional().describe("why this boundary exists and what it is around — commonly a Product/System, Program/Function, Portfolio/Network, or Practice/Community — plus its dominant work modes (Build, Operate, Coordinate, Discuss, Share) when that helps; plain prose, not metadata syntax"),
13200
13216
  title: string2().optional().describe("a new title for the space"),
13217
+ key: SPACE_KEY_INPUT.optional().describe("a new thread short-id prefix (BUD in BUD-34), unique in the org; every thread's short id changes, the old ones stop resolving, and the old key stays reserved to this Space"),
13201
13218
  visibility: _enum(["open", "private"]).optional().describe("open or private (invite-only)"),
13202
13219
  stage: _enum(["exploration", "design", "implementation", "maintenance", "retired"]).optional().describe("set the lifecycle stage; retired archives the Space reversibly and restores with an active stage, but only when no Run is active/suspended and no App is serving"),
13203
13220
  attachWorkflow: string2().optional().describe("add a workflow to this Space's list: a built-in id (`standard`, `queue`, `content`, `experiment`, `funnel`) or a catalog `wfl_…` from `workflow_list`"),
@@ -13408,7 +13425,7 @@ var ACTION_DEFINITIONS = [
13408
13425
  title: "Inspect a thread (superadmin)",
13409
13426
  description: "Platform-operator only: read any thread by id across orgs (its contributions + authors), bypassing the per-org membership boundary for oversight.",
13410
13427
  inputSchema: {
13411
- threadId: string2().min(1).describe("the thread id, e.g. thr_…")
13428
+ threadId: string2().min(1).describe("the canonical thread id, e.g. thr_… (admin reads are cross-org)")
13412
13429
  },
13413
13430
  surfaces: ["cli"],
13414
13431
  toolset: "admin",
@@ -13429,7 +13446,7 @@ var ACTION_DEFINITIONS = [
13429
13446
  description: "List compact goals attached to one Space, or the linked and available goals for one Thread. Space pages omit relatedThreads; Thread pages keep linked complete and page only the available `all` list; view=summary returns 3 active goals; status pages named lifecycles before the page; it cannot mutate a goal.",
13430
13447
  inputSchema: {
13431
13448
  spaceId: string2().optional().describe("a Space whose attached goals to list, spc_…"),
13432
- threadId: string2().optional().describe("a Thread whose linked and available goals to list, thr_…"),
13449
+ threadId: string2().optional().describe("a Thread whose linked and available goals to list, thr_… or a short id like BUD-34"),
13433
13450
  view: literal("summary").optional().describe("summary: Topics home — 3 most recently active goals (title + in-space linked Thread count). Ignores status. Omit for the attached list."),
13434
13451
  status: union([
13435
13452
  _enum(["active", "paused", "completed", "archived"]),
@@ -13461,7 +13478,7 @@ var ACTION_DEFINITIONS = [
13461
13478
  threadIds: array(string2()).optional().describe("create: threads to link at birth"),
13462
13479
  id: string2().optional().describe("update/set_status: the goal, ini_…"),
13463
13480
  status: _enum(["active", "paused", "completed", "archived"]).optional().describe("set_status: the new lifecycle state"),
13464
- threadId: string2().optional().describe("link_thread/unlink_thread: the thread, thr_…"),
13481
+ threadId: string2().optional().describe("link_thread/unlink_thread: the thread, thr_… or a short id like BUD-34"),
13465
13482
  initiativeId: string2().optional().describe("link/unlink/attach/detach: the goal, ini_…")
13466
13483
  },
13467
13484
  surfaces: ["mcp"],
@@ -13645,7 +13662,7 @@ var ACTION_DEFINITIONS = [
13645
13662
  computerSessionId: string2().optional().describe("create: the attached computer session that produced it, cms_…"),
13646
13663
  sourceContributionIds: array(string2()).optional().describe("create: contributions it distills"),
13647
13664
  artifactId: string2().optional().describe("edit/set_live_preview/set_snapshot: the Artifact, art_…"),
13648
- threadId: string2().optional().describe("set_live_preview: the configured Thread Live Preview, thr_…; omit to clear the binding"),
13665
+ threadId: string2().optional().describe("set_live_preview: the configured Thread Live Preview, thr_… or a short id like BUD-34; omit to clear the binding"),
13649
13666
  baseVersion: number2().optional().describe("edit: the version you READ (from get/create) — stale base is rejected with the current source"),
13650
13667
  patches: array(object({ old: string2(), new: string2() })).optional().describe("edit: exact-match hunks applied in order, atomically; each old must match exactly once"),
13651
13668
  note: string2().optional().describe("edit: one-line summary of what changed"),
@@ -14320,7 +14337,7 @@ var ACTION_DEFINITIONS = [
14320
14337
  topicId: string2().optional().describe("topic_guidance/topic_lanes: the topic, top_…"),
14321
14338
  guidance: proseList("space_guidance/topic_guidance: full list, replaces; [] clears").optional(),
14322
14339
  contributionLanes: proseList("space_lanes/topic_lanes: full list of ways to help, replaces; [] clears").optional(),
14323
- threadId: string2().optional().describe("ways_to_help: the thread, thr_…"),
14340
+ threadId: string2().optional().describe("ways_to_help: the thread, thr_… or a short id like BUD-34"),
14324
14341
  waysToHelp: proseList("ways_to_help: full list, replaces; [] clears").optional()
14325
14342
  },
14326
14343
  surfaces: ["mcp"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.24.3",
3
+ "version": "0.24.4",
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",
@@ -27,7 +27,7 @@
27
27
  "access": "public"
28
28
  },
29
29
  "scripts": {
30
- "arbor": "tsx src/bin.ts",
30
+ "arbor": "vpx src/bin.ts",
31
31
  "build": "bun build ./src/bin.ts --target=node --outfile=dist/arbor.js",
32
32
  "test": "vp test run --passWithNoTests",
33
33
  "typecheck": "tsc -b",
@@ -38,7 +38,6 @@
38
38
  "@arbor/core": "workspace:*",
39
39
  "@types/node": "^26.2.0",
40
40
  "just-bash": "3.4.2",
41
- "tsx": "^4.20.6",
42
41
  "typescript": "^5.8.0",
43
42
  "vite-plus": "catalog:",
44
43
  "zod": "^4.4.3"