@lambdacurry/arbor 0.4.26 → 0.4.28

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 +66 -11
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -16003,8 +16003,8 @@ var ORIENTATION = `Arbor is your team's deliberation room and shared memory —
16003
16003
 
16004
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.
16005
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.
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).
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").
16006
+ 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).
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 — request a review 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").
16008
16008
  5. EDIT, don't repost. \`edit\` your own contribution to sharpen it; the record stays audited. A genuinely different point is a NEW contribution.
16009
16009
  6. OPEN STRUCTURE sparingly, and CLOSE it when done. Check \`tree\` first and prefer an existing thread; \`create_topic\`/\`create_thread\` only when work truly doesn't fit, named by its OBJECTIVE with your first contribution. When a thread reaches its conclusion, \`transition_thread --to resolved\` (done); if it was opened in the wrong place, \`--to archived\` and reopen where it belongs. WHY: structure is scarce — both clutter AND open threads no one closes make the room harder to read.
16010
16010
 
@@ -16211,12 +16211,12 @@ var ACTIONS = [
16211
16211
  },
16212
16212
  {
16213
16213
  name: "request",
16214
- title: "Ask for a review",
16215
- description: "Request a review of work in a thread — name targets (an inbox item each) or leave it open (the thread board). Use this when you need someone's eyes to move forward; completion is software-computed from their responses (first | quorum(n) | all-targets | deadline | explicit). Review-only (AD-130): a review placed on the contribution it's about counts as a response.",
16214
+ title: "Request a contribution or review",
16215
+ description: "Request input on a thread (AD-161). Two kinds, picked by `aboutContributionId`: OMIT it to request a CONTRIBUTIONnew input on the thread (evidence, a proposal, a counter-argument), met by someone's `respond` contribution. PASS it to request a REVIEW of that specific contribution, met by a `stamp` on it. Either way, name targets (an inbox item each) or leave it open (the thread board); completion is software-computed from their responses (first | quorum(n) | all-targets | deadline | explicit).",
16216
16216
  inputSchema: {
16217
16217
  threadId: exports_external.string().describe("the thread the request is in, thr_…"),
16218
- requestedAction: exports_external.string().optional().describe("a one-line 'what'"),
16219
- aboutContributionId: exports_external.string().optional().describe("card-scoped request: the contribution this is about, con_ (must be in the thread; badges that card)"),
16218
+ requestedAction: exports_external.string().optional().describe("a one-line 'what you're requesting'"),
16219
+ aboutContributionId: exports_external.string().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)."),
16220
16220
  targetProfileIds: exports_external.array(exports_external.string()).optional().describe("targeted recipients (omit → open board)"),
16221
16221
  completion: exports_external.enum(["first", "quorum", "all-targets", "deadline", "explicit"]),
16222
16222
  quorumN: exports_external.number().int().min(1).optional().describe("required when completion=quorum"),
@@ -16355,7 +16355,7 @@ var ACTIONS = [
16355
16355
  {
16356
16356
  name: "members",
16357
16357
  title: "List the people + agents in your org",
16358
- description: "List everyone in your org — humans and agents — with their profile id, identity, role, and self-declared capabilities. Reach for this to find WHO to route work to: the profile id to @-mention in a contribution, or to target a `request` at a specific person (e.g. ask Meg for a design review). Read-only.",
16358
+ description: "List everyone in your org — humans and agents — with their profile id, identity, role, and self-declared capabilities. Reach for this to find WHO to route work to: the profile id to @-mention in a contribution, or to target a `request` at a specific person (e.g. request a review from Meg). Read-only.",
16359
16359
  inputSchema: {},
16360
16360
  surfaces: ["mcp", "cli"],
16361
16361
  run: forward("org.members")
@@ -16876,6 +16876,9 @@ function readTextSource(src) {
16876
16876
  }
16877
16877
  return text3.replace(/[\r\n]+$/, "");
16878
16878
  }
16879
+ function primaryPositionalField(inputSchema) {
16880
+ return flagsForSchema(inputSchema).find((f) => f.required && (f.kind === "string" || f.kind === "number"));
16881
+ }
16879
16882
  function flagsForSchema(inputSchema) {
16880
16883
  return Object.entries(inputSchema).map(([field, raw]) => {
16881
16884
  const { inner, optional: optional2 } = unwrapOptional(raw);
@@ -16981,6 +16984,35 @@ function helpLine(action) {
16981
16984
  }
16982
16985
  var COMMAND_HELP = CLI_ACTIONS.map(helpLine).join(`
16983
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
+ }
16984
17016
  function commandCatalog() {
16985
17017
  return CLI_ACTIONS.map((action) => ({
16986
17018
  command: commandWords(action),
@@ -16999,7 +17031,21 @@ async function runObjectVerb(positionals, flags, ctx) {
16999
17031
  const match = matchCommand(positionals);
17000
17032
  if (!match)
17001
17033
  throw new UsageError(`unknown command: ${positionals.join(" ") || "(none)"}`);
17002
- 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
+ }
17003
17049
  const accepted = acceptedFlags(action.inputSchema);
17004
17050
  const unknown2 = Object.keys(flags).filter((f) => !accepted.has(f) && !RESERVED_FLAGS.has(f));
17005
17051
  if (unknown2.length > 0) {
@@ -17155,13 +17201,18 @@ async function renderMe(ctx, action) {
17155
17201
  const spaceLines = spaceGaps.length > 0 ? ` spaces without your charter (say how you operate there):
17156
17202
  ` + spaceGaps.map((s) => ` • ${s.spaceTitle} — \`set_space_charter --space-id ${s.spaceId} --charter "…"\`
17157
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
+ ` : "");
17158
17209
  const human = `${me.profile.displayName} · ${me.profile.kind} · org-role ${me.profile.orgRole}
17159
17210
  ` + ` org ${me.profile.orgId} · resolved via ${me.client.kind}
17160
- ` + (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\`)
17161
17212
  ` : "") + spaceLines;
17162
17213
  emitDual(me, human, action, ctx);
17163
17214
  }
17164
- var CLI_NOTE = `On this CLI, before your first write: commands are NOUN-VERB (\`thread get\`, \`space get\`, not \`get thread\`). 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. \`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.`;
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.`;
17165
17216
  function renderOrient(ctx) {
17166
17217
  emitDual({ orientation: ORIENTATION, cliNote: CLI_NOTE }, `${ORIENTATION}
17167
17218
 
@@ -17248,7 +17299,11 @@ async function main() {
17248
17299
  return;
17249
17300
  }
17250
17301
  if (truthyFlag(flags.help)) {
17251
- 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);
17252
17307
  return;
17253
17308
  }
17254
17309
  switch (cmd) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.4.26",
3
+ "version": "0.4.28",
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": {