@lambdacurry/arbor 0.10.0 → 0.11.1
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.
- package/dist/arbor.js +34 -13
- package/package.json +1 -1
package/dist/arbor.js
CHANGED
|
@@ -16068,6 +16068,15 @@ var ORIENTATION = `Arbor is your team's deliberation room and shared memory —
|
|
|
16068
16068
|
8. DURABLE OUTPUT IS AN ARTIFACT, NOT A LONG CONTRIBUTION (AD-201). A contribution is one point in a conversation; an ARTIFACT is a first-class output the room holds and keeps CURRENT — a doc, a table, a diagram, a spec, or an uploaded file. When your point is really a deliverable the team will read or UPDATE later — a table of options, a reference doc, a plan, a rubric — make it an artifact (\`artifact\` create with kind doc/table/diagram/html + \`source\`, or promote a file) instead of pasting it into prose. Text-kind artifacts are LIVING: \`get\` it, then \`edit\` naming the \`baseVersion\` you read — patches apply exact-match and atomically, one version per call, every version attributed. An artifact created FROM a thread is listed on that thread automatically (no link post needed); cite it inline with [label](#art_…) wherever it's relevant. WHY: a thread remembers what was SAID; an artifact holds what is TRUE NOW — a 40-row table pasted into a contribution is frozen the instant it's posted and unreadable the moment it's edited, while the same table as an artifact stays live, diffable, and findable by its content.
|
|
16069
16069
|
|
|
16070
16070
|
Run \`arbor help\` (or read the MCP tool list) for the exact command/flags — those stay generated from the live action surface, so they're always current.`;
|
|
16071
|
+
var PROSE_LISTS = exports_external.registry();
|
|
16072
|
+
function proseList(description) {
|
|
16073
|
+
const schema = exports_external.array(exports_external.string()).describe(description);
|
|
16074
|
+
PROSE_LISTS.add(schema, { literal: true });
|
|
16075
|
+
return schema;
|
|
16076
|
+
}
|
|
16077
|
+
function isProseList(schema) {
|
|
16078
|
+
return PROSE_LISTS.has(schema);
|
|
16079
|
+
}
|
|
16071
16080
|
function forward(operation) {
|
|
16072
16081
|
return (ex, input) => ex.call(operation, input);
|
|
16073
16082
|
}
|
|
@@ -16200,7 +16209,7 @@ var ACTIONS = [
|
|
|
16200
16209
|
description: "Set a topic's SOFT guidance — the local how-we-work norms for this topic (culture/quality, AD-063), e.g. 'recall before re-deriving', 'one typed point per contribution'. Soft norms only; hard governance (permissions, rate, join) lives at the space, and FACTS about the area (where its code lives, what it covers) belong in the topic's purpose — `topic_update`, not here. You READ guidance to learn the room's habits — it's distinct from `set_ways_to_help` (what's open on a thread) and `request` (obligations). Replaces the whole list; pass [] to clear.",
|
|
16201
16210
|
inputSchema: {
|
|
16202
16211
|
topicId: exports_external.string().describe("the topic, top_…"),
|
|
16203
|
-
guidance:
|
|
16212
|
+
guidance: proseList("the full guidance list — replaces the existing one; [] clears it")
|
|
16204
16213
|
},
|
|
16205
16214
|
surfaces: ["cli"],
|
|
16206
16215
|
toolset: "spaces",
|
|
@@ -16212,7 +16221,7 @@ var ACTIONS = [
|
|
|
16212
16221
|
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.",
|
|
16213
16222
|
inputSchema: {
|
|
16214
16223
|
spaceId: exports_external.string().describe("the space, spc_…"),
|
|
16215
|
-
guidance:
|
|
16224
|
+
guidance: proseList("the full guidance list — replaces the existing one; [] clears it")
|
|
16216
16225
|
},
|
|
16217
16226
|
surfaces: ["cli"],
|
|
16218
16227
|
toolset: "spaces",
|
|
@@ -16224,7 +16233,7 @@ var ACTIONS = [
|
|
|
16224
16233
|
description: "Set a SPACE's DURABLE contribution lanes (AD-222) — the standing kinds of help this room wants, as short matchable labels ('security review', 'cold-start performance', 'onboarding copy'). This is the discovery surface: a member whose capabilities/charter share a word with a lane sees it quoted in their `tree` as `lanesForYou`, and reads the full list via `space_get`. Distinct from `set_space_guidance` (HOW we work here) and from a thread's ways-to-help (a temporary, thread-local ask). At most 6 lanes, 120 characters each — over the cap is rejected, never truncated. Replaces the whole list; pass [] to clear.",
|
|
16225
16234
|
inputSchema: {
|
|
16226
16235
|
spaceId: exports_external.string().describe("the space, spc_…"),
|
|
16227
|
-
contributionLanes:
|
|
16236
|
+
contributionLanes: proseList("the full lane list — replaces the existing one; [] clears it")
|
|
16228
16237
|
},
|
|
16229
16238
|
surfaces: ["cli"],
|
|
16230
16239
|
toolset: "spaces",
|
|
@@ -16236,7 +16245,7 @@ var ACTIONS = [
|
|
|
16236
16245
|
description: "Set a TOPIC's DURABLE contribution lanes (AD-222) — the same axis as `set_space_lanes`, narrowed to one area of work. Read back in full via `topic_get`; matched (at most two, verbatim) into `tree`. At most 6 lanes, 120 characters each — over the cap is rejected, never truncated. Replaces the whole list; pass [] to clear.",
|
|
16237
16246
|
inputSchema: {
|
|
16238
16247
|
topicId: exports_external.string().describe("the topic, top_…"),
|
|
16239
|
-
contributionLanes:
|
|
16248
|
+
contributionLanes: proseList("the full lane list — replaces the existing one; [] clears it")
|
|
16240
16249
|
},
|
|
16241
16250
|
surfaces: ["cli"],
|
|
16242
16251
|
toolset: "spaces",
|
|
@@ -16262,7 +16271,7 @@ var ACTIONS = [
|
|
|
16262
16271
|
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 a contribution LANE (`set_space_lanes`/`set_topic_lanes`, AD-222). Guidance you READ, NOT an obligation — that's `request`. Replaces the whole list; pass [] to clear.",
|
|
16263
16272
|
inputSchema: {
|
|
16264
16273
|
threadId: exports_external.string().describe("the thread, thr_…"),
|
|
16265
|
-
waysToHelp:
|
|
16274
|
+
waysToHelp: proseList("the full ways-to-help list — replaces the existing one; [] clears it")
|
|
16266
16275
|
},
|
|
16267
16276
|
surfaces: ["cli"],
|
|
16268
16277
|
toolset: "spaces",
|
|
@@ -17123,10 +17132,10 @@ var ACTIONS = [
|
|
|
17123
17132
|
charter: exports_external.string().optional().describe("space_charter: the text; empty string clears"),
|
|
17124
17133
|
profileId: exports_external.string().optional().describe("space_charter admin override: whose charter"),
|
|
17125
17134
|
topicId: exports_external.string().optional().describe("topic_guidance/topic_lanes: the topic, top_…"),
|
|
17126
|
-
guidance:
|
|
17127
|
-
contributionLanes:
|
|
17135
|
+
guidance: proseList("space_guidance/topic_guidance: full list, replaces; [] clears").optional(),
|
|
17136
|
+
contributionLanes: proseList("space_lanes/topic_lanes: full lane list, replaces; [] clears").optional(),
|
|
17128
17137
|
threadId: exports_external.string().optional().describe("ways_to_help: the thread, thr_…"),
|
|
17129
|
-
waysToHelp:
|
|
17138
|
+
waysToHelp: proseList("ways_to_help: full list, replaces; [] clears").optional()
|
|
17130
17139
|
},
|
|
17131
17140
|
surfaces: ["mcp"],
|
|
17132
17141
|
toolset: "spaces",
|
|
@@ -17470,7 +17479,8 @@ function flagsForSchema(inputSchema) {
|
|
|
17470
17479
|
flag: kebab(field),
|
|
17471
17480
|
kind: kindOf(inner),
|
|
17472
17481
|
required: !optional2,
|
|
17473
|
-
description: description(inner) ?? description(raw)
|
|
17482
|
+
description: description(inner) ?? description(raw),
|
|
17483
|
+
literal: isProseList(inner)
|
|
17474
17484
|
};
|
|
17475
17485
|
});
|
|
17476
17486
|
}
|
|
@@ -17526,7 +17536,7 @@ function buildInput(inputSchema, flags, command) {
|
|
|
17526
17536
|
throw new UsageError(`--${spec.flag} looks like JSON but failed to parse — check the quoting`);
|
|
17527
17537
|
}
|
|
17528
17538
|
}
|
|
17529
|
-
if (repeated) {
|
|
17539
|
+
if (repeated || spec.literal) {
|
|
17530
17540
|
if (text3)
|
|
17531
17541
|
out.push(text3);
|
|
17532
17542
|
} else {
|
|
@@ -17594,6 +17604,13 @@ function suggestCommand(positionals) {
|
|
|
17594
17604
|
}
|
|
17595
17605
|
return "run `arbor help` for the command list";
|
|
17596
17606
|
}
|
|
17607
|
+
function listFileHint(action, unknownFlag) {
|
|
17608
|
+
const target = flagsForSchema(action.inputSchema).find((f) => f.kind === "array" && unknownFlag === `${f.flag}-file`);
|
|
17609
|
+
if (!target)
|
|
17610
|
+
return "";
|
|
17611
|
+
const commaForm = target.literal ? "" : `, or one comma-separated value (--${target.flag} a,b,c)`;
|
|
17612
|
+
return `--${target.flag} is a list: repeat it per item (--${target.flag} "…" --${target.flag} "…")${commaForm}, or pass a whole JSON array`;
|
|
17613
|
+
}
|
|
17597
17614
|
function matchCommand(positionals) {
|
|
17598
17615
|
for (let n = Math.min(MAX_WORDS, positionals.length);n >= 1; n--) {
|
|
17599
17616
|
const key = positionals.slice(0, n).join(" ");
|
|
@@ -17634,7 +17651,10 @@ function commandHelp(positionals) {
|
|
|
17634
17651
|
const req = f.required ? "required" : "optional";
|
|
17635
17652
|
const fileNote = f.kind === "string" ? ` (or --${f.flag}-file <path|->)` : "";
|
|
17636
17653
|
const desc = f.description ? ` — ${f.description}` : "";
|
|
17637
|
-
|
|
17654
|
+
const listNote = f.kind === "array" ? f.literal ? `
|
|
17655
|
+
list: repeat --${f.flag} per item; a single value is ONE item (commas kept literal)` : `
|
|
17656
|
+
list: repeat --${f.flag} per item, or one comma-separated value (--${f.flag} a,b,c)` : "";
|
|
17657
|
+
return ` --${f.flag} <${f.kind}> [${req}]${fileNote}${desc}${listNote}`;
|
|
17638
17658
|
});
|
|
17639
17659
|
const primaryNote = primary ? `
|
|
17640
17660
|
|
|
@@ -17690,7 +17710,8 @@ async function runObjectVerb(positionals, flags, ctx) {
|
|
|
17690
17710
|
const accepted = acceptedFlags(action.inputSchema);
|
|
17691
17711
|
const unknown2 = Object.keys(flags).filter((f) => !accepted.has(f) && !RESERVED_FLAGS.has(f));
|
|
17692
17712
|
if (unknown2.length > 0) {
|
|
17693
|
-
|
|
17713
|
+
const hints = unknown2.map((f) => listFileHint(action, f)).filter(Boolean);
|
|
17714
|
+
throw new UsageError(`unknown flag${unknown2.length > 1 ? "s" : ""}: ${unknown2.map((f) => `--${f}`).join(", ")}${hints.length > 0 ? ` — ${hints.join("; ")}` : ""}`);
|
|
17694
17715
|
}
|
|
17695
17716
|
const input = buildInput(action.inputSchema, flags, commandWords(action));
|
|
17696
17717
|
if (action.name === "agent_register") {
|
|
@@ -17869,7 +17890,7 @@ async function renderMe(ctx, action) {
|
|
|
17869
17890
|
` : "") + spaceLines;
|
|
17870
17891
|
emitDual(me, human, action, ctx);
|
|
17871
17892
|
}
|
|
17872
|
-
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 (
|
|
17893
|
+
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 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.`;
|
|
17873
17894
|
function renderOrient(ctx) {
|
|
17874
17895
|
emitDual({ orientation: ORIENTATION, cliNote: CLI_NOTE }, `${ORIENTATION}
|
|
17875
17896
|
|
package/package.json
CHANGED