@lambdacurry/arbor 0.8.10 → 0.9.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.
Files changed (2) hide show
  1. package/dist/arbor.js +65 -37
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -30,15 +30,6 @@ var CONTRIBUTION_TYPES = [
30
30
  "correction",
31
31
  "decision"
32
32
  ];
33
- var CONTRIBUTION_LINK_RELS = [
34
- "fulfills",
35
- "cites",
36
- "contests",
37
- "inReplyTo",
38
- "produces",
39
- "tracked-as",
40
- "delivered-by"
41
- ];
42
33
  var STAMP_FACETS = ["quality", "impact", "fit", "originality"];
43
34
  // ../../node_modules/.pnpm/drizzle-orm@0.38.4_@cloudflare+workers-types@4.20260529.1_@prisma+client@5.22.0_@types+_885285c61ee4b1c788385eea24f801ee/node_modules/drizzle-orm/entity.js
44
35
  var entityKind = Symbol.for("drizzle:entityKind");
@@ -1374,6 +1365,7 @@ var spaces = sqliteTable("spaces", {
1374
1365
  purpose: text("purpose").notNull().default(""),
1375
1366
  visibility: text("visibility").$type().notNull().default("open"),
1376
1367
  norms: text("norms", { mode: "json" }).$type().notNull().default({}),
1368
+ contributionLanes: text("contribution_lanes", { mode: "json" }).$type().notNull().default([]),
1377
1369
  defaultReviewDimensions: text("default_review_dimensions", { mode: "json" }).$type().notNull().default([]),
1378
1370
  stage: text("stage").$type().notNull().default("exploration"),
1379
1371
  createdAt: ts("created_at").notNull()
@@ -1435,6 +1427,7 @@ var topics = sqliteTable("topics", {
1435
1427
  title: text("title").notNull(),
1436
1428
  purpose: text("purpose"),
1437
1429
  guidance: text("guidance", { mode: "json" }).$type().notNull().default([]),
1430
+ contributionLanes: text("contribution_lanes", { mode: "json" }).$type().notNull().default([]),
1438
1431
  createdAt: ts("created_at").notNull()
1439
1432
  }, (t) => ({ spaceIdx: index("topics_space_idx").on(t.spaceId) }));
1440
1433
  var initiatives = sqliteTable("initiatives", {
@@ -1669,17 +1662,21 @@ var watches = sqliteTable("watches", {
1669
1662
  watchUq: uniqueIndex("watches_watcher_target_uniq").on(t.watcherProfileId, t.targetType, t.targetId),
1670
1663
  watchTargetIdx: index("watches_target_idx").on(t.targetType, t.targetId)
1671
1664
  }));
1665
+ // ../core/src/ops/request.ts
1666
+ var REQUEST_TTL_MS = 14 * 24 * 60 * 60 * 1000;
1667
+
1672
1668
  // ../core/src/ops/onboarding.ts
1673
1669
  var INVITE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
1674
1670
  var EMOJI_RE = new RegExp("^\\p{RGI_Emoji}$", "v");
1671
+
1672
+ // ../core/src/db/demo-scenario.ts
1673
+ var BASE_MS = Date.parse("2026-07-20T15:00:00.000Z");
1675
1674
  // ../core/src/ops/agent-pairing.ts
1676
1675
  var PAIRING_TTL_MS = 15 * 60 * 1000;
1677
- // ../core/src/ops/request.ts
1678
- var REQUEST_TTL_MS = 14 * 24 * 60 * 60 * 1000;
1676
+ // ../core/src/queries/lane-match.ts
1677
+ var STOP_WORDS = new Set("a an and are as at be by for from has have here how i in is it me of on or our the their they this to was what when where which who will with you your".split(" "));
1679
1678
  // ../core/src/queries/activity.ts
1680
1679
  var targetAuthor = alias(profiles, "target_author");
1681
- // ../core/src/queries/lane-candidates.ts
1682
- var STOP_WORDS = new Set("a an and are as at be by for from here how i in is it me of on or our the their this to what where with you your".split(" "));
1683
1680
  // ../core/src/blob/in-memory.ts
1684
1681
  class InMemoryBlobStore {
1685
1682
  store = new Map;
@@ -16049,9 +16046,17 @@ function date4(params) {
16049
16046
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
16050
16047
  config(en_default());
16051
16048
  // ../actions/src/index.ts
16049
+ var CONTRIBUTION_ADD_LINK_RELS = [
16050
+ "cites",
16051
+ "contests",
16052
+ "inReplyTo",
16053
+ "produces",
16054
+ "tracked-as",
16055
+ "delivered-by"
16056
+ ];
16052
16057
  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:
16053
16058
 
16054
- 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.
16059
+ 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: \`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\`.
16055
16060
  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.
16056
16061
  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).
16057
16062
  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").
@@ -16098,7 +16103,7 @@ var ACTIONS = [
16098
16103
  {
16099
16104
  name: "contribute",
16100
16105
  title: "Contribute to a thread",
16101
- description: "Add your own typed contribution (proposal/critique/question/evidence/…) — ONE point per contribution, on the record. BEFORE ADDING, ask what the most additive move is — not just whether to say something (AD-205): if your reaction to a point already on the record fits in one line — agree OR disagree — STAMP it (vouch, or push back with your one-line why), don't restate it as a contribution; contribute what's genuinely NEW (a typed move — a developed critique counts — that advances THIS thread's objective); if you'd only be echoing, reviewing IS the contribution and staying out is fine. RECALL FIRST (recalling beats re-deriving), and put references IN THE BODY: URLs and inline [label](#con_…) refs become typed reference edges + smart pills automatically. Body refs are CITATIONS (AD-196) — they never change where your contribution sits in the thread, so cite freely. An artifact ref ([label](#art_…)) on its OWN LINE unfurls into a preview CARD (a peek of the doc/table); inline in a sentence it stays a compact pill (AD-204) — so put an artifact on its own line when you want the reader to SEE it. To thread your contribution UNDER a specific one (a reply), pass links: [{rel: 'inReplyTo', targetId}] — that deliberate edge is what nests it. AUTOMATED/RETRYABLE callers should pass a stable idempotencyKey for the one logical contribution; replay returns the original card without another event or fan-out.",
16106
+ description: "Add your own typed contribution (proposal/critique/question/evidence/…) — ONE point per contribution, on the record. BEFORE ADDING, ask what the most additive move is — not just whether to say something (AD-205): if your reaction to a point already on the record fits in one line — agree OR disagree — STAMP it (vouch, or push back with your one-line why), don't restate it as a contribution; contribute what's genuinely NEW (a typed move — a developed critique counts — that advances THIS thread's objective); if you'd only be echoing, reviewing IS the contribution and staying out is fine. RECALL FIRST (recalling beats re-deriving), and put references IN THE BODY: URLs and inline [label](#con_…) refs become typed reference edges + smart pills automatically. Body refs are CITATIONS (AD-196) — they never change where your contribution sits in the thread, so cite freely. An artifact ref ([label](#art_…)) on its OWN LINE unfurls into a preview CARD (a peek of the doc/table); inline in a sentence it stays a compact pill (AD-204) — so put an artifact on its own line when you want the reader to SEE it. To thread your contribution UNDER a specific one (a reply), pass links: [{rel: 'inReplyTo', targetId}] — that deliberate edge is what nests it. To respond to a request, use `respond` or `mark_as_response`; `contribute` cannot create a `fulfills` link. AUTOMATED/RETRYABLE callers should pass a stable idempotencyKey for the one logical contribution; replay returns the original card without another event or fan-out.",
16102
16107
  inputSchema: {
16103
16108
  threadId: exports_external.string().describe("the thread id, e.g. thr_…"),
16104
16109
  type: exports_external.enum(CONTRIBUTION_TYPES).describe("the contribution type (AD-066 taxonomy)"),
@@ -16111,7 +16116,7 @@ var ACTIONS = [
16111
16116
  id: exports_external.string(),
16112
16117
  label: exports_external.string()
16113
16118
  })).optional().describe("inline @-mentions in the body; person mentions notify"),
16114
- links: exports_external.array(exports_external.object({ rel: exports_external.enum(CONTRIBUTION_LINK_RELS), targetId: exports_external.string() })).optional().describe("internal typed links: { rel, targetId } (same-space) — a DELIBERATE edge: inReplyTo/contests nests your contribution under the target (AD-196); body refs never do. External refs go IN THE BODY as URLs.")
16119
+ links: exports_external.array(exports_external.object({ rel: exports_external.enum(CONTRIBUTION_ADD_LINK_RELS), targetId: exports_external.string() })).optional().describe("internal typed links: { rel, targetId } (same-space) — a DELIBERATE edge: inReplyTo/contests nests your contribution under the target (AD-196); body refs never do. External refs go IN THE BODY as URLs.")
16115
16120
  },
16116
16121
  surfaces: ["mcp", "cli"],
16117
16122
  toolset: "loop",
@@ -16165,7 +16170,7 @@ var ACTIONS = [
16165
16170
  {
16166
16171
  name: "create_topic",
16167
16172
  title: "Create a topic",
16168
- 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.",
16173
+ 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, and its contribution lanes (set_topic_lanes) so they can find the work that fits them.",
16169
16174
  inputSchema: {
16170
16175
  spaceId: exports_external.string().describe("the space to create the topic in, spc_…"),
16171
16176
  title: exports_external.string().min(1).describe("the topic's name — an area of work, not a question"),
@@ -16199,6 +16204,30 @@ var ACTIONS = [
16199
16204
  toolset: "spaces",
16200
16205
  run: forward("space.setGuidance")
16201
16206
  },
16207
+ {
16208
+ name: "set_space_lanes",
16209
+ title: "Set a space's contribution lanes",
16210
+ 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.",
16211
+ inputSchema: {
16212
+ spaceId: exports_external.string().describe("the space, spc_…"),
16213
+ contributionLanes: exports_external.array(exports_external.string()).describe("the full lane list — replaces the existing one; [] clears it")
16214
+ },
16215
+ surfaces: ["cli"],
16216
+ toolset: "spaces",
16217
+ run: forward("space.setLanes")
16218
+ },
16219
+ {
16220
+ name: "set_topic_lanes",
16221
+ title: "Set a topic's contribution lanes",
16222
+ 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.",
16223
+ inputSchema: {
16224
+ topicId: exports_external.string().describe("the topic, top_…"),
16225
+ contributionLanes: exports_external.array(exports_external.string()).describe("the full lane list — replaces the existing one; [] clears it")
16226
+ },
16227
+ surfaces: ["cli"],
16228
+ toolset: "spaces",
16229
+ run: forward("topic.setLanes")
16230
+ },
16202
16231
  {
16203
16232
  name: "create_thread",
16204
16233
  title: "Open a thread",
@@ -16216,7 +16245,7 @@ var ACTIONS = [
16216
16245
  {
16217
16246
  name: "set_ways_to_help",
16218
16247
  title: "Set a thread's ways to help",
16219
- description: "Set a thread's READ-ONLY 'ways to help' (AD-038) — a short, curated list of perspectives, skills, or concrete tasks that orient someone on how they could pitch in (e.g. 'a design read on the onboarding flow', 'a benchmark on cold-start latency', 'ops perspective'). It's guidance you READ to learn how to participate, NOT an obligationthe actionable layer is `request`. Replaces the whole list; pass [] to clear.",
16248
+ 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.",
16220
16249
  inputSchema: {
16221
16250
  threadId: exports_external.string().describe("the thread, thr_…"),
16222
16251
  waysToHelp: exports_external.array(exports_external.string()).describe("the full ways-to-help list — replaces the existing one; [] clears it")
@@ -16544,7 +16573,7 @@ var ACTIONS = [
16544
16573
  {
16545
16574
  name: "tree",
16546
16575
  title: "Navigate the workspace tree",
16547
- description: 'Map the workspace a GLANCEABLE structure map, not a dump. Depths: `spaces` | `topics` (default: spaces → topics + light roster) | `threads` (adds each topic\'s threads with status, open-request counts — `openRequestsForYou` answers "does this space need me?" (AD-182) — plus `lastActivityAt` + `standouts` (AD-198): a quiet-for-days ACTIVE thread with a standout is worth OPENING). These are TRIAGE signals — where to look, never what to do: a quiet thread may be closeable, waiting on a human, or a monitor doing its job, and reading it IS the cheap check before any resolve. Scope with space/topic; drill down with space_get/topic_get/thread_get instead of inflating the tree',
16576
+ description: "Map the workspace AND find where you fit the one compact orientation surface. Depths: `spaces` | `topics` (default: spaces → topics + light roster) | `threads` (adds each topic's threads with status, open-request counts — `openRequestsForYou` answers \"does this space need me?\" (AD-182) — plus `lastActivityAt` + `standouts` (AD-198): a quiet-for-days ACTIVE thread with a standout is worth OPENING). Every space/topic also carries `lanesForYou` at any depth (AD-222): up to two of that room's DURABLE contribution lanes, quoted verbatim, that match what YOU said you do — the discovery signal, soft and never an obligation (what you OWE is `inbox`). These are TRIAGE signals — where to look, never what to do: a quiet thread may be closeable, waiting on a human, or a monitor doing its job, and reading it IS the cheap check before any resolve. Scope with space/topic; drill down with space_get/topic_get (the full lane list) or thread_get instead of inflating the tree",
16548
16577
  inputSchema: {
16549
16578
  space: exports_external.string().optional().describe("scope to one space id (spc_…)"),
16550
16579
  topic: exports_external.string().optional().describe("scope to one topic id (top_…)"),
@@ -16554,17 +16583,6 @@ var ACTIONS = [
16554
16583
  toolset: "loop",
16555
16584
  run: forward("navigation.tree")
16556
16585
  },
16557
- {
16558
- name: "lane_candidates",
16559
- title: "Find soft lane matches",
16560
- description: "After inbox, notifications, and tree, find up to three live threads that match your identity/capabilities or the space lane. Explicit `waysToHelp` matches rank first; every result explains the matching text. This is soft discovery only — it never creates or replaces an inbox obligation.",
16561
- inputSchema: {
16562
- limit: exports_external.number().int().min(0).max(3).optional().describe("maximum candidates to return (default 3)")
16563
- },
16564
- surfaces: ["mcp", "cli"],
16565
- toolset: "loop",
16566
- run: forward("navigation.laneCandidates")
16567
- },
16568
16586
  {
16569
16587
  name: "members",
16570
16588
  title: "List the people + agents in your org",
@@ -16760,7 +16778,7 @@ var ACTIONS = [
16760
16778
  {
16761
16779
  name: "space_create",
16762
16780
  title: "Create a space",
16763
- 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.",
16781
+ 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), its contribution lanes (space_lanes — what help the room stands open for, which is how members find it), and its goals (create_goal) so members and agents know how to operate here.",
16764
16782
  inputSchema: {
16765
16783
  title: exports_external.string().min(1).describe("the space title"),
16766
16784
  purpose: exports_external.string().optional().describe("optional one-line purpose"),
@@ -16812,7 +16830,7 @@ var ACTIONS = [
16812
16830
  {
16813
16831
  name: "space_get",
16814
16832
  title: "Read a space",
16815
- description: "Read one space by id — its details, the topics under it, and the full MEMBER roster: who's here, their role, their capabilities, and each member's space charter (how they operate in THIS space, AD-152) plus their identity charter. Use it to understand who you're collaborating with and how to work with them before you contribute (tree gives the lighter roster across the whole workspace; this zooms into one space with the full how-they-work picture). Space-access gated, like every read.",
16833
+ description: "Read one space by id — the room's full durable context: its details, its soft `guidance` (how we work here), its complete `contributionLanes` (the standing kinds of help this room wants, AD-222 — the tree only hints at two), the topics under it (each with its own lanes), and the full MEMBER roster: who's here, their role, their capabilities, and each member's space charter (how they operate in THIS space, AD-152) plus their identity charter. Reach for it when `tree` shows a `lanesForYou` worth following, or to learn who you're collaborating with before you contribute. Space-access gated, like every read.",
16816
16834
  inputSchema: {
16817
16835
  spaceId: exports_external.string().min(1).describe("the space id")
16818
16836
  },
@@ -16823,7 +16841,7 @@ var ACTIONS = [
16823
16841
  {
16824
16842
  name: "topic_get",
16825
16843
  title: "Read a topic",
16826
- description: "Read one topic by id — its details + the threads under it. Use it to zoom into a single topic (tree gives the whole workspace). Space-access gated, like every read.",
16844
+ description: "Read one topic by id — its details, its soft `guidance`, its full `contributionLanes` plus the parent space's (AD-222 — the durable kinds of help wanted in this area), the threads under it, its open requests, and its promoted artifacts. Use it to zoom into a single area (tree gives the whole workspace, space_get the whole room). Space-access gated, like every read.",
16827
16845
  inputSchema: {
16828
16846
  topicId: exports_external.string().min(1).describe("the topic id")
16829
16847
  },
@@ -17077,14 +17095,22 @@ var ACTIONS = [
17077
17095
  {
17078
17096
  name: "charter",
17079
17097
  title: "Set the guidance surfaces",
17080
- 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`).",
17098
+ 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), space_lanes / topic_lanes (spaceId|topicId + contributionLanes[] — the room's DURABLE contribution lanes, AD-222: short matchable labels of the help it stands open for, which is what `tree` matches into `lanesForYou`; max 6 × 120 chars, replaces the list, [] clears), ways_to_help (threadId+waysToHelp[] — one thread's temporary pitch-in list, read inside that thread only; guidance, never obligation — obligations are `request`).",
17081
17099
  inputSchema: {
17082
- verb: exports_external.enum(["space_charter", "space_guidance", "topic_guidance", "ways_to_help"]).describe("which guidance surface to set"),
17083
- spaceId: exports_external.string().optional().describe("space_charter/space_guidance: the space, spc_…"),
17100
+ verb: exports_external.enum([
17101
+ "space_charter",
17102
+ "space_guidance",
17103
+ "topic_guidance",
17104
+ "space_lanes",
17105
+ "topic_lanes",
17106
+ "ways_to_help"
17107
+ ]).describe("which guidance surface to set"),
17108
+ spaceId: exports_external.string().optional().describe("space_charter/space_guidance/space_lanes: the space, spc_…"),
17084
17109
  charter: exports_external.string().optional().describe("space_charter: the text; empty string clears"),
17085
17110
  profileId: exports_external.string().optional().describe("space_charter admin override: whose charter"),
17086
- topicId: exports_external.string().optional().describe("topic_guidance: the topic, top_…"),
17111
+ topicId: exports_external.string().optional().describe("topic_guidance/topic_lanes: the topic, top_…"),
17087
17112
  guidance: exports_external.array(exports_external.string()).optional().describe("space_guidance/topic_guidance: full list, replaces; [] clears"),
17113
+ contributionLanes: exports_external.array(exports_external.string()).optional().describe("space_lanes/topic_lanes: full lane list, replaces; [] clears"),
17088
17114
  threadId: exports_external.string().optional().describe("ways_to_help: the thread, thr_…"),
17089
17115
  waysToHelp: exports_external.array(exports_external.string()).optional().describe("ways_to_help: full list, replaces; [] clears")
17090
17116
  },
@@ -17094,6 +17120,8 @@ var ACTIONS = [
17094
17120
  space_charter: "space.setCharter",
17095
17121
  space_guidance: "space.setGuidance",
17096
17122
  topic_guidance: "topic.update",
17123
+ space_lanes: "space.setLanes",
17124
+ topic_lanes: "topic.setLanes",
17097
17125
  ways_to_help: "thread.update"
17098
17126
  })
17099
17127
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.8.10",
3
+ "version": "0.9.1",
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",