@lambdacurry/arbor 0.4.25 → 0.4.27

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 +63 -7
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -1404,6 +1404,7 @@ var invitations = sqliteTable("invitations", {
1404
1404
  token: text("token"),
1405
1405
  expiresAt: ts("expires_at"),
1406
1406
  invitedByProfileId: text("invited_by_profile_id").references(() => profiles.id),
1407
+ spaceIds: text("space_ids", { mode: "json" }).$type(),
1407
1408
  createdAt: ts("created_at").notNull()
1408
1409
  }, (t) => ({
1409
1410
  emailIdx: index("invitations_email_idx").on(t.email, t.status),
@@ -16000,7 +16001,7 @@ config(en_default());
16000
16001
  // ../actions/src/index.ts
16001
16002
  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:
16002
16003
 
16003
- 1. RECALL FIRST. Run \`recall\` before re-deriving or restating anything — it may already be settled; cite prior work ([label](#con_…)) and build on it. Empty recall is itself worth noting. WHY: a room where everyone re-derives is just a chat log.
16004
+ 1. RECALL FIRST. 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. WHY: a room where everyone re-derives is just a chat log.
16004
16005
  2. CONTRIBUTE typed points — ONE point per contribution, 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 — there's no separate links field). WHY: one typed point is reviewable on its own.
16005
16006
  3. ANSWER through asks. When \`inbox\` or a thread shows an open request you can meet, answer THROUGH it — \`respond\` to it, or \`stamp\` the contribution a review-ask is about — so it completes and the requester is notified. WHY: a plain reply that merely happens to answer leaves their ask hanging (the most common failure).
16006
16007
  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 — ask via \`request\`). PROMOTE a contribution/artifact only when it's the standout the org should find FIRST (the \uD83C\uDF96️). WHY: promotion is curation, not applause — and it's about an OUTPUT, never a whole thread (a thread RESOLVES; it is never "promoted").
@@ -16342,11 +16343,11 @@ var ACTIONS = [
16342
16343
  {
16343
16344
  name: "tree",
16344
16345
  title: "Navigate the workspace tree",
16345
- description: "Map the workspace in one call your accessible spaces (with their purpose, governance stage, and ROSTER: who's in each space, their role, and what they can do) plus each space's topics and threads (with contribution counts) to orient WITHOUT chaining space/topic/thread reads. The roster tells you who to route work to; for the full picture of how someone operates (their charter + how they work in a specific space) read `space_get`. Scope with space or topic; depth=topics stops above threads.",
16346
+ description: "Map the workspace a GLANCEABLE structure map, not a full dump. By default (depth `topics`) you get your accessible spaces (purpose, governance stage) → their topics, plus a LIGHT roster (who's in each space by name/kind/role). Go DEEPER with the targeted reads, not by inflating the tree: `space_get` for a space's full roster + capabilities + charters, `topic_get` for a topic's threads, `thread_get` for a thread's contributions. Depths: `spaces` (just the spaces lightest), `topics` (default spaces + topics + light roster), `threads` (also expands each topic's threads with contribution counts). Scope with space or topic to map just that subtree.",
16346
16347
  inputSchema: {
16347
16348
  space: exports_external.string().optional().describe("scope to one space id (spc_…)"),
16348
16349
  topic: exports_external.string().optional().describe("scope to one topic id (top_…)"),
16349
- depth: exports_external.enum(["topics", "threads"]).optional().describe("how deep to expand: topics | threads (default threads)")
16350
+ 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.")
16350
16351
  },
16351
16352
  surfaces: ["mcp", "cli"],
16352
16353
  run: forward("navigation.tree")
@@ -16875,6 +16876,9 @@ function readTextSource(src) {
16875
16876
  }
16876
16877
  return text3.replace(/[\r\n]+$/, "");
16877
16878
  }
16879
+ function primaryPositionalField(inputSchema) {
16880
+ return flagsForSchema(inputSchema).find((f) => f.required && (f.kind === "string" || f.kind === "number"));
16881
+ }
16878
16882
  function flagsForSchema(inputSchema) {
16879
16883
  return Object.entries(inputSchema).map(([field, raw]) => {
16880
16884
  const { inner, optional: optional2 } = unwrapOptional(raw);
@@ -16980,6 +16984,35 @@ function helpLine(action) {
16980
16984
  }
16981
16985
  var COMMAND_HELP = CLI_ACTIONS.map(helpLine).join(`
16982
16986
  `);
16987
+ function commandHelp(positionals) {
16988
+ const match = matchCommand(positionals);
16989
+ if (!match)
16990
+ return;
16991
+ const { action } = match;
16992
+ const specs = flagsForSchema(action.inputSchema);
16993
+ const primary = primaryPositionalField(action.inputSchema);
16994
+ const usageFlags = specs.map((f) => {
16995
+ const token = f.kind === "boolean" ? `--${f.flag}` : `--${f.flag} <${f.kind}>`;
16996
+ return f.required ? token : `[${token}]`;
16997
+ }).join(" ");
16998
+ const usage = `Usage: arbor ${commandWords(action)}${primary ? ` [<${primary.field}>]` : ""}${usageFlags ? ` ${usageFlags}` : ""}`;
16999
+ const lines = specs.map((f) => {
17000
+ const req = f.required ? "required" : "optional";
17001
+ const fileNote = f.kind === "string" ? ` (or --${f.flag}-file <path|->)` : "";
17002
+ const desc = f.description ? ` — ${f.description}` : "";
17003
+ return ` --${f.flag} <${f.kind}> [${req}]${fileNote}${desc}`;
17004
+ });
17005
+ const primaryNote = primary ? `
17006
+
17007
+ A single bare argument fills --${primary.flag} (e.g. \`arbor ${commandWords(action)} <${primary.field}>\`).` : "";
17008
+ return `${commandWords(action)} — ${action.description}
17009
+
17010
+ ${usage}
17011
+
17012
+ ${lines.join(`
17013
+ `)}${primaryNote}
17014
+ `;
17015
+ }
16983
17016
  function commandCatalog() {
16984
17017
  return CLI_ACTIONS.map((action) => ({
16985
17018
  command: commandWords(action),
@@ -16998,7 +17031,21 @@ async function runObjectVerb(positionals, flags, ctx) {
16998
17031
  const match = matchCommand(positionals);
16999
17032
  if (!match)
17000
17033
  throw new UsageError(`unknown command: ${positionals.join(" ") || "(none)"}`);
17001
- const { action } = match;
17034
+ const { action, words } = match;
17035
+ const extras = positionals.slice(words);
17036
+ if (extras.length > 0) {
17037
+ const primary = primaryPositionalField(action.inputSchema);
17038
+ if (!primary) {
17039
+ throw new UsageError(`unexpected argument: ${extras[0]} (\`${commandWords(action)}\` takes no positional — use flags)`);
17040
+ }
17041
+ if (extras.length > 1) {
17042
+ throw new UsageError(`too many arguments: \`${commandWords(action)}\` takes one positional (--${primary.flag}); pass the rest as flags`);
17043
+ }
17044
+ if (flags[primary.flag] !== undefined || flags[`${primary.flag}-file`] !== undefined) {
17045
+ throw new UsageError(`pass --${primary.flag} either as a flag or as the positional argument, not both`);
17046
+ }
17047
+ flags[primary.flag] = extras[0];
17048
+ }
17002
17049
  const accepted = acceptedFlags(action.inputSchema);
17003
17050
  const unknown2 = Object.keys(flags).filter((f) => !accepted.has(f) && !RESERVED_FLAGS.has(f));
17004
17051
  if (unknown2.length > 0) {
@@ -17154,13 +17201,18 @@ async function renderMe(ctx, action) {
17154
17201
  const spaceLines = spaceGaps.length > 0 ? ` spaces without your charter (say how you operate there):
17155
17202
  ` + spaceGaps.map((s) => ` • ${s.spaceTitle} — \`set_space_charter --space-id ${s.spaceId} --charter "…"\`
17156
17203
  `).join("") : "";
17204
+ const charter = me.profile.description?.trim();
17205
+ const caps = me.profile.capabilities ?? [];
17206
+ const setLines = (charter ? ` charter: ${charter}
17207
+ ` : "") + (caps.length > 0 ? ` capabilities: ${caps.join(", ")}
17208
+ ` : "");
17157
17209
  const human = `${me.profile.displayName} · ${me.profile.kind} · org-role ${me.profile.orgRole}
17158
17210
  ` + ` org ${me.profile.orgId} · resolved via ${me.client.kind}
17159
- ` + (gaps.length > 0 ? ` to be more legible to your team, set: ${gaps.join("; ")} (\`introduce\`)
17211
+ ` + setLines + (gaps.length > 0 ? ` to be more legible to your team, set: ${gaps.join("; ")} (\`introduce\`)
17160
17212
  ` : "") + spaceLines;
17161
17213
  emitDual(me, human, action, ctx);
17162
17214
  }
17163
- var CLI_NOTE = `On this CLI, before your first write: 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\` for a command's exact 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.`;
17215
+ var CLI_NOTE = `On this CLI, before your first write: commands are NOUN-VERB (\`thread get\`, \`space get\`, not \`get thread\`). 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.`;
17164
17216
  function renderOrient(ctx) {
17165
17217
  emitDual({ orientation: ORIENTATION, cliNote: CLI_NOTE }, `${ORIENTATION}
17166
17218
 
@@ -17247,7 +17299,11 @@ async function main() {
17247
17299
  return;
17248
17300
  }
17249
17301
  if (truthyFlag(flags.help)) {
17250
- renderHelp(ctx);
17302
+ const focused = positionals.length > 0 ? commandHelp(positionals) : undefined;
17303
+ if (focused)
17304
+ emitDual({ help: focused }, focused, "help", ctx);
17305
+ else
17306
+ renderHelp(ctx);
17251
17307
  return;
17252
17308
  }
17253
17309
  switch (cmd) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.4.25",
3
+ "version": "0.4.27",
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
  "type": "module",
6
6
  "bin": {