@lambdacurry/arbor 0.8.2 → 0.8.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 +71 -29
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -1594,9 +1594,13 @@ var requests = sqliteTable("requests", {
1594
1594
  audience: text("audience", { mode: "json" }).$type().notNull(),
1595
1595
  completionPolicy: text("completion_policy", { mode: "json" }).$type().notNull(),
1596
1596
  status: text("status").$type().notNull().default("open"),
1597
+ opensAt: ts("opens_at"),
1597
1598
  expiresAt: ts("expires_at"),
1598
1599
  createdAt: ts("created_at").notNull()
1599
- }, (t) => ({ threadIdx: index("requests_thread_idx").on(t.threadId) }));
1600
+ }, (t) => ({
1601
+ threadIdx: index("requests_thread_idx").on(t.threadId),
1602
+ statusOpensIdx: index("requests_status_opens_idx").on(t.status, t.opensAt)
1603
+ }));
1600
1604
  var inboxItems = sqliteTable("inbox_items", {
1601
1605
  id: text("id").primaryKey(),
1602
1606
  targetProfileId: text("target_profile_id").notNull().references(() => profiles.id),
@@ -16042,7 +16046,7 @@ config(en_default());
16042
16046
  // ../actions/src/index.ts
16043
16047
  var ORIENTATION = `Arbor is your team's deliberation room and shared memory — people and agents settle typed work here, and Arbor remembers what's decided. To work well:
16044
16048
 
16045
- 1. RECALL FIRST — but Arbor is MEMORY, NOT TRUTH. Run \`recall\` before re-deriving or restating anything — it may already be settled; cite prior work ([label](#con_…)) and build on it. Phrase the query in PROBLEM-LANGUAGE (a natural-language question — "how do agents handle X"), not extracted keywords; it ranks better. Empty recall is itself worth noting. A contribution records what was true when it was WRITTEN, so before you assert the CURRENT state of anything outside Arbor — a PR, a build, a deploy, a config — check the live source; another contribution is not evidence of the present, and neither is a local copy of something whose home is elsewhere. WHY: a room where everyone re-derives is just a chat log — but a room that mistakes its own memory for the world confidently reports blockers that no longer exist.
16049
+ 1. RECALL FIRST — but Arbor is MEMORY, NOT TRUTH. Run \`recall\` before re-deriving or restating anything — it may already be settled; cite prior work ([label](#con_…)) and build on it. Phrase the query in PROBLEM-LANGUAGE (a natural-language question — "how do agents handle X"), not extracted keywords; it ranks better. Empty recall is itself worth noting. A contribution records what was true when it was WRITTEN, so before you assert the CURRENT state of anything outside Arbor — a PR, a build, a deploy, a config — check the live source; another contribution is not evidence of the present, and neither is a local copy of something whose home is elsewhere. And when you DO check, post the RECEIPT with the claim (AD-209): attach the actual output/screenshot (an attached file becomes a durable artifact carrying who-captured-it and when, citable as #art_… forever) or name exactly what you checked and when ("CI run #841, green, checked just now") — a "verified" with no receipt is a claim the next reader must take on faith or re-derive. When a receipted claim has AGED and matters again, don't re-trust it and don't silently re-argue it: \`request\` a re-check ("re-run this check"), and whoever runs it answers through the request with fresh evidence. WHY: a room where everyone re-derives is just a chat log — but a room that mistakes its own memory for the world confidently reports blockers that no longer exist, and this week's failures were exactly that: stale claims re-asserted as current because nothing distinguished a receipted observation from confident prose. And orient to the ROOM the way you orient to the record: a space's purpose, guidance, and goals (\`space_get\`) are how you learn to operate in it — read them before contributing.
16046
16050
  2. CONTRIBUTE typed points — but ADD ONLY WHAT'S ADDITIVE (AD-205). Ask what the most additive move is, not whether to say something: if your reaction to a point already on the record fits in one line — agree OR disagree — STAMP it (vouch, or push back with a one-line why), don't restate it; if you'd only echo consensus, reviewing IS the contribution and staying out is fine. When you DO contribute, it's ONE point, with the type that names your move (proposal / critique / question / evidence / risk / correction / assertion / decision). Markdown welcome; put references IN your prose (a URL or [label](#con_…) becomes a navigable reference). Prose refs are CITATIONS — they never move your contribution in the thread, so cite freely; to REPLY under a specific contribution, pass links: [{rel: 'inReplyTo', targetId}] (AD-196). WHY: a thread where every agent restates the consensus is noise — the record is strongest when each point appears ONCE and gets vouched (or contested) with a stamp, not re-said; and one typed point is reviewable on its own, so a synthesis citing five points should read as the most top-level thing in the thread, not as a reply to the first one it mentions.
16047
16051
  3. ANSWER through requests. When \`inbox\` or a thread shows an open request you can meet, answer THROUGH it — \`respond\` to it, or \`stamp\` the contribution a review request is about — so it completes and the requester is notified. WHY: a plain reply that merely happens to answer leaves their request hanging (the most common failure).
16048
16052
  4. REVIEW honestly; promote the standout, sparingly. \`stamp\` to vouch or push back with a one-line why (you can't stamp your own work — request a review via \`request\`). PROMOTE a contribution/artifact only when it's the standout the org should find FIRST (the \uD83C\uDF96️). One deliberate exception (AD-200): in a STANDING thread, periodically promoting a distilling synthesis IS the job — it's how an open-forever lane compresses for newcomers and recall, not applause inflation; promoting your own synthesis there is fine (only stamps bar self-review). WHY: promotion is curation, not applause — and it's about an OUTPUT, never a whole thread (a thread RESOLVES; it is never "promoted").
@@ -16094,7 +16098,7 @@ var ACTIONS = [
16094
16098
  threadId: exports_external.string().describe("the thread id, e.g. thr_…"),
16095
16099
  type: exports_external.enum(CONTRIBUTION_TYPES).describe("the contribution type (AD-066 taxonomy)"),
16096
16100
  body: exports_external.string().min(1).describe("the contribution text"),
16097
- summary: exports_external.string().max(300).optional().describe("optional ≤300-char gistbecomes the recall snippet AND sharpens recall for long contributions (it's prepended to the embedded text); write one when the body is long"),
16101
+ summary: exports_external.string().max(500).optional().describe("optional gist, 1-2 short sentences HARD LIMIT 500 characters (the request is rejected past it, so keep well under). Becomes the recall snippet AND sharpens recall for long contributions (it's prepended to the embedded text); write one when the body is long"),
16098
16102
  confidence: exports_external.number().int().min(0).max(100).optional().describe("optional 0–100 confidence"),
16099
16103
  mentions: exports_external.array(exports_external.object({
16100
16104
  kind: exports_external.enum(["person", "contribution", "artifact"]),
@@ -16114,7 +16118,7 @@ var ACTIONS = [
16114
16118
  inputSchema: {
16115
16119
  contributionId: exports_external.string().describe("your contribution's id, con_…"),
16116
16120
  body: exports_external.string().min(1).describe("the replacement markdown body"),
16117
- summary: exports_external.string().max(300).optional().describe("optional ≤300-char gist — omit to leave unchanged, empty string to clear")
16121
+ summary: exports_external.string().max(500).optional().describe("optional gist, 1-2 short sentences (HARD LIMIT 500 characters) — omit to leave unchanged, empty string to clear")
16118
16122
  },
16119
16123
  surfaces: ["mcp", "cli"],
16120
16124
  toolset: "loop",
@@ -16155,7 +16159,7 @@ var ACTIONS = [
16155
16159
  {
16156
16160
  name: "create_topic",
16157
16161
  title: "Create a topic",
16158
- description: "Open a NEW topic in a space — a durable area of work that will hold multiple threads. Check `tree` first and prefer an existing topic: structure should be scarce, and a topic that holds one thread was probably a thread.",
16162
+ description: "Open a NEW topic in a space — a durable area of work that will hold multiple threads. Check `tree` first and prefer an existing topic: structure should be scarce, and a topic that holds one thread was probably a thread. After creating, set its guidance (set_topic_guidance) so contributors learn the topic's habits.",
16159
16163
  inputSchema: {
16160
16164
  spaceId: exports_external.string().describe("the space to create the topic in, spc_…"),
16161
16165
  title: exports_external.string().min(1).describe("the topic's name — an area of work, not a question"),
@@ -16177,10 +16181,22 @@ var ACTIONS = [
16177
16181
  toolset: "spaces",
16178
16182
  run: forward("topic.update")
16179
16183
  },
16184
+ {
16185
+ name: "set_space_guidance",
16186
+ title: "Set a space's guidance",
16187
+ description: "Set a SPACE's SOFT guidance — the how-we-work-here norms for the whole space (culture/quality, AD-062/063), e.g. 'recall before re-deriving', 'promote the standout, sparingly'. Soft norms only, read not enforced; hard governance (permissions, rate, join) is separate. Members READ it (via space_get) to learn how the room operates — it's broader than `set_topic_guidance` (one topic's habits) and distinct from `request` (obligations). Replaces the whole list; pass [] to clear.",
16188
+ inputSchema: {
16189
+ spaceId: exports_external.string().describe("the space, spc_…"),
16190
+ guidance: exports_external.array(exports_external.string()).describe("the full guidance list — replaces the existing one; [] clears it")
16191
+ },
16192
+ surfaces: ["cli"],
16193
+ toolset: "spaces",
16194
+ run: forward("space.setGuidance")
16195
+ },
16180
16196
  {
16181
16197
  name: "create_thread",
16182
16198
  title: "Open a thread",
16183
- description: "Open a NEW deliberation thread under a topic, named by its OBJECTIVE (the question to settle or outcome to reach). Check `tree` first and prefer contributing to an existing thread — open a new one only when the deliberation genuinely doesn't fit anywhere; then make the first contribution yourself.",
16199
+ description: "Open a NEW deliberation thread under a topic, named by its OBJECTIVE (the question to settle or outcome to reach). Check `tree` first and prefer contributing to an existing thread — open a new one only when the deliberation genuinely doesn't fit anywhere; then make the first contribution yourself. After opening, set its waysToHelp (set_ways_to_help) so others see how to pitch in.",
16184
16200
  inputSchema: {
16185
16201
  spaceId: exports_external.string().describe("the space, spc_…"),
16186
16202
  topicId: exports_external.string().describe("the topic to file it under, top_…"),
@@ -16337,7 +16353,7 @@ var ACTIONS = [
16337
16353
  {
16338
16354
  name: "request",
16339
16355
  title: "Request a contribution or review",
16340
- description: "Request input on a thread (AD-161). OMIT `aboutContributionId` to ask for a CONTRIBUTION — evidence, a proposal, or a decision you need — answered via `respond`. PASS it to ask for a REVIEW of that contribution — answered ONLY by a `stamp`, so never wrap a decision as a review. Name targets (an inbox item each) or leave it open; completion is software-computed (first | quorum | all-targets | deadline | explicit); every request expires (default 14 days)",
16356
+ description: 'Request input on a thread (AD-161). OMIT `aboutContributionId` to ask for a CONTRIBUTION — evidence, a proposal, or a decision you need — answered via `respond`. PASS it to ask for a REVIEW of that contribution — answered ONLY by a `stamp`, so never wrap a decision as a review. Name targets (an inbox item each) or leave it open; completion is software-computed (first | quorum | all-targets | deadline | explicit); every request expires (default 14 days). SEND LATER: pass `opensAt` (ISO) or `opensIn` ("2h", "3d", "1w") to schedule the request — it stays dormant (no inbox delivery, no notification) until that time, then opens normally; default expiry runs 14 days from OPEN. Reschedule via the CLI `reschedule_request` (or cancel + re-request), retire with `cancel_request`.',
16341
16357
  inputSchema: {
16342
16358
  threadId: exports_external.string().describe("the thread the request is in, thr_…"),
16343
16359
  requestedAction: exports_external.string().optional().describe("a one-line 'what you're requesting'"),
@@ -16346,12 +16362,27 @@ var ACTIONS = [
16346
16362
  targetProfileIds: exports_external.array(exports_external.string()).optional().describe("targeted recipients (omit → open board)"),
16347
16363
  completion: exports_external.enum(["first", "quorum", "all-targets", "deadline", "explicit"]),
16348
16364
  quorumN: exports_external.number().int().min(1).optional().describe("required when completion=quorum"),
16349
- expiresAt: exports_external.string().optional().describe("ISO-8601 deadline (default: 14 days from creation, AD-167)")
16365
+ expiresAt: exports_external.string().optional().describe("ISO-8601 deadline (default: 14 days from creation — or from opensAt when scheduled, AD-167/SFR-360)"),
16366
+ opensAt: exports_external.string().optional().describe("SEND LATER (SFR-360): ISO-8601 instant to open at — the request stays dormant until then. Must be future and before expiresAt"),
16367
+ opensIn: exports_external.string().optional().describe('SEND LATER sugar: a duration from now — "30m", "2h", "3d", "1w". opensAt wins if both')
16350
16368
  },
16351
16369
  surfaces: ["mcp", "cli"],
16352
16370
  toolset: "loop",
16353
16371
  run: forward("request.create")
16354
16372
  },
16373
+ {
16374
+ name: "reschedule_request",
16375
+ title: "Reschedule a scheduled request",
16376
+ description: 'Move a SCHEDULED request\'s open time (SFR-360) — yours only (or org owner). Takes `opensAt` (ISO) or `opensIn` ("2h", "3d", "1w") like `request`. Only works while the request is still dormant; once it opens it\'s live and can\'t be rescheduled. A default expiry moves with the new open time; an explicit one stays.',
16377
+ inputSchema: {
16378
+ requestId: exports_external.string().describe("the scheduled request, req_…"),
16379
+ opensAt: exports_external.string().optional().describe("new ISO-8601 open instant"),
16380
+ opensIn: exports_external.string().optional().describe('new open time as a duration from now — "2h", "3d", "1w"')
16381
+ },
16382
+ surfaces: ["cli"],
16383
+ toolset: "loop",
16384
+ run: forward("request.reschedule")
16385
+ },
16355
16386
  {
16356
16387
  name: "respond",
16357
16388
  title: "Respond to a request",
@@ -16381,7 +16412,7 @@ var ACTIONS = [
16381
16412
  {
16382
16413
  name: "cancel_request",
16383
16414
  title: "Cancel a request",
16384
- description: "Cancel an OPEN request you raised (or any open request, if you're the org owner) — it moves to a terminal `cancelled` state and the inbox items it fanned out are SILENTLY withdrawn (they leave recipients' inboxes, no notification). Use this when a request is no longer needed. Only open requests can be cancelled (a completed/expired one can't). Returns `status: cancelled` (success) + `withdrawn`: how many recipients' inbox items were retracted — `0` just means it hadn't reached anyone yet, NOT a failure.",
16415
+ description: "Cancel an OPEN or SCHEDULED request you raised (or any such request, if you're the org owner) — it moves to a terminal `cancelled` state and any inbox items it fanned out are SILENTLY withdrawn (they leave recipients' inboxes, no notification). Use this when a request is no longer needed. A completed/expired one can't be cancelled. Returns `status: cancelled` (success) + `withdrawn`: how many recipients' inbox items were retracted — `0` just means it hadn't reached anyone yet (a scheduled request always withdraws 0), NOT a failure.",
16385
16416
  inputSchema: {
16386
16417
  requestId: exports_external.string().describe("the open request to cancel, req_…")
16387
16418
  },
@@ -16698,7 +16729,7 @@ var ACTIONS = [
16698
16729
  {
16699
16730
  name: "space_create",
16700
16731
  title: "Create a space",
16701
- description: "Create a top-level space — the org-foundation container topics and threads live under. ORG OWNER/ADMIN only (a non-admin gets a clean 403): stand up a new area of work, e.g. a 'Saffron' space for cross-agent infra/tooling deliberation. Pass visibility private for invite-only (default open). Pass memberProfileIds to seed the space with members in one step — agents are added directly, humans get a pending invite to accept.",
16732
+ description: "Create a top-level space — the org-foundation container topics and threads live under. ORG OWNER/ADMIN only (a non-admin gets a clean 403): stand up a new area of work, e.g. a 'Saffron' space for cross-agent infra/tooling deliberation. Pass visibility private for invite-only (default open). Pass memberProfileIds to seed the space with members in one step — agents are added directly, humans get a pending invite to accept. After creating, set the space's guidance (the `charter` tool's space_guidance verb) and its goals (create_goal) so members and agents know how to operate here.",
16702
16733
  inputSchema: {
16703
16734
  title: exports_external.string().min(1).describe("the space title"),
16704
16735
  purpose: exports_external.string().optional().describe("optional one-line purpose"),
@@ -16811,7 +16842,7 @@ var ACTIONS = [
16811
16842
  {
16812
16843
  name: "goal",
16813
16844
  title: "Work with goals",
16814
- description: "GOALS (initiatives) — the wide 'why' threads serve toward (AD-146/180). verb=get (id — one goal read fully, ANY status incl. archived), create (spaceId+title, optional purpose/threadIds — the creating space becomes its HOME), list (threadIdthe goals that thread's space offers), update (id + title/purpose), set_status (id+status: active|paused|completed|archived — completed = reached, archived = retired from pick lists), delete (id), link_thread/unlink_thread (threadId+initiativeId), attach_space/detach_space (initiativeId+spaceId — surface a goal in MORE spaces).",
16845
+ description: "GOALS (initiatives) — the wide 'why' threads serve toward (AD-146/180). verb=get (id — one goal read fully, ANY status incl. archived), create (spaceId+title, optional purpose/threadIds — the creating space becomes its HOME), list (spaceIda space's goals, OR threadId — a thread's linked goals), update (id + title/purpose), set_status (id+status: active|paused|completed|archived — completed = reached, archived = retired from pick lists), delete (id), link_thread/unlink_thread (threadId+initiativeId), attach_space/detach_space (initiativeId+spaceId — surface a goal in MORE spaces).",
16815
16846
  inputSchema: {
16816
16847
  verb: exports_external.enum([
16817
16848
  "create",
@@ -16824,7 +16855,7 @@ var ACTIONS = [
16824
16855
  "attach_space",
16825
16856
  "detach_space"
16826
16857
  ]).describe("which goal move to make"),
16827
- spaceId: exports_external.string().optional().describe("create: HOME space · attach/detach_space: the target space, spc_…"),
16858
+ spaceId: exports_external.string().optional().describe("create: HOME space · list: a space's goals · attach/detach_space: the target space, spc_…"),
16828
16859
  title: exports_external.string().optional().describe("create/update: the goal's name — an outcome, not a task"),
16829
16860
  purpose: exports_external.string().optional().describe("create/update: one or two lines on what reaching it means"),
16830
16861
  threadIds: exports_external.array(exports_external.string()).optional().describe("create: threads to link at birth"),
@@ -16835,18 +16866,28 @@ var ACTIONS = [
16835
16866
  },
16836
16867
  surfaces: ["mcp"],
16837
16868
  toolset: "goals",
16838
- run: dispatch({
16839
- get: "initiative.get",
16840
- create: "initiative.create",
16841
- list: "initiative.forThread",
16842
- update: "initiative.update",
16843
- set_status: "initiative.setStatus",
16844
- delete: "initiative.delete",
16845
- link_thread: "initiative.linkThread",
16846
- unlink_thread: "initiative.unlinkThread",
16847
- attach_space: "initiative.attachSpace",
16848
- detach_space: "initiative.detachSpace"
16849
- })
16869
+ run: (ex, input) => {
16870
+ const { verb, spaceId, threadId } = input;
16871
+ if (verb === "list") {
16872
+ if (typeof spaceId === "string")
16873
+ return ex.call("initiative.listForSpace", { spaceId });
16874
+ if (typeof threadId === "string")
16875
+ return ex.call("initiative.forThread", { threadId });
16876
+ return Promise.reject(new Error("goal list requires a spaceId (a space's goals) or a threadId (a thread's goals)"));
16877
+ }
16878
+ return dispatch({
16879
+ get: "initiative.get",
16880
+ create: "initiative.create",
16881
+ list: "initiative.forThread",
16882
+ update: "initiative.update",
16883
+ set_status: "initiative.setStatus",
16884
+ delete: "initiative.delete",
16885
+ link_thread: "initiative.linkThread",
16886
+ unlink_thread: "initiative.unlinkThread",
16887
+ attach_space: "initiative.attachSpace",
16888
+ detach_space: "initiative.detachSpace"
16889
+ })(ex, input);
16890
+ }
16850
16891
  },
16851
16892
  {
16852
16893
  name: "membership",
@@ -16991,14 +17032,14 @@ var ACTIONS = [
16991
17032
  {
16992
17033
  name: "charter",
16993
17034
  title: "Set the guidance surfaces",
16994
- description: "The guidance you WRITE (read back via space_get/topic_get/thread_get). verb=space_charter (spaceId+charter — how YOU operate in this space, AD-152; org admins may pass profileId to bootstrap another member's), topic_guidance (topicId+guidance[] — the topic's soft norms, replaces the list, [] clears), ways_to_help (threadId+waysToHelp[] — a thread's curated pitch-in list; guidance, never obligation — obligations are `request`).",
17035
+ description: "The guidance you WRITE (read back via space_get/topic_get/thread_get). verb=space_charter (spaceId+charter — how YOU operate in this space, AD-152; org admins may pass profileId to bootstrap another member's), space_guidance (spaceId+guidance[] — the SPACE's soft norms/how-we-work-here, replaces the list, [] clears), topic_guidance (topicId+guidance[] — the topic's soft norms, replaces the list, [] clears), ways_to_help (threadId+waysToHelp[] — a thread's curated pitch-in list; guidance, never obligation — obligations are `request`).",
16995
17036
  inputSchema: {
16996
- verb: exports_external.enum(["space_charter", "topic_guidance", "ways_to_help"]).describe("which guidance surface to set"),
16997
- spaceId: exports_external.string().optional().describe("space_charter: the space, spc_…"),
17037
+ verb: exports_external.enum(["space_charter", "space_guidance", "topic_guidance", "ways_to_help"]).describe("which guidance surface to set"),
17038
+ spaceId: exports_external.string().optional().describe("space_charter/space_guidance: the space, spc_…"),
16998
17039
  charter: exports_external.string().optional().describe("space_charter: the text; empty string clears"),
16999
17040
  profileId: exports_external.string().optional().describe("space_charter admin override: whose charter"),
17000
17041
  topicId: exports_external.string().optional().describe("topic_guidance: the topic, top_…"),
17001
- guidance: exports_external.array(exports_external.string()).optional().describe("topic_guidance: full list, replaces; [] clears"),
17042
+ guidance: exports_external.array(exports_external.string()).optional().describe("space_guidance/topic_guidance: full list, replaces; [] clears"),
17002
17043
  threadId: exports_external.string().optional().describe("ways_to_help: the thread, thr_…"),
17003
17044
  waysToHelp: exports_external.array(exports_external.string()).optional().describe("ways_to_help: full list, replaces; [] clears")
17004
17045
  },
@@ -17006,6 +17047,7 @@ var ACTIONS = [
17006
17047
  toolset: "spaces",
17007
17048
  run: dispatch({
17008
17049
  space_charter: "space.setCharter",
17050
+ space_guidance: "space.setGuidance",
17009
17051
  topic_guidance: "topic.update",
17010
17052
  ways_to_help: "thread.update"
17011
17053
  })
@@ -17697,7 +17739,7 @@ async function renderMe(ctx, action) {
17697
17739
  ` : "") + spaceLines;
17698
17740
  emitDual(me, human, action, ctx);
17699
17741
  }
17700
- var CLI_NOTE = `On this CLI, before your first write: commands are NOUN-VERB (\`thread get\`, \`space get\`, not \`get thread\`). The underscore tool-names you see in MCP, recall, and docs (\`set_space_charter\`, \`transition_thread\`) work as CLI commands VERBATIM too — \`set_space_charter …\` and \`set space charter …\` are the same command, either form. A single-argument command also takes a bare positional — \`recall "your question"\`, \`thread get thr_…\` — so you don't have to name the obvious flag. Flag names are kebab-derived from the inputs (\`--thread-id\`, \`--request-id\`, \`--contribution-id\` — not \`--thread\`/\`--request\`), so check \`arbor help\` or \`arbor <command> --help\` (now focused on that command's flags) instead of guessing. Pass long/markdown bodies via \`--body-file -\` (stdin), never shell-quoted; a one-line \`--summary\` (≤300 chars) on a long contribution becomes its recall snippet. List inputs (e.g. \`--capabilities\`) accept EITHER a comma list (\`--capabilities a,b,c\`) OR a repeated flag (\`--capabilities a --capabilities b\`) — both build the array. \`tree\` is a glanceable map (default depth \`topics\`); drill down with \`space get\`/\`topic get\`/\`thread get\` rather than expanding the whole tree. If \`inbox\` is empty, that's "nothing needs you" — but if you're unsure your auth resolved, \`whoami\` confirms it.`;
17742
+ var CLI_NOTE = `On this CLI, before your first write: commands are NOUN-VERB (\`thread get\`, \`space get\`, not \`get thread\`). The underscore tool-names you see in MCP, recall, and docs (\`set_space_charter\`, \`transition_thread\`) work as CLI commands VERBATIM too — \`set_space_charter …\` and \`set space charter …\` are the same command, either form. A single-argument command also takes a bare positional — \`recall "your question"\`, \`thread get thr_…\` — so you don't have to name the obvious flag. Flag names are kebab-derived from the inputs (\`--thread-id\`, \`--request-id\`, \`--contribution-id\` — not \`--thread\`/\`--request\`), so check \`arbor help\` or \`arbor <command> --help\` (now focused on that command's flags) instead of guessing. Pass long/markdown bodies via \`--body-file -\` (stdin), never shell-quoted; a one-line \`--summary\` (1-2 short sentences, hard limit 500 chars) on a long contribution becomes its recall snippet. List inputs (e.g. \`--capabilities\`) accept EITHER a comma list (\`--capabilities a,b,c\`) OR a repeated flag (\`--capabilities a --capabilities b\`) — both build the array. \`tree\` is a glanceable map (default depth \`topics\`); drill down with \`space get\`/\`topic get\`/\`thread get\` rather than expanding the whole tree. If \`inbox\` is empty, that's "nothing needs you" — but if you're unsure your auth resolved, \`whoami\` confirms it.`;
17701
17743
  function renderOrient(ctx) {
17702
17744
  emitDual({ orientation: ORIENTATION, cliNote: CLI_NOTE }, `${ORIENTATION}
17703
17745
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.8.2",
3
+ "version": "0.8.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",