@lambdacurry/arbor 0.20.21 → 0.20.23

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 +21 -17
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -16725,14 +16725,14 @@ var recallHit = exports_external.looseObject({
16725
16725
  score: exports_external.number(),
16726
16726
  excerpt: exports_external.string(),
16727
16727
  space: spaceRef.nullable(),
16728
- url: exports_external.string(),
16728
+ url: nullableString,
16729
16729
  createdAt: timestamp
16730
16730
  });
16731
16731
  var contributionRef = exports_external.looseObject({
16732
16732
  id,
16733
16733
  objectType: exports_external.string(),
16734
16734
  excerpt: exports_external.string(),
16735
- url: exports_external.string(),
16735
+ url: nullableString,
16736
16736
  createdAt: timestamp,
16737
16737
  space: spaceRef.nullable(),
16738
16738
  crossSpace: exports_external.boolean()
@@ -18193,7 +18193,7 @@ var CONTRIBUTION_ADD_LINK_RELS = [
18193
18193
  ];
18194
18194
  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:
18195
18195
 
18196
- 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. In a large Space, don't search the whole org by habit: use \`tree\` to choose the room, then scope \`recall\` with \`space\`/\`topic\`/\`thread\` before deeper reads. 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: \`tree\` is the map AND the way in — it carries each room's \`lanesForYou\`, the durable contribution lanes that match what you said you do; follow one into \`space_get\`/\`topic_get\`, where the room's purpose, guidance, goals, and full lane list live. A lane is an invitation, never an obligation: what you OWE is only ever in \`inbox\`.
18196
+ 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. In a large Space, don't search the whole org by habit: use \`tree\` to choose the room, then scope \`recall\` with \`space\`/\`topic\`/\`thread\` before deeper reads. On that map, \`activeThreadCount\` is the current working set (active/stuck/needs-review/standing), while \`status\` is the Topic attention rollup: \`stuck\` means any stuck Thread; \`attention\` means needs-review or an open request; \`healthy\` means neither. 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: \`tree\` is the map AND the way in — it carries each room's \`lanesForYou\`, the durable contribution lanes that match what you said you do; follow one into \`space_get\`/\`topic_get\`, where the room's purpose, guidance, goals, and full lane list live. A lane is an invitation, never an obligation: what you OWE is only ever in \`inbox\`.
18197
18197
  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.
18198
18198
  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).
18199
18199
  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").
@@ -18225,6 +18225,7 @@ function dispatch(map2, reshape) {
18225
18225
  return ex.call(op, reshape && verb ? reshape(verb, rest) : rest);
18226
18226
  };
18227
18227
  }
18228
+ var NOTIFICATION_TRIAGE_DESCRIPTION = "READ ONLY: List your awareness feed newest first with unseen count and derived triage class: `settled-context` = settled Thread context; `owed-by-me` = an open request pointing to `inbox`; `judgment-available` = live engagement inviting judgment; `closed-loop` = your request completed; `room-motion` = ambient activity. Notifications are FYI, not a second obligation surface: `inbox` alone contains work owed by you; this cannot mark notifications read or modify inbox obligations.";
18228
18229
  var PAGINATION_INPUT = {
18229
18230
  limit: exports_external.number().int().min(1).optional().describe("max items to return — enables pagination"),
18230
18231
  cursor: exports_external.string().optional().describe("opaque cursor from a prior response's nextCursor (use with --limit)")
@@ -18300,7 +18301,7 @@ var ACTION_DEFINITIONS = [
18300
18301
  {
18301
18302
  name: "recall",
18302
18303
  title: "Recall existing knowledge",
18303
- description: "Search Arbor for what's already known before you re-derive an answer — returns ranked prior contributions, artifacts, and decisions scoped to your org. When you know the room, especially in a large Space, pass space/topic/thread to keep recall inside that working set before deeper reads.",
18304
+ description: "READ ONLY: Search Arbor semantically for existing contributions, artifacts, and decisions. Use `tree` for lifecycle/attention routing; once you know the area, pass space/topic/thread to keep recall inside that working set before targeted reads.",
18304
18305
  inputSchema: {
18305
18306
  query: exports_external.string().min(1).describe("what you want to recall, in natural language"),
18306
18307
  space: exports_external.string().optional().describe("optional space id to scope the search"),
@@ -18610,7 +18611,7 @@ var ACTION_DEFINITIONS = [
18610
18611
  {
18611
18612
  name: "computer_run_receipt",
18612
18613
  title: "Read a run receipt",
18613
- description: "READ ONLY: Inspect one Run's durable receipt during or after execution when you need purpose, placement, durability, recoverable operation state, activity, or terminal outcome. Returns compact Run history and assessments, including durable operation receipts, not raw command transcripts or process output.",
18614
+ description: "READ ONLY: Inspect one Run's durable receipt during or after execution, including its Run-owned operation/activity state; use this instead of parent computer_status to establish whether an isolated Run still has work in flight. Returns compact history/assessments and durable operation receipts, not raw command transcripts or process output.",
18614
18615
  inputSchema: {
18615
18616
  runId: exports_external.string().describe("the run to read, run_… (from computer_run_start or computer_runs)")
18616
18617
  },
@@ -18681,7 +18682,7 @@ var ACTION_DEFINITIONS = [
18681
18682
  {
18682
18683
  name: "computer_status",
18683
18684
  title: "Inspect a computer",
18684
- description: "READ ONLY: Inspect live Computer capabilities, runtime/process state, and the declared profile when computer_open did not answer a current operational question. Use get_computer instead for durable recipe, generation, and snapshot lineage.",
18685
+ description: "READ ONLY: Inspect the live PARENT Thread Computer's capabilities, runtime/process state, and declared profile. This does not report isolated Run command state; use computer_run_receipt for a Run's operations, or get_computer for durable recipe/generation/snapshot lineage.",
18685
18686
  inputSchema: {
18686
18687
  computerSessionId: exports_external.string().describe("the computerSessionId returned by computer_open, cms_…")
18687
18688
  },
@@ -19154,7 +19155,7 @@ var ACTION_DEFINITIONS = [
19154
19155
  {
19155
19156
  name: "notifications",
19156
19157
  title: "List your notifications",
19157
- description: "List the awareness feed of activity involving you — stamps on your work, replies in your threads, @-mentions, and your completed requests — newest first, with an unseen count. Each item carries a triage `class` (AD-182) derived from thread state: `settled-context` (thread resolved — durable context, never live work), `owed-by-me` (an open ask targets you — go to `inbox`, this row is just a pointer), `judgment-available` (your work was engaged in a live thread — an invitation, not an obligation), `closed-loop` (your ask completed), `room-motion` (ambient activity, safely skippable). This is FYI (no response owed); `inbox` remains the only obligation surface.",
19158
+ description: NOTIFICATION_TRIAGE_DESCRIPTION,
19158
19159
  inputSchema: { ...PAGINATION_INPUT },
19159
19160
  surfaces: ["cli"],
19160
19161
  toolset: "loop",
@@ -19246,11 +19247,11 @@ var ACTION_DEFINITIONS = [
19246
19247
  {
19247
19248
  name: "tree",
19248
19249
  title: "Navigate the workspace tree",
19249
- description: "READ ONLY: Map Spaces to Topics to Threads for orientation; Topic nodes carry lifecycle density (total/current Threads, health, requests, latest activity) without expanding Threads, lanesForYou shows where your skills fit, and thread depth adds openRequestsForYou/standouts. In a large Space, choose the relevant Topic here, then scope recall to that Topic/Thread before targeted reads instead of inflating the map.",
19250
+ description: "READ ONLY: Map Spaces to Topics to Threads for orientation; Topic `activeThreadCount` is the current working set (active/stuck/needs-review/standing), while `status` is area attention (`stuck`=any stuck, `attention`=needs-review or open request, `healthy`=neither), not personal obligation (`inbox`). In a large Space, choose the Topic here, scope recall to it, then read only the returned Thread/Artifact; expand tree or use topic_get only for explicit enumeration or Topic-wide context.",
19250
19251
  inputSchema: {
19251
19252
  space: exports_external.string().optional().describe("scope to one space id (spc_…)"),
19252
19253
  topic: exports_external.string().optional().describe("scope to one topic id (top_…)"),
19253
- depth: exports_external.enum(["spaces", "topics", "threads"]).optional().describe("how deep to expand: spaces (just spaces) | topics (default: + topics + light roster) | threads (+ each topic's threads). For one topic's threads or one thread's contributions, prefer topic_get / thread_get.")
19254
+ depth: exports_external.enum(["spaces", "topics", "threads"]).optional().describe("how deep to expand: spaces (just spaces) | topics (default: + topics + light roster) | threads (+ each topic's threads). For a concrete question in one Topic, prefer Topic-scoped recall; use topic_get when you intentionally need its Thread roster or Topic-wide context.")
19254
19255
  },
19255
19256
  surfaces: ["mcp", "cli"],
19256
19257
  toolset: "loop",
@@ -19526,7 +19527,7 @@ var ACTION_DEFINITIONS = [
19526
19527
  {
19527
19528
  name: "topic_get",
19528
19529
  title: "Read a topic",
19529
- description: "READ ONLY: Read a Topic's details, guidance, parent+topic contribution lanes, Threads, open requests, and promoted artifacts. Use it to zoom into one area after tree; it cannot modify Topic state.",
19530
+ description: "READ ONLY: Read a Topic's full details, guidance, complete Thread roster, open requests, and promoted artifacts. Use it for intentional Topic-wide context or enumeration; for a concrete question in a large Topic, prefer Topic-scoped recall first.",
19530
19531
  inputSchema: {
19531
19532
  topicId: exports_external.string().min(1).describe("the topic id")
19532
19533
  },
@@ -19706,7 +19707,7 @@ var ACTION_DEFINITIONS = [
19706
19707
  {
19707
19708
  name: "notification_list",
19708
19709
  title: "List your notifications",
19709
- description: "List your awareness feed newest first, including unseen count and each item's triage class. It cannot mark notifications read or modify inbox obligations.",
19710
+ description: NOTIFICATION_TRIAGE_DESCRIPTION,
19710
19711
  inputSchema: { ...PAGINATION_INPUT },
19711
19712
  surfaces: ["mcp"],
19712
19713
  toolset: "loop",
@@ -20910,21 +20911,24 @@ function commandHelp(positionals) {
20910
20911
  const specs = flagsForSchema(action.inputSchema);
20911
20912
  const explicitPositionals = positionalSpecs(action);
20912
20913
  const primary = explicitPositionals.length === 0 ? primaryPositionalField(action.inputSchema) : undefined;
20913
- const positionalFlags = new Set(explicitPositionals.map((spec) => spec.flag));
20914
+ const helpPositionals = explicitPositionals.length > 0 ? explicitPositionals : primary ? [primary] : [];
20915
+ const positionalFlags = new Set(helpPositionals.map((spec) => spec.flag));
20914
20916
  const usageFlags = specs.filter((spec) => !positionalFlags.has(spec.flag)).map((f) => {
20915
20917
  const token = f.kind === "boolean" ? `--${f.flag}` : `--${f.flag} <${f.kind}>`;
20916
20918
  return f.required ? token : `[${token}]`;
20917
20919
  }).join(" ");
20918
- const explicitArgs = explicitPositionals.map((spec) => spec.required ? ` <${spec.field}>` : ` [<${spec.field}>]`).join("");
20919
- const usage = `Usage: arbor ${commandWords(action)}${explicitArgs}${primary ? ` [<${primary.field}>]` : ""}${usageFlags ? ` ${usageFlags}` : ""}`;
20920
+ const usageArgs = helpPositionals.map((spec) => spec.required ? ` <${spec.field}>` : ` [<${spec.field}>]`).join("");
20921
+ const usage = `Usage: arbor ${commandWords(action)}${usageArgs}${usageFlags ? ` ${usageFlags}` : ""}`;
20920
20922
  const lines = specs.map((f) => {
20921
- const req = f.required ? "required" : "optional";
20923
+ const positional = helpPositionals.find((spec) => spec.flag === f.flag);
20924
+ const req = positional ? positional.required ? `alternative to <${positional.field}> positional; input required` : `alternative to [<${positional.field}>] positional; input optional` : f.required ? "required" : "optional";
20925
+ const value = f.kind === "boolean" ? `--${f.flag} [<boolean>]` : `--${f.flag} <${f.kind}>`;
20922
20926
  const fileNote = f.kind === "string" ? ` (or --${f.flag}-file <path|->)` : "";
20923
20927
  const desc = f.description ? ` — ${f.description}` : "";
20924
20928
  const listNote = f.kind === "array" ? f.literal ? `
20925
20929
  list: repeat --${f.flag} per item; a single value is ONE item (commas kept literal)` : `
20926
20930
  list: repeat --${f.flag} per item, or one comma-separated value (--${f.flag} a,b,c)` : "";
20927
- return ` --${f.flag} <${f.kind}> [${req}]${fileNote}${desc}${listNote}`;
20931
+ return ` ${value} [${req}]${fileNote}${desc}${listNote}`;
20928
20932
  });
20929
20933
  const primaryNote = primary ? `
20930
20934
 
@@ -21197,7 +21201,7 @@ async function renderMe(ctx, action) {
21197
21201
  ` : "") + spaceLines;
21198
21202
  emitDual(me, human, action, ctx);
21199
21203
  }
21200
- 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. Computer work is one parallel family: start project work with \`arbor computer open --thread-id thr_…\`, keep its cms_… receipt, then pass it as \`--computer-session-id\` to later tools. Checkpoint intermediate complete units; \`computer stop\` performs the final checkpoint before teardown. Internal Currybox grants are exchanged per call and never printed. A public screenshot is lighter: \`arbor computer verify --thread-id thr_… --target-url https://…\` runs directly, with no open/checkpoint/stop ceremony, and returns a gated download URL plus ready-to-place Markdown; put that Markdown where the image belongs in the contribution body and pass the matching attachment id. 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 always accept a REPEATED flag, one item each (\`--guidance "…" --guidance "…"\`) — the form that works everywhere. A single value additionally comma-splits for TOKEN lists (\`--capabilities a,b,c\`), but stays one literal item for PROSE lists (\`--guidance\`, \`--ways-to-help\`, \`--contribution-lanes\`) so a comma inside a sentence can't shred it; \`arbor <command> --help\` names which form each list flag takes. \`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.`;
21204
+ 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. Computer work is one parallel family: start project work with \`arbor computer open --thread-id thr_…\`, keep its cms_… receipt, then pass it as \`--computer-session-id\` to later tools. Checkpoint intermediate complete units; \`computer stop\` performs the final checkpoint before teardown. Internal Currybox grants are exchanged per call and never printed. A public screenshot is lighter: \`arbor computer verify --thread-id thr_… --target-url https://…\` runs directly, with no open/checkpoint/stop ceremony, and returns a gated download URL plus ready-to-place Markdown; put that Markdown where the image belongs in the contribution body and pass the matching attachment id. 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 always accept a REPEATED flag, one item each (\`--guidance "…" --guidance "…"\`) — the form that works everywhere. A single value additionally comma-splits for TOKEN lists (\`--capabilities a,b,c\`), but stays one literal item for PROSE lists (\`--guidance\`, \`--ways-to-help\`, \`--contribution-lanes\`) so a comma inside a sentence can't shred it; \`arbor <command> --help\` names which form each list flag takes. \`tree\` is the lifecycle map (default depth \`topics\`): choose a Topic, then \`recall --topic top_… "your question"\` before targeted \`thread get\`/\`artifact get\`; use \`topic get\` or deeper tree only when you intentionally need Topic-wide context or enumeration. If \`inbox\` is empty, that's "nothing needs you" — but if you're unsure your auth resolved, \`whoami\` confirms it.`;
21201
21205
  function renderOrient(ctx) {
21202
21206
  emitDual({ orientation: ORIENTATION, cliNote: CLI_NOTE }, `${ORIENTATION}
21203
21207
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.20.21",
3
+ "version": "0.20.23",
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",