@lambdacurry/arbor 0.7.1 → 0.8.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 +67 -3
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -1652,6 +1652,17 @@ var notificationCursors = sqliteTable("notification_cursors", {
1652
1652
  profileId: text("profile_id").primaryKey().references(() => profiles.id),
1653
1653
  lastSeenAt: ts("last_seen_at").notNull()
1654
1654
  });
1655
+ var watches = sqliteTable("watches", {
1656
+ id: text("id").primaryKey(),
1657
+ watcherProfileId: text("watcher_profile_id").notNull().references(() => profiles.id),
1658
+ targetType: text("target_type").$type().notNull(),
1659
+ targetId: text("target_id").notNull(),
1660
+ cadence: text("cadence").$type().notNull().default("digest"),
1661
+ createdAt: ts("created_at").notNull()
1662
+ }, (t) => ({
1663
+ watchUq: uniqueIndex("watches_watcher_target_uniq").on(t.watcherProfileId, t.targetType, t.targetId),
1664
+ watchTargetIdx: index("watches_target_idx").on(t.targetType, t.targetId)
1665
+ }));
1655
1666
  // ../core/src/ops/onboarding.ts
1656
1667
  var INVITE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
1657
1668
  var EMOJI_RE = new RegExp("^\\p{RGI_Emoji}$", "v");
@@ -16033,7 +16044,7 @@ config(en_default());
16033
16044
  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:
16034
16045
 
16035
16046
  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. 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.
16036
- 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). 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: one typed point is reviewable on its own, and 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.
16047
+ 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.
16037
16048
  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).
16038
16049
  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").
16039
16050
  5. EDIT, don't repost. \`edit\` your own contribution to sharpen it; the record stays audited. A genuinely different point is a NEW contribution.
@@ -16079,7 +16090,7 @@ var ACTIONS = [
16079
16090
  {
16080
16091
  name: "contribute",
16081
16092
  title: "Contribute to a thread",
16082
- description: "Add your own typed contribution (proposal/critique/question/evidence/…) — ONE point per contribution, on the record. 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. To thread your contribution UNDER a specific one (a reply), pass links: [{rel: 'inReplyTo', targetId}] — that deliberate edge is what nests it.",
16093
+ 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.",
16083
16094
  inputSchema: {
16084
16095
  threadId: exports_external.string().describe("the thread id, e.g. thr_…"),
16085
16096
  type: exports_external.enum(CONTRIBUTION_TYPES).describe("the contribution type (AD-066 taxonomy)"),
@@ -16100,7 +16111,7 @@ var ACTIONS = [
16100
16111
  {
16101
16112
  name: "edit",
16102
16113
  title: "Edit your contribution",
16103
- description: "Edit the BODY of your own contribution (AD-132 — editable-but-audited: the displayed text changes, an 'edited' marker appears, and the event log keeps the previous body). Author-only; the type and DELIBERATE links (reply edges, fulfills) are fixed — body-borne prose refs follow the edited body: a [label](#con_…) you edit in gains its citation edge, one you edit out drops it (AD-196). A different point is a NEW contribution, not an edit.",
16114
+ description: "Edit the BODY of your own contribution (AD-132 — editable-but-audited: the displayed text changes, an 'edited' marker appears, and the event log keeps the previous body). Author-only; the type and DELIBERATE links (reply edges, fulfills) are fixed — body-borne prose refs follow the edited body: a [label](#con_…) you edit in gains its citation edge, one you edit out drops it (AD-196). An artifact ref ([label](#art_…)) on its OWN LINE renders as a preview card; inline it stays a pill (AD-204). A different point is a NEW contribution, not an edit.",
16104
16115
  inputSchema: {
16105
16116
  contributionId: exports_external.string().describe("your contribution's id, con_…"),
16106
16117
  body: exports_external.string().min(1).describe("the replacement markdown body"),
@@ -16876,6 +16887,59 @@ var ACTIONS = [
16876
16887
  read_all: "notification.markAllRead"
16877
16888
  })
16878
16889
  },
16890
+ {
16891
+ name: "watch",
16892
+ title: "Watch for changes",
16893
+ description: "CHOSEN attention (AD-202) — subscribe to a thread/artifact/topic and get a notification when it changes, even on work you didn't touch (participation already notifies you about threads you're in; watch is for the rest). verb=on: start watching (targetType thread|artifact|topic + targetId). verb=off: stop. verb=status: are you watching this one? verb=list: everything you watch. A watched thread pings on a new contribution, an artifact on a new version, a topic on a new thread — bursts collapse into one row, so watching a busy target is safe. Watching is PRIVATE (nobody sees you watch).",
16894
+ inputSchema: {
16895
+ verb: exports_external.enum(["on", "off", "status", "list"]).describe("start/stop/check watching, or list"),
16896
+ targetType: exports_external.enum(["thread", "artifact", "topic"]).optional().describe("on/off/status: what to watch"),
16897
+ targetId: exports_external.string().optional().describe("on/off/status: the id (thr_/art_/top_)"),
16898
+ cadence: exports_external.enum(["immediate", "digest"]).optional().describe("on: email cadence for later (stored now; in-app fires regardless today)")
16899
+ },
16900
+ surfaces: ["mcp"],
16901
+ toolset: "loop",
16902
+ run: dispatch({
16903
+ on: "watch.toggle",
16904
+ off: "watch.toggle",
16905
+ status: "watch.get",
16906
+ list: "watch.list"
16907
+ }, (verb, input) => verb === "off" ? { ...input, watching: false } : input)
16908
+ },
16909
+ {
16910
+ name: "watch_target",
16911
+ title: "Watch a thread/artifact/topic",
16912
+ description: "Start watching a thread, artifact, or topic (AD-202) — you'll be notified on its next change (new contribution / version / thread) even if you never touched it. Private; bursts collapse to one notification.",
16913
+ inputSchema: {
16914
+ targetType: exports_external.enum(["thread", "artifact", "topic"]).describe("what to watch"),
16915
+ targetId: exports_external.string().describe("the id (thr_/art_/top_)"),
16916
+ cadence: exports_external.enum(["immediate", "digest"]).optional().describe("email cadence for later (in-app fires regardless today)")
16917
+ },
16918
+ surfaces: ["cli"],
16919
+ toolset: "loop",
16920
+ run: forward("watch.toggle")
16921
+ },
16922
+ {
16923
+ name: "unwatch_target",
16924
+ title: "Stop watching",
16925
+ description: "Stop watching a thread/artifact/topic (AD-202). Idempotent.",
16926
+ inputSchema: {
16927
+ targetType: exports_external.enum(["thread", "artifact", "topic"]).describe("what to stop watching"),
16928
+ targetId: exports_external.string().describe("the id (thr_/art_/top_)")
16929
+ },
16930
+ surfaces: ["cli"],
16931
+ toolset: "loop",
16932
+ run: (ex, input) => ex.call("watch.toggle", { ...input, watching: false })
16933
+ },
16934
+ {
16935
+ name: "watches",
16936
+ title: "List what you watch",
16937
+ description: "List every thread/artifact/topic you're watching (AD-202), newest first.",
16938
+ inputSchema: {},
16939
+ surfaces: ["cli"],
16940
+ toolset: "loop",
16941
+ run: forward("watch.list")
16942
+ },
16879
16943
  {
16880
16944
  name: "curation",
16881
16945
  title: "Curate the record",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.7.1",
3
+ "version": "0.8.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",