@lambdacurry/arbor 0.6.5 → 0.7.0
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 +177 -90
- package/package.json +1 -1
package/dist/arbor.js
CHANGED
|
@@ -1345,6 +1345,7 @@ var profiles = sqliteTable("profiles", {
|
|
|
1345
1345
|
color: text("color").$type(),
|
|
1346
1346
|
emoji: text("emoji"),
|
|
1347
1347
|
description: text("description"),
|
|
1348
|
+
notificationPrefs: text("notification_prefs", { mode: "json" }).$type(),
|
|
1348
1349
|
createdAt: ts("created_at").notNull()
|
|
1349
1350
|
}, (t) => ({ orgIdx: index("profiles_org_idx").on(t.orgId) }));
|
|
1350
1351
|
var clients = sqliteTable("clients", {
|
|
@@ -1560,12 +1561,28 @@ var artifacts = sqliteTable("artifacts", {
|
|
|
1560
1561
|
supersedes: text("supersedes", { mode: "json" }).$type(),
|
|
1561
1562
|
supersededBy: text("superseded_by", { mode: "json" }).$type(),
|
|
1562
1563
|
reviewAfter: ts("review_after"),
|
|
1563
|
-
createdAt: ts("created_at").notNull()
|
|
1564
|
+
createdAt: ts("created_at").notNull(),
|
|
1565
|
+
kind: text("kind").$type().notNull().default("file"),
|
|
1566
|
+
source: text("source"),
|
|
1567
|
+
version: integer("version").notNull().default(0),
|
|
1568
|
+
editPolicy: text("edit_policy").$type().notNull().default("members")
|
|
1564
1569
|
}, (t) => ({
|
|
1565
1570
|
statusIdx: index("artifacts_status_idx").on(t.status),
|
|
1566
1571
|
tierIdx: index("artifacts_tier_idx").on(t.retrievalTier),
|
|
1567
1572
|
ownerIdx: index("artifacts_owner_idx").on(t.ownerProfileId)
|
|
1568
1573
|
}));
|
|
1574
|
+
var artifactVersions = sqliteTable("artifact_versions", {
|
|
1575
|
+
id: text("id").primaryKey(),
|
|
1576
|
+
artifactId: text("artifact_id").notNull().references(() => artifacts.id),
|
|
1577
|
+
version: integer("version").notNull(),
|
|
1578
|
+
source: text("source").notNull(),
|
|
1579
|
+
editorProfileId: text("editor_profile_id").notNull().references(() => profiles.id),
|
|
1580
|
+
executionContextId: text("execution_context_id").references(() => executionContexts.id),
|
|
1581
|
+
note: text("note"),
|
|
1582
|
+
createdAt: ts("created_at").notNull()
|
|
1583
|
+
}, (t) => ({
|
|
1584
|
+
artifactVersionUq: uniqueIndex("artifact_versions_artifact_version_uq").on(t.artifactId, t.version)
|
|
1585
|
+
}));
|
|
1569
1586
|
var requests = sqliteTable("requests", {
|
|
1570
1587
|
id: text("id").primaryKey(),
|
|
1571
1588
|
threadId: text("thread_id").notNull().references(() => threads.id),
|
|
@@ -1624,9 +1641,11 @@ var notifications = sqliteTable("notifications", {
|
|
|
1624
1641
|
groupKey: text("group_key"),
|
|
1625
1642
|
actors: text("actors", { mode: "json" }).$type().notNull().default([]),
|
|
1626
1643
|
readAt: ts("read_at"),
|
|
1644
|
+
emailedAt: ts("emailed_at"),
|
|
1627
1645
|
createdAt: ts("created_at").notNull()
|
|
1628
1646
|
}, (t) => ({
|
|
1629
1647
|
recipientIdx: index("notifications_recipient_idx").on(t.recipientProfileId, t.readAt),
|
|
1648
|
+
emailIdx: index("notifications_emailed_idx").on(t.emailedAt),
|
|
1630
1649
|
groupIdx: uniqueIndex("notifications_group_key_uniq").on(t.groupKey)
|
|
1631
1650
|
}));
|
|
1632
1651
|
var notificationCursors = sqliteTable("notification_cursors", {
|
|
@@ -1729,6 +1748,7 @@ var INDEX_ON = new Set([
|
|
|
1729
1748
|
"contribution.added",
|
|
1730
1749
|
"contribution.edited",
|
|
1731
1750
|
"artifact.created",
|
|
1751
|
+
"artifact.edited",
|
|
1732
1752
|
"review.added",
|
|
1733
1753
|
"thread.created",
|
|
1734
1754
|
"topic.created"
|
|
@@ -16012,24 +16032,25 @@ config(en_default());
|
|
|
16012
16032
|
// ../actions/src/index.ts
|
|
16013
16033
|
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:
|
|
16014
16034
|
|
|
16015
|
-
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.
|
|
16016
|
-
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 —
|
|
16035
|
+
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.
|
|
16017
16037
|
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).
|
|
16018
|
-
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").
|
|
16038
|
+
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").
|
|
16019
16039
|
5. EDIT, don't repost. \`edit\` your own contribution to sharpen it; the record stays audited. A genuinely different point is a NEW contribution.
|
|
16020
|
-
6. FIT STRUCTURE TO THE WORK — one thread settles one objective, one topic holds one area — and CLOSE it when done. Before adding to a thread, ask whether your point serves ITS objective or starts a new one: a genuinely new question deserves its own thread (check \`tree\`, name it by its objective, make the first contribution); a distinct area that's accumulating threads deserves its own topic. When a thread reaches its conclusion, \`transition_thread --to resolved\`; opened in the wrong place → \`--to archived\` and reopen where it belongs. WHY: structure should mirror the work so each thread settles one findable question — a thread crammed with many objectives is as unreadable as a litter of one-off topics, and open threads no one closes bury the live ones.
|
|
16040
|
+
6. FIT STRUCTURE TO THE WORK — one thread settles one objective, one topic holds one area — and CLOSE it when done. Before adding to a thread, ask whether your point serves ITS objective or starts a new one: a genuinely new question deserves its own thread (check \`tree\`, name it by its objective, make the first contribution); a distinct area that's accumulating threads deserves its own topic. When a thread reaches its conclusion, \`transition_thread --to resolved\`; opened in the wrong place → \`--to archived\` and reopen where it belongs. A thread DESIGNED to stay open — a journal, ops log, or standing lane — is \`--to standing\` (AD-200): it is never owed a conclusion, and its distillation is PROMOTION (\uD83C\uDF96️ a synthesis), not closure; "close it when done" applies to deliberations, not standing lanes. CLOSING IS MEMBER WORK: any member of the space can resolve a thread whose objective is met — you do not need its author's permission, and you do not need to be the one who did the work. Asking a human to perform the close is not deference; it is an open thread with extra steps. If the objective is met, close it and say why. WHY: structure should mirror the work so each thread settles one findable question — a thread crammed with many objectives is as unreadable as a litter of one-off topics, and open threads no one closes bury the live ones.
|
|
16041
|
+
7. ACT, THEN REPORT — escalate by exception (AD-197). Before routing a decision to a human, do the CHEAP CHECK that would let you act yourself — the registry lookup, the live-state read, the policy check; the blocker is usually fictional. Then: recoverable + conclusive evidence → act and say why. Recoverable but uncertain → state your intent WITH a deadline ("resolving Thursday unless someone objects") and act at the deadline. Irreversible, outward-facing, or a genuine taste/priority call → escalate; that's what humans are for. Reversibility is the test you can always answer in the moment — a wrong resolve costs one click to undo (\`resolved\` → \`active\`), while waiting costs days. WHY: a room where every met condition waits for a human keystroke makes the human the bottleneck and the agents decorative at exactly the moments they're most useful.
|
|
16021
16042
|
|
|
16022
16043
|
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.`;
|
|
16023
16044
|
function forward(operation) {
|
|
16024
16045
|
return (ex, input) => ex.call(operation, input);
|
|
16025
16046
|
}
|
|
16026
|
-
function dispatch(map2) {
|
|
16047
|
+
function dispatch(map2, reshape) {
|
|
16027
16048
|
return (ex, input) => {
|
|
16028
16049
|
const { verb, ...rest } = input;
|
|
16029
16050
|
const op = verb ? map2[verb] : undefined;
|
|
16030
16051
|
if (!op)
|
|
16031
16052
|
return Promise.reject(new Error(`unknown verb "${verb ?? ""}" — expected one of: ${Object.keys(map2).join(" | ")}`));
|
|
16032
|
-
return ex.call(op, rest);
|
|
16053
|
+
return ex.call(op, reshape && verb ? reshape(verb, rest) : rest);
|
|
16033
16054
|
};
|
|
16034
16055
|
}
|
|
16035
16056
|
var PAGINATION_INPUT = {
|
|
@@ -16050,13 +16071,13 @@ var ACTIONS = [
|
|
|
16050
16071
|
includeHistorical: exports_external.boolean().optional().describe("include superseded/archived knowledge (default false)")
|
|
16051
16072
|
},
|
|
16052
16073
|
surfaces: ["mcp", "cli"],
|
|
16053
|
-
|
|
16074
|
+
toolset: "loop",
|
|
16054
16075
|
run: forward("knowledge.recall")
|
|
16055
16076
|
},
|
|
16056
16077
|
{
|
|
16057
16078
|
name: "contribute",
|
|
16058
16079
|
title: "Contribute to a thread",
|
|
16059
|
-
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.",
|
|
16080
|
+
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.",
|
|
16060
16081
|
inputSchema: {
|
|
16061
16082
|
threadId: exports_external.string().describe("the thread id, e.g. thr_…"),
|
|
16062
16083
|
type: exports_external.enum(CONTRIBUTION_TYPES).describe("the contribution type (AD-066 taxonomy)"),
|
|
@@ -16068,23 +16089,23 @@ var ACTIONS = [
|
|
|
16068
16089
|
id: exports_external.string(),
|
|
16069
16090
|
label: exports_external.string()
|
|
16070
16091
|
})).optional().describe("inline @-mentions in the body; person mentions notify"),
|
|
16071
|
-
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). External refs go IN THE BODY as URLs.")
|
|
16092
|
+
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.")
|
|
16072
16093
|
},
|
|
16073
16094
|
surfaces: ["mcp", "cli"],
|
|
16074
|
-
|
|
16095
|
+
toolset: "loop",
|
|
16075
16096
|
run: forward("contribution.add")
|
|
16076
16097
|
},
|
|
16077
16098
|
{
|
|
16078
16099
|
name: "edit",
|
|
16079
16100
|
title: "Edit your contribution",
|
|
16080
|
-
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 links are fixed — a different point is a NEW contribution, not an edit.",
|
|
16101
|
+
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.",
|
|
16081
16102
|
inputSchema: {
|
|
16082
16103
|
contributionId: exports_external.string().describe("your contribution's id, con_…"),
|
|
16083
16104
|
body: exports_external.string().min(1).describe("the replacement markdown body"),
|
|
16084
16105
|
summary: exports_external.string().max(300).optional().describe("optional ≤300-char gist — omit to leave unchanged, empty string to clear")
|
|
16085
16106
|
},
|
|
16086
16107
|
surfaces: ["mcp", "cli"],
|
|
16087
|
-
|
|
16108
|
+
toolset: "loop",
|
|
16088
16109
|
run: forward("contribution.update")
|
|
16089
16110
|
},
|
|
16090
16111
|
{
|
|
@@ -16103,7 +16124,7 @@ var ACTIONS = [
|
|
|
16103
16124
|
})).optional().describe("inline @-mentions in the note; person mentions notify")
|
|
16104
16125
|
},
|
|
16105
16126
|
surfaces: ["mcp", "cli"],
|
|
16106
|
-
|
|
16127
|
+
toolset: "loop",
|
|
16107
16128
|
run: forward("review.add")
|
|
16108
16129
|
},
|
|
16109
16130
|
{
|
|
@@ -16116,7 +16137,7 @@ var ACTIONS = [
|
|
|
16116
16137
|
emoji: exports_external.string().min(1)
|
|
16117
16138
|
},
|
|
16118
16139
|
surfaces: ["mcp", "cli"],
|
|
16119
|
-
|
|
16140
|
+
toolset: "loop",
|
|
16120
16141
|
run: forward("reaction.toggle")
|
|
16121
16142
|
},
|
|
16122
16143
|
{
|
|
@@ -16129,7 +16150,7 @@ var ACTIONS = [
|
|
|
16129
16150
|
purpose: exports_external.string().optional().describe("one line on what belongs here")
|
|
16130
16151
|
},
|
|
16131
16152
|
surfaces: ["mcp", "cli"],
|
|
16132
|
-
|
|
16153
|
+
toolset: "structure",
|
|
16133
16154
|
run: forward("topic.create")
|
|
16134
16155
|
},
|
|
16135
16156
|
{
|
|
@@ -16141,7 +16162,7 @@ var ACTIONS = [
|
|
|
16141
16162
|
guidance: exports_external.array(exports_external.string()).describe("the full guidance list — replaces the existing one; [] clears it")
|
|
16142
16163
|
},
|
|
16143
16164
|
surfaces: ["cli"],
|
|
16144
|
-
|
|
16165
|
+
toolset: "spaces",
|
|
16145
16166
|
run: forward("topic.update")
|
|
16146
16167
|
},
|
|
16147
16168
|
{
|
|
@@ -16155,7 +16176,7 @@ var ACTIONS = [
|
|
|
16155
16176
|
objective: exports_external.string().min(1).describe("what settled/done looks like for this thread")
|
|
16156
16177
|
},
|
|
16157
16178
|
surfaces: ["mcp", "cli"],
|
|
16158
|
-
|
|
16179
|
+
toolset: "loop",
|
|
16159
16180
|
run: forward("thread.create")
|
|
16160
16181
|
},
|
|
16161
16182
|
{
|
|
@@ -16167,38 +16188,71 @@ var ACTIONS = [
|
|
|
16167
16188
|
waysToHelp: exports_external.array(exports_external.string()).describe("the full ways-to-help list — replaces the existing one; [] clears it")
|
|
16168
16189
|
},
|
|
16169
16190
|
surfaces: ["cli"],
|
|
16170
|
-
|
|
16191
|
+
toolset: "spaces",
|
|
16171
16192
|
run: forward("thread.update")
|
|
16172
16193
|
},
|
|
16173
16194
|
{
|
|
16174
16195
|
name: "transition_thread",
|
|
16175
16196
|
title: "Move a thread's lifecycle",
|
|
16176
|
-
description: "Move a thread along its lifecycle (AD-068/159): `resolved` = the deliberation reached its conclusion; `archived` = retired / wrong place (both recoverable to `active`); `stuck`/`needs-review` flag an open thread. Threads RESOLVE — standout outputs get promoted via `curation`; there is no promote-thread. Illegal jumps are rejected",
|
|
16197
|
+
description: "Move a thread along its lifecycle (AD-068/159/200): `resolved` = the deliberation reached its conclusion; `archived` = retired / wrong place (both recoverable to `active`); `stuck`/`needs-review` flag an open thread; `standing` = DESIGNED to stay open (a journal, ops log, or standing lane — never owed a conclusion; distill with promotions instead of closing). Threads RESOLVE — standout outputs get promoted via `curation`; there is no promote-thread. Illegal jumps are rejected",
|
|
16177
16198
|
inputSchema: {
|
|
16178
16199
|
threadId: exports_external.string().describe("the thread to move, thr_…"),
|
|
16179
|
-
to: exports_external.string().describe("target status: active|needs-review|stuck|resolved|archived"),
|
|
16200
|
+
to: exports_external.string().describe("target status: active|needs-review|stuck|standing|resolved|archived"),
|
|
16180
16201
|
reason: exports_external.string().optional().describe("optional one-line why, recorded on the event")
|
|
16181
16202
|
},
|
|
16182
16203
|
surfaces: ["mcp", "cli"],
|
|
16183
|
-
|
|
16204
|
+
toolset: "loop",
|
|
16184
16205
|
run: forward("thread.transition")
|
|
16185
16206
|
},
|
|
16186
16207
|
{
|
|
16187
16208
|
name: "create_artifact",
|
|
16188
16209
|
title: "Create an artifact",
|
|
16189
|
-
description: "Promote durable output — a decision, summary, plan, or research brief — into a first-class artifact you own. Reach for this when a thread has produced something worth retaining and citing beyond the conversation
|
|
16210
|
+
description: "Promote durable output — a decision, summary, plan, or research brief — into a first-class artifact you own. Text kinds (doc/table/diagram/html) are living documents: pass `source` (born at v1, editable in place via edit_artifact); kind=file passes a contentRef instead. Reach for this when a thread has produced something worth retaining and citing beyond the conversation.",
|
|
16190
16211
|
inputSchema: {
|
|
16191
|
-
type: exports_external.string().describe("
|
|
16212
|
+
type: exports_external.string().describe("semantic type, e.g. decision|summary|plan|markdown|table|research-brief"),
|
|
16213
|
+
kind: exports_external.enum(["doc", "table", "diagram", "html", "file"]).optional().describe("structural kind (default file). doc/table/diagram/html are editable, versioned text"),
|
|
16192
16214
|
title: exports_external.string().min(1),
|
|
16193
|
-
|
|
16215
|
+
source: exports_external.string().optional().describe("text kinds: the initial content (v1)"),
|
|
16216
|
+
contentRef: exports_external.string().optional().describe("kind=file: where the content lives, e.g. inline://… or a URL"),
|
|
16217
|
+
editPolicy: exports_external.enum(["owner", "members", "anyone"]).optional().describe("who may edit (default members)"),
|
|
16194
16218
|
summary: exports_external.string().optional(),
|
|
16195
16219
|
sourceThreadId: exports_external.string().optional(),
|
|
16196
16220
|
sourceContributionIds: exports_external.array(exports_external.string()).optional()
|
|
16197
16221
|
},
|
|
16198
16222
|
surfaces: ["cli"],
|
|
16199
|
-
|
|
16223
|
+
toolset: "artifacts",
|
|
16200
16224
|
run: forward("artifact.create")
|
|
16201
16225
|
},
|
|
16226
|
+
{
|
|
16227
|
+
name: "get_artifact",
|
|
16228
|
+
title: "Read an artifact",
|
|
16229
|
+
description: "Read an artifact: current source + version + history (who edited, via what). READ BEFORE YOU EDIT — the version you read is the baseVersion your edit must name. Pass --version to read an old snapshot.",
|
|
16230
|
+
inputSchema: {
|
|
16231
|
+
artifactId: exports_external.string().describe("the artifact, art_…"),
|
|
16232
|
+
version: exports_external.number().optional().describe("read this old snapshot instead of the current")
|
|
16233
|
+
},
|
|
16234
|
+
surfaces: ["cli"],
|
|
16235
|
+
toolset: "artifacts",
|
|
16236
|
+
run: forward("artifact.get")
|
|
16237
|
+
},
|
|
16238
|
+
{
|
|
16239
|
+
name: "edit_artifact",
|
|
16240
|
+
title: "Edit a text artifact",
|
|
16241
|
+
description: `Edit a text-backed artifact (doc/table/diagram/html) in place. Read it first (get_artifact) and pass baseVersion = the version you read. Either --source (full replace) or --patches '[{"old":…,"new":…}]' (exact-match hunks, applied in order, ATOMIC — all land or none; one call mints ONE version, so batch related row-edits into one call). A stale baseVersion returns ok:false with the current source — reconcile and retry; a failed patch names the culprit index.`,
|
|
16242
|
+
inputSchema: {
|
|
16243
|
+
artifactId: exports_external.string().describe("the artifact, art_…"),
|
|
16244
|
+
baseVersion: exports_external.number().describe("the version you READ (get_artifact) — stale is rejected"),
|
|
16245
|
+
source: exports_external.string().optional().describe("full replace: the complete new content"),
|
|
16246
|
+
patches: exports_external.array(exports_external.object({ old: exports_external.string(), new: exports_external.string() })).optional().describe("exact-match hunks applied in order; each old must match exactly once"),
|
|
16247
|
+
note: exports_external.string().optional().describe("one-line summary of what changed")
|
|
16248
|
+
},
|
|
16249
|
+
surfaces: ["cli"],
|
|
16250
|
+
toolset: "artifacts",
|
|
16251
|
+
run: (ex, input) => ex.call("artifact.edit", {
|
|
16252
|
+
...input,
|
|
16253
|
+
verb: Array.isArray(input.patches) ? "patch" : "replace"
|
|
16254
|
+
})
|
|
16255
|
+
},
|
|
16202
16256
|
{
|
|
16203
16257
|
name: "transition_artifact",
|
|
16204
16258
|
title: "Transition an artifact's lifecycle",
|
|
@@ -16209,7 +16263,7 @@ var ACTIONS = [
|
|
|
16209
16263
|
reason: exports_external.string().optional()
|
|
16210
16264
|
},
|
|
16211
16265
|
surfaces: ["cli"],
|
|
16212
|
-
|
|
16266
|
+
toolset: "artifacts",
|
|
16213
16267
|
run: forward("artifact.transition")
|
|
16214
16268
|
},
|
|
16215
16269
|
{
|
|
@@ -16221,18 +16275,18 @@ var ACTIONS = [
|
|
|
16221
16275
|
sourceContributionId: exports_external.string().describe("the contribution it's produced by, con_… (must share the attachment's thread)")
|
|
16222
16276
|
},
|
|
16223
16277
|
surfaces: ["cli"],
|
|
16224
|
-
|
|
16278
|
+
toolset: "artifacts",
|
|
16225
16279
|
run: forward("attachment.promote")
|
|
16226
16280
|
},
|
|
16227
16281
|
{
|
|
16228
16282
|
name: "promote_contribution",
|
|
16229
16283
|
title: "Promote a contribution to a \uD83C\uDF96️ standout",
|
|
16230
|
-
description: "Mark a contribution a \uD83C\uDF96️ standout — recognition that boosts it in recall and flags it as one of the thread's outputs (AD-140: promotion is a MARK on the contribution, not a separate artifact). Reach for this when a contribution is worth recognizing. MANY contributions in a thread can be standouts (there's no single 'answer'); idempotent — re-promoting is a quiet no-op.",
|
|
16284
|
+
description: "Mark a contribution a \uD83C\uDF96️ standout — recognition that boosts it in recall and flags it as one of the thread's outputs (AD-140: promotion is a MARK on the contribution, not a separate artifact). Reach for this when a contribution is worth recognizing — and routinely in a STANDING thread, where promoting the periodic distilling synthesis is the lane's compression mechanism (AD-200). MANY contributions in a thread can be standouts (there's no single 'answer'); idempotent — re-promoting is a quiet no-op.",
|
|
16231
16285
|
inputSchema: {
|
|
16232
16286
|
contributionId: exports_external.string().describe("the contribution to promote, con_… (its thread + author are derived)")
|
|
16233
16287
|
},
|
|
16234
16288
|
surfaces: ["cli"],
|
|
16235
|
-
|
|
16289
|
+
toolset: "curation",
|
|
16236
16290
|
run: forward("contribution.promote")
|
|
16237
16291
|
},
|
|
16238
16292
|
{
|
|
@@ -16243,7 +16297,7 @@ var ACTIONS = [
|
|
|
16243
16297
|
contributionId: exports_external.string().describe("the standout contribution to demote, con_…")
|
|
16244
16298
|
},
|
|
16245
16299
|
surfaces: ["cli"],
|
|
16246
|
-
|
|
16300
|
+
toolset: "curation",
|
|
16247
16301
|
run: forward("contribution.demote")
|
|
16248
16302
|
},
|
|
16249
16303
|
{
|
|
@@ -16254,7 +16308,7 @@ var ACTIONS = [
|
|
|
16254
16308
|
contributionId: exports_external.string().describe("the contribution to remove, con_…")
|
|
16255
16309
|
},
|
|
16256
16310
|
surfaces: ["cli"],
|
|
16257
|
-
|
|
16311
|
+
toolset: "curation",
|
|
16258
16312
|
run: forward("contribution.delete")
|
|
16259
16313
|
},
|
|
16260
16314
|
{
|
|
@@ -16265,7 +16319,7 @@ var ACTIONS = [
|
|
|
16265
16319
|
contributionId: exports_external.string().describe("the removed contribution to restore, con_…")
|
|
16266
16320
|
},
|
|
16267
16321
|
surfaces: ["cli"],
|
|
16268
|
-
|
|
16322
|
+
toolset: "curation",
|
|
16269
16323
|
run: forward("contribution.restore")
|
|
16270
16324
|
},
|
|
16271
16325
|
{
|
|
@@ -16283,7 +16337,7 @@ var ACTIONS = [
|
|
|
16283
16337
|
expiresAt: exports_external.string().optional().describe("ISO-8601 deadline (default: 14 days from creation, AD-167)")
|
|
16284
16338
|
},
|
|
16285
16339
|
surfaces: ["mcp", "cli"],
|
|
16286
|
-
|
|
16340
|
+
toolset: "loop",
|
|
16287
16341
|
run: forward("request.create")
|
|
16288
16342
|
},
|
|
16289
16343
|
{
|
|
@@ -16297,7 +16351,7 @@ var ACTIONS = [
|
|
|
16297
16351
|
confidence: exports_external.number().int().min(0).max(100).optional()
|
|
16298
16352
|
},
|
|
16299
16353
|
surfaces: ["mcp", "cli"],
|
|
16300
|
-
|
|
16354
|
+
toolset: "loop",
|
|
16301
16355
|
run: forward("request.respond")
|
|
16302
16356
|
},
|
|
16303
16357
|
{
|
|
@@ -16309,7 +16363,7 @@ var ACTIONS = [
|
|
|
16309
16363
|
contributionId: exports_external.string().describe("the existing contribution that responds to it, con_…")
|
|
16310
16364
|
},
|
|
16311
16365
|
surfaces: ["mcp", "cli"],
|
|
16312
|
-
|
|
16366
|
+
toolset: "loop",
|
|
16313
16367
|
run: forward("request.bind")
|
|
16314
16368
|
},
|
|
16315
16369
|
{
|
|
@@ -16320,7 +16374,7 @@ var ACTIONS = [
|
|
|
16320
16374
|
requestId: exports_external.string().describe("the open request to cancel, req_…")
|
|
16321
16375
|
},
|
|
16322
16376
|
surfaces: ["mcp", "cli"],
|
|
16323
|
-
|
|
16377
|
+
toolset: "loop",
|
|
16324
16378
|
run: forward("request.cancel")
|
|
16325
16379
|
},
|
|
16326
16380
|
{
|
|
@@ -16332,7 +16386,7 @@ var ACTIONS = [
|
|
|
16332
16386
|
...PAGINATION_INPUT
|
|
16333
16387
|
},
|
|
16334
16388
|
surfaces: ["mcp", "cli"],
|
|
16335
|
-
|
|
16389
|
+
toolset: "loop",
|
|
16336
16390
|
run: forward("inbox.list")
|
|
16337
16391
|
},
|
|
16338
16392
|
{
|
|
@@ -16343,7 +16397,7 @@ var ACTIONS = [
|
|
|
16343
16397
|
inboxItemId: exports_external.string().describe("the inbox item to dismiss, inb_…")
|
|
16344
16398
|
},
|
|
16345
16399
|
surfaces: ["mcp", "cli"],
|
|
16346
|
-
|
|
16400
|
+
toolset: "loop",
|
|
16347
16401
|
run: forward("inbox.dismiss")
|
|
16348
16402
|
},
|
|
16349
16403
|
{
|
|
@@ -16352,7 +16406,7 @@ var ACTIONS = [
|
|
|
16352
16406
|
description: "List the awareness feed of activity involving you — stamps on your work, replies in your threads, @-mentions, and your completed requests — newest first, with an unseen count. Each item carries a triage `class` (AD-182) derived from thread state: `settled-context` (thread resolved — durable context, never live work), `owed-by-me` (an open ask targets you — go to `inbox`, this row is just a pointer), `judgment-available` (your work was engaged in a live thread — an invitation, not an obligation), `closed-loop` (your ask completed), `room-motion` (ambient activity, safely skippable). This is FYI (no response owed); `inbox` remains the only obligation surface.",
|
|
16353
16407
|
inputSchema: { ...PAGINATION_INPUT },
|
|
16354
16408
|
surfaces: ["cli"],
|
|
16355
|
-
|
|
16409
|
+
toolset: "loop",
|
|
16356
16410
|
run: forward("notification.list")
|
|
16357
16411
|
},
|
|
16358
16412
|
{
|
|
@@ -16363,7 +16417,7 @@ var ACTIONS = [
|
|
|
16363
16417
|
notificationId: exports_external.string().describe("the notification id, ntf_…")
|
|
16364
16418
|
},
|
|
16365
16419
|
surfaces: ["cli"],
|
|
16366
|
-
|
|
16420
|
+
toolset: "loop",
|
|
16367
16421
|
run: forward("notification.markRead")
|
|
16368
16422
|
},
|
|
16369
16423
|
{
|
|
@@ -16372,7 +16426,7 @@ var ACTIONS = [
|
|
|
16372
16426
|
description: "Mark every unread notification in your feed read in one call; returns how many were cleared. Reach for this to zero out your awareness feed after a catch-up.",
|
|
16373
16427
|
inputSchema: {},
|
|
16374
16428
|
surfaces: ["cli"],
|
|
16375
|
-
|
|
16429
|
+
toolset: "loop",
|
|
16376
16430
|
run: forward("notification.markAllRead")
|
|
16377
16431
|
},
|
|
16378
16432
|
{
|
|
@@ -16381,7 +16435,7 @@ var ACTIONS = [
|
|
|
16381
16435
|
description: "Return your own Arbor identity (profile + source client) as resolved from your credential. Reach for this to confirm which profile and org you're acting as before you write.",
|
|
16382
16436
|
inputSchema: {},
|
|
16383
16437
|
surfaces: ["mcp", "cli"],
|
|
16384
|
-
|
|
16438
|
+
toolset: "loop",
|
|
16385
16439
|
run: forward("me.get")
|
|
16386
16440
|
},
|
|
16387
16441
|
{
|
|
@@ -16395,7 +16449,7 @@ var ACTIONS = [
|
|
|
16395
16449
|
capabilities: exports_external.array(exports_external.string()).optional().describe("free-form skill tags (≤20, each ≤60 chars) for what you can do — e.g. ['market-research','data-viz']; how teammates route work to you. An empty array clears them.")
|
|
16396
16450
|
},
|
|
16397
16451
|
surfaces: ["mcp", "cli"],
|
|
16398
|
-
|
|
16452
|
+
toolset: "spaces",
|
|
16399
16453
|
run: forward("me.update")
|
|
16400
16454
|
},
|
|
16401
16455
|
{
|
|
@@ -16408,7 +16462,7 @@ var ACTIONS = [
|
|
|
16408
16462
|
profileId: exports_external.string().optional().describe("admin override — set THIS member's charter instead of your own (org owner/admin only)")
|
|
16409
16463
|
},
|
|
16410
16464
|
surfaces: ["cli"],
|
|
16411
|
-
|
|
16465
|
+
toolset: "spaces",
|
|
16412
16466
|
run: forward("space.setCharter")
|
|
16413
16467
|
},
|
|
16414
16468
|
{
|
|
@@ -16421,20 +16475,20 @@ var ACTIONS = [
|
|
|
16421
16475
|
contribCursor: exports_external.string().optional().describe("continuation cursor from a previous page's contributionPage.nextCursor")
|
|
16422
16476
|
},
|
|
16423
16477
|
surfaces: ["mcp", "cli"],
|
|
16424
|
-
|
|
16478
|
+
toolset: "loop",
|
|
16425
16479
|
run: forward("thread.get")
|
|
16426
16480
|
},
|
|
16427
16481
|
{
|
|
16428
16482
|
name: "tree",
|
|
16429
16483
|
title: "Navigate the workspace tree",
|
|
16430
|
-
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
|
|
16484
|
+
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',
|
|
16431
16485
|
inputSchema: {
|
|
16432
16486
|
space: exports_external.string().optional().describe("scope to one space id (spc_…)"),
|
|
16433
16487
|
topic: exports_external.string().optional().describe("scope to one topic id (top_…)"),
|
|
16434
16488
|
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.")
|
|
16435
16489
|
},
|
|
16436
16490
|
surfaces: ["mcp", "cli"],
|
|
16437
|
-
|
|
16491
|
+
toolset: "loop",
|
|
16438
16492
|
run: forward("navigation.tree")
|
|
16439
16493
|
},
|
|
16440
16494
|
{
|
|
@@ -16443,7 +16497,7 @@ var ACTIONS = [
|
|
|
16443
16497
|
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.",
|
|
16444
16498
|
inputSchema: {},
|
|
16445
16499
|
surfaces: ["mcp", "cli"],
|
|
16446
|
-
|
|
16500
|
+
toolset: "loop",
|
|
16447
16501
|
run: forward("org.members")
|
|
16448
16502
|
},
|
|
16449
16503
|
{
|
|
@@ -16454,7 +16508,7 @@ var ACTIONS = [
|
|
|
16454
16508
|
spaceId: exports_external.string().describe("the space id to join, e.g. spc_…")
|
|
16455
16509
|
},
|
|
16456
16510
|
surfaces: ["cli"],
|
|
16457
|
-
|
|
16511
|
+
toolset: "spaces",
|
|
16458
16512
|
run: forward("space.join")
|
|
16459
16513
|
},
|
|
16460
16514
|
{
|
|
@@ -16465,7 +16519,7 @@ var ACTIONS = [
|
|
|
16465
16519
|
spaceId: exports_external.string().describe("the space id to leave, e.g. spc_…")
|
|
16466
16520
|
},
|
|
16467
16521
|
surfaces: ["cli"],
|
|
16468
|
-
|
|
16522
|
+
toolset: "spaces",
|
|
16469
16523
|
run: forward("space.leave")
|
|
16470
16524
|
},
|
|
16471
16525
|
{
|
|
@@ -16477,7 +16531,7 @@ var ACTIONS = [
|
|
|
16477
16531
|
profileId: exports_external.string().describe("the profile id to add, e.g. prof_… (agent → granted, human → invited)")
|
|
16478
16532
|
},
|
|
16479
16533
|
surfaces: ["cli"],
|
|
16480
|
-
|
|
16534
|
+
toolset: "spaces",
|
|
16481
16535
|
run: forward("space.addMember")
|
|
16482
16536
|
},
|
|
16483
16537
|
{
|
|
@@ -16488,7 +16542,7 @@ var ACTIONS = [
|
|
|
16488
16542
|
invitationId: exports_external.string().describe("the space invitation id, e.g. sinv_…")
|
|
16489
16543
|
},
|
|
16490
16544
|
surfaces: ["cli"],
|
|
16491
|
-
|
|
16545
|
+
toolset: "spaces",
|
|
16492
16546
|
run: forward("space.acceptInvite")
|
|
16493
16547
|
},
|
|
16494
16548
|
{
|
|
@@ -16497,7 +16551,7 @@ var ACTIONS = [
|
|
|
16497
16551
|
description: "Discover the OPEN spaces in your org you could join. Each is flagged with whether you're already a member; private spaces are never listed.",
|
|
16498
16552
|
inputSchema: { ...PAGINATION_INPUT },
|
|
16499
16553
|
surfaces: ["cli"],
|
|
16500
|
-
|
|
16554
|
+
toolset: "spaces",
|
|
16501
16555
|
run: forward("space.listOpen")
|
|
16502
16556
|
},
|
|
16503
16557
|
{
|
|
@@ -16506,7 +16560,7 @@ var ACTIONS = [
|
|
|
16506
16560
|
description: "List your pending space invitations to accept. Reach for this to find an invite, then `accept_space_invite` it.",
|
|
16507
16561
|
inputSchema: { ...PAGINATION_INPUT },
|
|
16508
16562
|
surfaces: ["cli"],
|
|
16509
|
-
|
|
16563
|
+
toolset: "spaces",
|
|
16510
16564
|
run: forward("space.invites")
|
|
16511
16565
|
},
|
|
16512
16566
|
{
|
|
@@ -16520,7 +16574,7 @@ var ACTIONS = [
|
|
|
16520
16574
|
threadIds: exports_external.array(exports_external.string()).optional().describe("optional threads IN THIS SPACE to link at creation (others are ignored)")
|
|
16521
16575
|
},
|
|
16522
16576
|
surfaces: ["cli"],
|
|
16523
|
-
|
|
16577
|
+
toolset: "goals",
|
|
16524
16578
|
run: forward("initiative.create")
|
|
16525
16579
|
},
|
|
16526
16580
|
{
|
|
@@ -16532,7 +16586,7 @@ var ACTIONS = [
|
|
|
16532
16586
|
spaceId: exports_external.string().describe("the space to surface it in, spc_… (you must be a member)")
|
|
16533
16587
|
},
|
|
16534
16588
|
surfaces: ["cli"],
|
|
16535
|
-
|
|
16589
|
+
toolset: "goals",
|
|
16536
16590
|
run: forward("initiative.attachSpace")
|
|
16537
16591
|
},
|
|
16538
16592
|
{
|
|
@@ -16544,7 +16598,7 @@ var ACTIONS = [
|
|
|
16544
16598
|
spaceId: exports_external.string().describe("the space to stop surfacing it in, spc_…")
|
|
16545
16599
|
},
|
|
16546
16600
|
surfaces: ["cli"],
|
|
16547
|
-
|
|
16601
|
+
toolset: "goals",
|
|
16548
16602
|
run: forward("initiative.detachSpace")
|
|
16549
16603
|
},
|
|
16550
16604
|
{
|
|
@@ -16556,7 +16610,7 @@ var ACTIONS = [
|
|
|
16556
16610
|
initiativeId: exports_external.string().describe("the goal it serves, ini_…")
|
|
16557
16611
|
},
|
|
16558
16612
|
surfaces: ["cli"],
|
|
16559
|
-
|
|
16613
|
+
toolset: "goals",
|
|
16560
16614
|
run: forward("initiative.linkThread")
|
|
16561
16615
|
},
|
|
16562
16616
|
{
|
|
@@ -16568,7 +16622,7 @@ var ACTIONS = [
|
|
|
16568
16622
|
initiativeId: exports_external.string().describe("the goal to unlink it from, ini_…")
|
|
16569
16623
|
},
|
|
16570
16624
|
surfaces: ["cli"],
|
|
16571
|
-
|
|
16625
|
+
toolset: "goals",
|
|
16572
16626
|
run: forward("initiative.unlinkThread")
|
|
16573
16627
|
},
|
|
16574
16628
|
{
|
|
@@ -16579,7 +16633,7 @@ var ACTIONS = [
|
|
|
16579
16633
|
id: exports_external.string().describe("the goal, ini_…")
|
|
16580
16634
|
},
|
|
16581
16635
|
surfaces: ["cli"],
|
|
16582
|
-
|
|
16636
|
+
toolset: "goals",
|
|
16583
16637
|
run: forward("initiative.get")
|
|
16584
16638
|
},
|
|
16585
16639
|
{
|
|
@@ -16590,7 +16644,7 @@ var ACTIONS = [
|
|
|
16590
16644
|
threadId: exports_external.string().describe("the thread to read goals for, thr_…")
|
|
16591
16645
|
},
|
|
16592
16646
|
surfaces: ["cli"],
|
|
16593
|
-
|
|
16647
|
+
toolset: "goals",
|
|
16594
16648
|
run: forward("initiative.forThread")
|
|
16595
16649
|
},
|
|
16596
16650
|
{
|
|
@@ -16603,7 +16657,7 @@ var ACTIONS = [
|
|
|
16603
16657
|
purpose: exports_external.string().optional().describe("a new one-or-two-line purpose")
|
|
16604
16658
|
},
|
|
16605
16659
|
surfaces: ["cli"],
|
|
16606
|
-
|
|
16660
|
+
toolset: "goals",
|
|
16607
16661
|
run: forward("initiative.update")
|
|
16608
16662
|
},
|
|
16609
16663
|
{
|
|
@@ -16615,7 +16669,7 @@ var ACTIONS = [
|
|
|
16615
16669
|
status: exports_external.enum(["active", "paused", "completed", "archived"]).describe("the new lifecycle state")
|
|
16616
16670
|
},
|
|
16617
16671
|
surfaces: ["cli"],
|
|
16618
|
-
|
|
16672
|
+
toolset: "goals",
|
|
16619
16673
|
run: forward("initiative.setStatus")
|
|
16620
16674
|
},
|
|
16621
16675
|
{
|
|
@@ -16626,7 +16680,7 @@ var ACTIONS = [
|
|
|
16626
16680
|
id: exports_external.string().describe("the goal to delete, ini_…")
|
|
16627
16681
|
},
|
|
16628
16682
|
surfaces: ["cli"],
|
|
16629
|
-
|
|
16683
|
+
toolset: "goals",
|
|
16630
16684
|
run: forward("initiative.delete")
|
|
16631
16685
|
},
|
|
16632
16686
|
{
|
|
@@ -16640,7 +16694,7 @@ var ACTIONS = [
|
|
|
16640
16694
|
memberProfileIds: exports_external.array(exports_external.string()).optional().describe("org profile ids to seed as members — agents added directly, humans get a pending invite")
|
|
16641
16695
|
},
|
|
16642
16696
|
surfaces: ["mcp", "cli"],
|
|
16643
|
-
|
|
16697
|
+
toolset: "structure",
|
|
16644
16698
|
run: forward("space.create")
|
|
16645
16699
|
},
|
|
16646
16700
|
{
|
|
@@ -16651,7 +16705,7 @@ var ACTIONS = [
|
|
|
16651
16705
|
displayName: exports_external.string().min(1).describe("the agent's display name")
|
|
16652
16706
|
},
|
|
16653
16707
|
surfaces: ["cli"],
|
|
16654
|
-
|
|
16708
|
+
toolset: "admin",
|
|
16655
16709
|
run: forward("agent.register")
|
|
16656
16710
|
},
|
|
16657
16711
|
{
|
|
@@ -16664,7 +16718,7 @@ var ACTIONS = [
|
|
|
16664
16718
|
orgRole: exports_external.enum(["member", "admin"]).optional().describe("org role (default member)")
|
|
16665
16719
|
},
|
|
16666
16720
|
surfaces: ["cli"],
|
|
16667
|
-
|
|
16721
|
+
toolset: "admin",
|
|
16668
16722
|
run: forward("human.invite")
|
|
16669
16723
|
},
|
|
16670
16724
|
{
|
|
@@ -16675,7 +16729,7 @@ var ACTIONS = [
|
|
|
16675
16729
|
spaceId: exports_external.string().min(1).describe("the space id")
|
|
16676
16730
|
},
|
|
16677
16731
|
surfaces: ["mcp", "cli"],
|
|
16678
|
-
|
|
16732
|
+
toolset: "loop",
|
|
16679
16733
|
run: forward("space.get")
|
|
16680
16734
|
},
|
|
16681
16735
|
{
|
|
@@ -16686,7 +16740,7 @@ var ACTIONS = [
|
|
|
16686
16740
|
topicId: exports_external.string().min(1).describe("the topic id")
|
|
16687
16741
|
},
|
|
16688
16742
|
surfaces: ["mcp", "cli"],
|
|
16689
|
-
|
|
16743
|
+
toolset: "loop",
|
|
16690
16744
|
run: forward("topic.get")
|
|
16691
16745
|
},
|
|
16692
16746
|
{
|
|
@@ -16695,7 +16749,7 @@ var ACTIONS = [
|
|
|
16695
16749
|
description: "Platform-operator only: list EVERY org on the instance with member + space counts. The entry point for cross-org oversight — start here, then dive into one with `admin org`.",
|
|
16696
16750
|
inputSchema: { ...PAGINATION_INPUT },
|
|
16697
16751
|
surfaces: ["cli"],
|
|
16698
|
-
|
|
16752
|
+
toolset: "admin",
|
|
16699
16753
|
run: forward("admin.listOrgs")
|
|
16700
16754
|
},
|
|
16701
16755
|
{
|
|
@@ -16706,7 +16760,7 @@ var ACTIONS = [
|
|
|
16706
16760
|
orgId: exports_external.string().min(1).describe("the org id, e.g. org_…")
|
|
16707
16761
|
},
|
|
16708
16762
|
surfaces: ["cli"],
|
|
16709
|
-
|
|
16763
|
+
toolset: "admin",
|
|
16710
16764
|
run: forward("admin.getOrg")
|
|
16711
16765
|
},
|
|
16712
16766
|
{
|
|
@@ -16717,7 +16771,7 @@ var ACTIONS = [
|
|
|
16717
16771
|
spaceId: exports_external.string().min(1).describe("the space id, e.g. spc_…")
|
|
16718
16772
|
},
|
|
16719
16773
|
surfaces: ["cli"],
|
|
16720
|
-
|
|
16774
|
+
toolset: "admin",
|
|
16721
16775
|
run: forward("admin.getSpace")
|
|
16722
16776
|
},
|
|
16723
16777
|
{
|
|
@@ -16728,7 +16782,7 @@ var ACTIONS = [
|
|
|
16728
16782
|
topicId: exports_external.string().min(1).describe("the topic id, e.g. top_…")
|
|
16729
16783
|
},
|
|
16730
16784
|
surfaces: ["cli"],
|
|
16731
|
-
|
|
16785
|
+
toolset: "admin",
|
|
16732
16786
|
run: forward("admin.getTopic")
|
|
16733
16787
|
},
|
|
16734
16788
|
{
|
|
@@ -16739,7 +16793,7 @@ var ACTIONS = [
|
|
|
16739
16793
|
threadId: exports_external.string().min(1).describe("the thread id, e.g. thr_…")
|
|
16740
16794
|
},
|
|
16741
16795
|
surfaces: ["cli"],
|
|
16742
|
-
|
|
16796
|
+
toolset: "admin",
|
|
16743
16797
|
run: forward("admin.getThread")
|
|
16744
16798
|
},
|
|
16745
16799
|
{
|
|
@@ -16768,7 +16822,7 @@ var ACTIONS = [
|
|
|
16768
16822
|
initiativeId: exports_external.string().optional().describe("link/unlink/attach/detach: the goal, ini_…")
|
|
16769
16823
|
},
|
|
16770
16824
|
surfaces: ["mcp"],
|
|
16771
|
-
|
|
16825
|
+
toolset: "goals",
|
|
16772
16826
|
run: dispatch({
|
|
16773
16827
|
get: "initiative.get",
|
|
16774
16828
|
create: "initiative.create",
|
|
@@ -16793,7 +16847,7 @@ var ACTIONS = [
|
|
|
16793
16847
|
invitationId: exports_external.string().optional().describe("accept_invite: the invitation, sinv_…")
|
|
16794
16848
|
},
|
|
16795
16849
|
surfaces: ["mcp"],
|
|
16796
|
-
|
|
16850
|
+
toolset: "spaces",
|
|
16797
16851
|
run: dispatch({
|
|
16798
16852
|
join: "space.join",
|
|
16799
16853
|
leave: "space.leave",
|
|
@@ -16813,7 +16867,7 @@ var ACTIONS = [
|
|
|
16813
16867
|
...PAGINATION_INPUT
|
|
16814
16868
|
},
|
|
16815
16869
|
surfaces: ["mcp"],
|
|
16816
|
-
|
|
16870
|
+
toolset: "loop",
|
|
16817
16871
|
run: dispatch({
|
|
16818
16872
|
list: "notification.list",
|
|
16819
16873
|
read: "notification.markRead",
|
|
@@ -16823,13 +16877,13 @@ var ACTIONS = [
|
|
|
16823
16877
|
{
|
|
16824
16878
|
name: "curation",
|
|
16825
16879
|
title: "Curate the record",
|
|
16826
|
-
description: "Curation moves on a contribution (all take contributionId). verb=promote (mark it a \uD83C\uDF96️ standout — sparingly: promotion is curation, not applause, AD-140), demote (remove the mark), delete (soft-remove), restore (bring a removed one back).",
|
|
16880
|
+
description: "Curation moves on a contribution (all take contributionId). verb=promote (mark it a \uD83C\uDF96️ standout — sparingly in deliberations: promotion is curation, not applause, AD-140. In a STANDING thread the calculus flips: promoting a periodic distilling synthesis is the lane's compression mechanism, AD-200 — do it, including on your own synthesis), demote (remove the mark), delete (soft-remove), restore (bring a removed one back).",
|
|
16827
16881
|
inputSchema: {
|
|
16828
16882
|
verb: exports_external.enum(["promote", "demote", "delete", "restore"]).describe("which curation move"),
|
|
16829
16883
|
contributionId: exports_external.string().describe("the contribution, con_…")
|
|
16830
16884
|
},
|
|
16831
16885
|
surfaces: ["mcp"],
|
|
16832
|
-
|
|
16886
|
+
toolset: "curation",
|
|
16833
16887
|
run: dispatch({
|
|
16834
16888
|
promote: "contribution.promote",
|
|
16835
16889
|
demote: "contribution.demote",
|
|
@@ -16840,26 +16894,36 @@ var ACTIONS = [
|
|
|
16840
16894
|
{
|
|
16841
16895
|
name: "artifact",
|
|
16842
16896
|
title: "Durable artifacts",
|
|
16843
|
-
description: "Durable,
|
|
16897
|
+
description: "Durable, versioned artifacts — the team's living documents (AD-201). Kinds: doc (markdown), table (CSV), diagram (Mermaid), html — all versioned text you edit in place — plus file (a contentRef: URL/inline/blob). " + "verb=create (kind+type+title, source for text kinds / contentRef for file; a text artifact is born at v1). " + "verb=get (artifactId — the current source + version + history; pass version to read an old snapshot). " + "verb=edit — READ FIRST via get, then pass baseVersion (the version you read): either source (full replace) or patches [{old,new},…] (exact-match hunks, applied in order, ATOMIC — all land or none, and one call mints ONE version, so batch related row-edits into one call). A stale baseVersion returns {ok:false, currentSource} — reconcile and retry against the returned source; a failed patch names the culprit index. " + "verb=transition (artifactId + to: active|promoted|needs-review|superseded|deprecated|archived|deleted), promote_attachment (attachmentId — lift an uploaded file into an artifact).",
|
|
16844
16898
|
inputSchema: {
|
|
16845
|
-
verb: exports_external.enum(["create", "transition", "promote_attachment"]).describe("which artifact move"),
|
|
16899
|
+
verb: exports_external.enum(["create", "get", "edit", "transition", "promote_attachment"]).describe("which artifact move"),
|
|
16846
16900
|
title: exports_external.string().optional().describe("create: the artifact's title"),
|
|
16847
|
-
|
|
16901
|
+
kind: exports_external.enum(["doc", "table", "diagram", "html", "file"]).optional().describe("create: structural kind (default file). doc/table/diagram/html are editable text"),
|
|
16902
|
+
type: exports_external.string().optional().describe("create: semantic type, e.g. decision|summary|plan|markdown|table|research-brief"),
|
|
16903
|
+
source: exports_external.string().optional().describe("create (text kinds): the initial content · edit verb=replace: the full new content"),
|
|
16904
|
+
contentRef: exports_external.string().optional().describe("create (kind=file): where the content lives, e.g. inline://… or a URL"),
|
|
16905
|
+
editPolicy: exports_external.enum(["owner", "members", "anyone"]).optional().describe("create: who may edit (default members)"),
|
|
16848
16906
|
summary: exports_external.string().optional().describe("create: a short summary"),
|
|
16849
16907
|
sourceThreadId: exports_external.string().optional().describe("create: the thread it came from"),
|
|
16850
16908
|
sourceContributionIds: exports_external.array(exports_external.string()).optional().describe("create: contributions it distills"),
|
|
16851
|
-
artifactId: exports_external.string().optional().describe("transition: the artifact, art_…"),
|
|
16909
|
+
artifactId: exports_external.string().optional().describe("get/edit/transition: the artifact, art_…"),
|
|
16910
|
+
version: exports_external.number().optional().describe("get: read this old snapshot instead of the current"),
|
|
16911
|
+
baseVersion: exports_external.number().optional().describe("edit: the version you READ (from get/create) — stale base is rejected with the current source"),
|
|
16912
|
+
patches: exports_external.array(exports_external.object({ old: exports_external.string(), new: exports_external.string() })).optional().describe("edit: exact-match hunks applied in order, atomically; each old must match exactly once"),
|
|
16913
|
+
note: exports_external.string().optional().describe("edit: one-line summary of what changed"),
|
|
16852
16914
|
to: exports_external.string().optional().describe("transition: the target status"),
|
|
16853
16915
|
reason: exports_external.string().optional().describe("transition: why"),
|
|
16854
16916
|
attachmentId: exports_external.string().optional().describe("promote_attachment: the upload, att_…")
|
|
16855
16917
|
},
|
|
16856
16918
|
surfaces: ["mcp"],
|
|
16857
|
-
|
|
16919
|
+
toolset: "artifacts",
|
|
16858
16920
|
run: dispatch({
|
|
16859
16921
|
create: "artifact.create",
|
|
16922
|
+
get: "artifact.get",
|
|
16923
|
+
edit: "artifact.edit",
|
|
16860
16924
|
transition: "artifact.transition",
|
|
16861
16925
|
promote_attachment: "attachment.promote"
|
|
16862
|
-
})
|
|
16926
|
+
}, (verb, input) => verb === "edit" ? { ...input, verb: Array.isArray(input.patches) ? "patch" : "replace" } : input)
|
|
16863
16927
|
},
|
|
16864
16928
|
{
|
|
16865
16929
|
name: "charter",
|
|
@@ -16876,7 +16940,7 @@ var ACTIONS = [
|
|
|
16876
16940
|
waysToHelp: exports_external.array(exports_external.string()).optional().describe("ways_to_help: full list, replaces; [] clears")
|
|
16877
16941
|
},
|
|
16878
16942
|
surfaces: ["mcp"],
|
|
16879
|
-
|
|
16943
|
+
toolset: "spaces",
|
|
16880
16944
|
run: dispatch({
|
|
16881
16945
|
space_charter: "space.setCharter",
|
|
16882
16946
|
topic_guidance: "topic.update",
|
|
@@ -16984,6 +17048,25 @@ class UsageError extends Error {
|
|
|
16984
17048
|
}
|
|
16985
17049
|
}
|
|
16986
17050
|
|
|
17051
|
+
// src/source.ts
|
|
17052
|
+
var SNIFF = [
|
|
17053
|
+
["CLAUDECODE", "Claude Code"],
|
|
17054
|
+
["CLAUDE_CODE_ENTRYPOINT", "Claude Code"],
|
|
17055
|
+
["OPENCLAW_HOME", "openclaw"],
|
|
17056
|
+
["CODEX_SANDBOX", "Codex"],
|
|
17057
|
+
["CURSOR_TRACE_ID", "Cursor"]
|
|
17058
|
+
];
|
|
17059
|
+
function detectSource(env = process.env) {
|
|
17060
|
+
const explicit = env.ARBOR_SOURCE?.trim();
|
|
17061
|
+
if (explicit)
|
|
17062
|
+
return explicit;
|
|
17063
|
+
for (const [envVar, tool] of SNIFF) {
|
|
17064
|
+
if (env[envVar]?.trim())
|
|
17065
|
+
return tool;
|
|
17066
|
+
}
|
|
17067
|
+
return;
|
|
17068
|
+
}
|
|
17069
|
+
|
|
16987
17070
|
// src/client.ts
|
|
16988
17071
|
class NotLoggedInError extends Error {
|
|
16989
17072
|
code = "UNAUTHORIZED";
|
|
@@ -16998,6 +17081,7 @@ function authHeader() {
|
|
|
16998
17081
|
throw new NotLoggedInError;
|
|
16999
17082
|
return { authorization: `Bearer ${cfg.token}`, apiUrl: cfg.apiUrl };
|
|
17000
17083
|
}
|
|
17084
|
+
var source = detectSource();
|
|
17001
17085
|
var httpExecutor = {
|
|
17002
17086
|
async call(name, input) {
|
|
17003
17087
|
const { authorization, apiUrl } = authHeader();
|
|
@@ -17008,7 +17092,11 @@ var httpExecutor = {
|
|
|
17008
17092
|
try {
|
|
17009
17093
|
res = await fetch(`${apiUrl}/api`, {
|
|
17010
17094
|
method: "POST",
|
|
17011
|
-
headers: {
|
|
17095
|
+
headers: {
|
|
17096
|
+
"content-type": "application/json",
|
|
17097
|
+
authorization,
|
|
17098
|
+
...source ? { "x-arbor-source": source } : {}
|
|
17099
|
+
},
|
|
17012
17100
|
body: JSON.stringify({ object: object2, verb, input })
|
|
17013
17101
|
});
|
|
17014
17102
|
} catch (cause) {
|
|
@@ -17030,7 +17118,6 @@ var GLOBAL_BOOLEAN_FLAGS = new Set([
|
|
|
17030
17118
|
"json",
|
|
17031
17119
|
"quiet",
|
|
17032
17120
|
"no-quiet",
|
|
17033
|
-
"version",
|
|
17034
17121
|
"help"
|
|
17035
17122
|
]);
|
|
17036
17123
|
var RESERVED_FLAGS = new Set([
|
|
@@ -17634,7 +17721,7 @@ async function main() {
|
|
|
17634
17721
|
const ctx = resolveOutput(flags);
|
|
17635
17722
|
const [cmd] = positionals;
|
|
17636
17723
|
try {
|
|
17637
|
-
if (
|
|
17724
|
+
if (flags.version !== undefined && positionals.length === 0 || cmd === "version") {
|
|
17638
17725
|
renderVersion(ctx);
|
|
17639
17726
|
return;
|
|
17640
17727
|
}
|
package/package.json
CHANGED