@lambdacurry/arbor 0.22.41 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/arbor.js +302 -21
- package/package.json +1 -1
package/dist/arbor.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// package.json
|
|
3
3
|
var package_default = {
|
|
4
4
|
name: "@lambdacurry/arbor",
|
|
5
|
-
version: "0.
|
|
5
|
+
version: "0.23.1",
|
|
6
6
|
description: "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
|
|
7
7
|
keywords: [
|
|
8
8
|
"agents",
|
|
@@ -4931,6 +4931,20 @@ var LIFECYCLE_TYPES = [
|
|
|
4931
4931
|
"canceled",
|
|
4932
4932
|
"archived"
|
|
4933
4933
|
];
|
|
4934
|
+
var LIFECYCLE_TYPE_DESCRIPTIONS = {
|
|
4935
|
+
backlog: "accepted, not committed",
|
|
4936
|
+
active: "committed and in flight",
|
|
4937
|
+
"needs-review": "waiting on a read",
|
|
4938
|
+
stuck: "in flight, blocked",
|
|
4939
|
+
standing: "open-forever; never owed a conclusion (AD-200)",
|
|
4940
|
+
resolved: "the objective was met",
|
|
4941
|
+
canceled: "we decided not to",
|
|
4942
|
+
archived: "left the record; refile with `thread_update`"
|
|
4943
|
+
};
|
|
4944
|
+
function transitionThreadActionDescription() {
|
|
4945
|
+
const types = LIFECYCLE_TYPES.map((type) => `\`${type}\` ${LIFECYCLE_TYPE_DESCRIPTIONS[type]}`).join("; ");
|
|
4946
|
+
return `Move a Thread by key, case-insensitive name, or type (\`--to resolved\` still works as a bare type); illegal jumps rejected. ${types}; live menu is \`thread_get.transitionsFrom\`.`;
|
|
4947
|
+
}
|
|
4934
4948
|
var CONTRIBUTION_TYPES = [
|
|
4935
4949
|
"comment",
|
|
4936
4950
|
"question",
|
|
@@ -6437,6 +6451,24 @@ var agentPairings = sqliteTable("agent_pairings", {
|
|
|
6437
6451
|
userCodeIdx: uniqueIndex("agent_pairings_user_code_idx").on(t.userCode),
|
|
6438
6452
|
orgStatusIdx: index("agent_pairings_org_status_idx").on(t.orgId, t.status)
|
|
6439
6453
|
}));
|
|
6454
|
+
var workflows = sqliteTable("workflows", {
|
|
6455
|
+
id: text("id").primaryKey(),
|
|
6456
|
+
orgId: text("org_id").notNull().references(() => orgs.id),
|
|
6457
|
+
name: text("name").notNull(),
|
|
6458
|
+
summary: text("summary").notNull(),
|
|
6459
|
+
labels: text("labels", { mode: "json" }).$type().notNull(),
|
|
6460
|
+
createdAt: ts("created_at").notNull(),
|
|
6461
|
+
updatedAt: ts("updated_at").notNull()
|
|
6462
|
+
}, (t) => ({ orgIdx: index("workflows_org_idx").on(t.orgId) }));
|
|
6463
|
+
var spaceWorkflows = sqliteTable("space_workflows", {
|
|
6464
|
+
spaceId: text("space_id").notNull().references(() => spaces.id),
|
|
6465
|
+
workflowId: text("workflow_id").notNull().references(() => workflows.id),
|
|
6466
|
+
isDefault: integer2("is_default", { mode: "boolean" }).notNull().default(false)
|
|
6467
|
+
}, (t) => ({
|
|
6468
|
+
pk: primaryKey({ columns: [t.spaceId, t.workflowId] }),
|
|
6469
|
+
workflowIdx: index("space_workflows_workflow_idx").on(t.workflowId),
|
|
6470
|
+
oneDefaultUq: uniqueIndex("space_workflows_one_default_uq").on(t.spaceId).where(sql`${t.isDefault} = 1`)
|
|
6471
|
+
}));
|
|
6440
6472
|
var topics = sqliteTable("topics", {
|
|
6441
6473
|
id: text("id").primaryKey(),
|
|
6442
6474
|
spaceId: text("space_id").notNull().references(() => spaces.id),
|
|
@@ -6444,9 +6476,13 @@ var topics = sqliteTable("topics", {
|
|
|
6444
6476
|
purpose: text("purpose"),
|
|
6445
6477
|
guidance: text("guidance", { mode: "json" }).$type().notNull().default([]),
|
|
6446
6478
|
contributionLanes: text("contribution_lanes", { mode: "json" }).$type().notNull().default([]),
|
|
6479
|
+
workflowId: text("workflow_id").references(() => workflows.id),
|
|
6447
6480
|
archivedAt: ts("archived_at"),
|
|
6448
6481
|
createdAt: ts("created_at").notNull()
|
|
6449
|
-
}, (t) => ({
|
|
6482
|
+
}, (t) => ({
|
|
6483
|
+
spaceIdx: index("topics_space_idx").on(t.spaceId),
|
|
6484
|
+
workflowIdx: index("topics_workflow_idx").on(t.workflowId)
|
|
6485
|
+
}));
|
|
6450
6486
|
var initiatives = sqliteTable("initiatives", {
|
|
6451
6487
|
id: text("id").primaryKey(),
|
|
6452
6488
|
orgId: text("org_id").notNull().references(() => orgs.id),
|
|
@@ -6475,6 +6511,8 @@ var threads = sqliteTable("threads", {
|
|
|
6475
6511
|
objective: text("objective").notNull(),
|
|
6476
6512
|
status: text("status").$type().notNull().default("active"),
|
|
6477
6513
|
lifecycleType: text("lifecycle_type").$type().notNull().default("active"),
|
|
6514
|
+
lifecycleLabel: text("lifecycle_label").notNull().default("active"),
|
|
6515
|
+
rank: text("rank"),
|
|
6478
6516
|
waysToHelp: text("ways_to_help", { mode: "json" }).$type().notNull().default([]),
|
|
6479
6517
|
openQuestions: text("open_questions", { mode: "json" }).$type().notNull().default([]),
|
|
6480
6518
|
expectedOutput: text("expected_output").notNull().default(""),
|
|
@@ -6482,7 +6520,8 @@ var threads = sqliteTable("threads", {
|
|
|
6482
6520
|
}, (t) => ({
|
|
6483
6521
|
topicIdx: index("threads_topic_idx").on(t.topicId),
|
|
6484
6522
|
spaceIdx: index("threads_space_idx").on(t.spaceId),
|
|
6485
|
-
lifecycleTypeIdx: index("threads_lifecycle_type_idx").on(t.lifecycleType)
|
|
6523
|
+
lifecycleTypeIdx: index("threads_lifecycle_type_idx").on(t.lifecycleType),
|
|
6524
|
+
topicLifecycleRankIdx: index("threads_topic_lifecycle_rank_idx").on(t.topicId, t.lifecycleType, t.rank)
|
|
6486
6525
|
}));
|
|
6487
6526
|
var computerConfigs = sqliteTable("computer_configs", {
|
|
6488
6527
|
id: text("id").primaryKey(),
|
|
@@ -7701,6 +7740,150 @@ var STATUS_OPENNESS = {
|
|
|
7701
7740
|
var typesWhere = (sense) => Object.keys(STATUS_OPENNESS).filter((s) => STATUS_OPENNESS[s][sense]);
|
|
7702
7741
|
var WORKING_THREAD_STATUSES = typesWhere("working");
|
|
7703
7742
|
var CURRENT_WORK_THREAD_STATUSES = typesWhere("currentWork");
|
|
7743
|
+
// ../core/src/lifecycle/rank.ts
|
|
7744
|
+
var THREAD_RANK_MAX = 128;
|
|
7745
|
+
var BASE62_CLASS = "[0-9A-Za-z]";
|
|
7746
|
+
var NON_ZERO_BASE62 = "[1-9A-Za-z]";
|
|
7747
|
+
var JIRA_LEXORANK = "[0-2]\\|[0-9a-z]+:[0-9a-z]*";
|
|
7748
|
+
function figmaFamilyPattern() {
|
|
7749
|
+
const arms = [];
|
|
7750
|
+
for (let i = 0;i < 26; i++) {
|
|
7751
|
+
const extra = String(i + 1);
|
|
7752
|
+
const lower = String.fromCharCode(97 + i);
|
|
7753
|
+
const upper = String.fromCharCode(90 - i);
|
|
7754
|
+
const rest = `${BASE62_CLASS}{${extra}}(?:${BASE62_CLASS}*${NON_ZERO_BASE62})?`;
|
|
7755
|
+
arms.push(`${lower}${rest}`, `${upper}${rest}`);
|
|
7756
|
+
}
|
|
7757
|
+
return arms.join("|");
|
|
7758
|
+
}
|
|
7759
|
+
var THREAD_RANK_PATTERN = new RegExp(`^(?:${JIRA_LEXORANK}|${figmaFamilyPattern()})$`);
|
|
7760
|
+
// ../core/src/lifecycle/workflow.ts
|
|
7761
|
+
var WORKFLOW_SUMMARY_MAX = 500;
|
|
7762
|
+
var WORKFLOW_LABEL_DESCRIPTION_MAX = 200;
|
|
7763
|
+
var LIFECYCLE_TYPE_SET = new Set(LIFECYCLE_TYPES);
|
|
7764
|
+
// ../core/src/lifecycle/builtins.ts
|
|
7765
|
+
var BUILTIN_WORKFLOW_IDS = [
|
|
7766
|
+
"standard",
|
|
7767
|
+
"queue",
|
|
7768
|
+
"content",
|
|
7769
|
+
"experiment",
|
|
7770
|
+
"funnel"
|
|
7771
|
+
];
|
|
7772
|
+
var col = (key, name, type, order, extra) => ({ key, name, type, order, ...extra });
|
|
7773
|
+
var STANDARD = {
|
|
7774
|
+
id: "standard",
|
|
7775
|
+
name: "Standard",
|
|
7776
|
+
summary: "One label per type using the protocol's own words — the zero-config default and the only all-eight workflow.",
|
|
7777
|
+
labels: [
|
|
7778
|
+
col("backlog", "Backlog", "backlog", 0),
|
|
7779
|
+
col("active", "Active", "active", 1),
|
|
7780
|
+
col("needs-review", "Needs review", "needs-review", 2),
|
|
7781
|
+
col("stuck", "Stuck", "stuck", 3),
|
|
7782
|
+
col("standing", "Standing", "standing", 4),
|
|
7783
|
+
col("resolved", "Resolved", "resolved", 5),
|
|
7784
|
+
col("canceled", "Canceled", "canceled", 6),
|
|
7785
|
+
col("archived", "Archived", "archived", 7)
|
|
7786
|
+
]
|
|
7787
|
+
};
|
|
7788
|
+
var QUEUE = {
|
|
7789
|
+
id: "queue",
|
|
7790
|
+
name: "Queue",
|
|
7791
|
+
summary: "Arrivals are handled or refused; no review gate; stuck names an external requester.",
|
|
7792
|
+
labels: [
|
|
7793
|
+
col("triage", "Triage", "backlog", 0, {
|
|
7794
|
+
description: "Arrived; not yet accepted or refused."
|
|
7795
|
+
}),
|
|
7796
|
+
col("accepted", "Accepted", "active", 1, { description: "Taken; being handled." }),
|
|
7797
|
+
col("waiting-on-requester", "Waiting on requester", "stuck", 2, {
|
|
7798
|
+
description: "Blocked on the person who sent it, not an internal blocker."
|
|
7799
|
+
}),
|
|
7800
|
+
col("handled", "Handled", "resolved", 3, { description: "The arrival was worked." }),
|
|
7801
|
+
col("declined", "Declined", "canceled", 4, { description: "We decided not to take it." }),
|
|
7802
|
+
col("duplicate", "Duplicate", "archived", 5, {
|
|
7803
|
+
description: "Same as an existing thread; the original holds the work."
|
|
7804
|
+
})
|
|
7805
|
+
]
|
|
7806
|
+
};
|
|
7807
|
+
var CONTENT = {
|
|
7808
|
+
id: "content",
|
|
7809
|
+
name: "Content",
|
|
7810
|
+
summary: "Draft, edit, approve, publish — two review gates by two authorities, plus a named return path.",
|
|
7811
|
+
labels: [
|
|
7812
|
+
col("pitch", "Pitch", "backlog", 0, { description: "Proposed, not yet in draft." }),
|
|
7813
|
+
col("drafting", "Drafting", "active", 1, {
|
|
7814
|
+
isDefaultForType: true,
|
|
7815
|
+
description: "Being written."
|
|
7816
|
+
}),
|
|
7817
|
+
col("changes-requested", "Changes requested", "active", 2, {
|
|
7818
|
+
description: "Failed a review; the bounce is the work."
|
|
7819
|
+
}),
|
|
7820
|
+
col("in-edit", "In edit", "needs-review", 3, {
|
|
7821
|
+
isDefaultForType: true,
|
|
7822
|
+
description: "Editorial review."
|
|
7823
|
+
}),
|
|
7824
|
+
col("final-approval", "Final approval", "needs-review", 4, {
|
|
7825
|
+
description: "Sign-off by a different authority than edit."
|
|
7826
|
+
}),
|
|
7827
|
+
col("waiting-on-assets", "Waiting on assets", "stuck", 5, {
|
|
7828
|
+
description: "Blocked on material, not a reader."
|
|
7829
|
+
}),
|
|
7830
|
+
col("published", "Published", "resolved", 6, { description: "Out." }),
|
|
7831
|
+
col("killed", "Killed", "canceled", 7, { description: "We decided not to ship it." })
|
|
7832
|
+
]
|
|
7833
|
+
};
|
|
7834
|
+
var EXPERIMENT = {
|
|
7835
|
+
id: "experiment",
|
|
7836
|
+
name: "Experiment",
|
|
7837
|
+
summary: "A hypothesis is run and owes a readout; two honest endings — adopted, or not.",
|
|
7838
|
+
labels: [
|
|
7839
|
+
col("hypothesis", "Hypothesis", "backlog", 0, {
|
|
7840
|
+
description: "Proposed trial, not yet running."
|
|
7841
|
+
}),
|
|
7842
|
+
col("running", "Running", "active", 1, {
|
|
7843
|
+
description: "Finite trial in flight; owed a readout."
|
|
7844
|
+
}),
|
|
7845
|
+
col("readout", "Readout", "needs-review", 2, {
|
|
7846
|
+
description: "Findings waiting on a reader."
|
|
7847
|
+
}),
|
|
7848
|
+
col("adopted", "Adopted", "resolved", 3, {
|
|
7849
|
+
description: "The hypothesis won; we will keep it."
|
|
7850
|
+
}),
|
|
7851
|
+
col("rejected", "Rejected", "canceled", 4, {
|
|
7852
|
+
description: "The hypothesis ran; we decided not to adopt."
|
|
7853
|
+
})
|
|
7854
|
+
]
|
|
7855
|
+
};
|
|
7856
|
+
var FUNNEL = {
|
|
7857
|
+
id: "funnel",
|
|
7858
|
+
name: "Funnel",
|
|
7859
|
+
summary: "A ladder of sequential stages against a counterparty, ending won or lost.",
|
|
7860
|
+
labels: [
|
|
7861
|
+
col("lead", "Lead", "backlog", 0, { description: "Not yet qualified." }),
|
|
7862
|
+
col("qualified", "Qualified", "active", 1, {
|
|
7863
|
+
isDefaultForType: true,
|
|
7864
|
+
description: "In the ladder; not yet a proposal."
|
|
7865
|
+
}),
|
|
7866
|
+
col("proposal", "Proposal", "active", 2, {
|
|
7867
|
+
description: "Proposal is out / submitted."
|
|
7868
|
+
}),
|
|
7869
|
+
col("negotiation", "Negotiation", "active", 3, { description: "Terms being worked." }),
|
|
7870
|
+
col("waiting-on-counterparty", "Waiting on counterparty", "stuck", 4, {
|
|
7871
|
+
description: "Blocked on them, not on an internal read."
|
|
7872
|
+
}),
|
|
7873
|
+
col("won", "Won", "resolved", 5, { description: "Closed won." }),
|
|
7874
|
+
col("lost", "Lost", "canceled", 6, {
|
|
7875
|
+
description: "We did not win; keep the reason findable."
|
|
7876
|
+
})
|
|
7877
|
+
]
|
|
7878
|
+
};
|
|
7879
|
+
var BUILTIN_WORKFLOWS = {
|
|
7880
|
+
standard: STANDARD,
|
|
7881
|
+
queue: QUEUE,
|
|
7882
|
+
content: CONTENT,
|
|
7883
|
+
experiment: EXPERIMENT,
|
|
7884
|
+
funnel: FUNNEL
|
|
7885
|
+
};
|
|
7886
|
+
var STANDARD_WORKFLOW = BUILTIN_WORKFLOWS.standard;
|
|
7704
7887
|
// ../core/src/ops/secret.ts
|
|
7705
7888
|
var SECRET_PERMISSIONS = [
|
|
7706
7889
|
"create",
|
|
@@ -8413,8 +8596,27 @@ var thread3 = looseObject({
|
|
|
8413
8596
|
title: string2(),
|
|
8414
8597
|
objective: string2(),
|
|
8415
8598
|
status: string2().optional(),
|
|
8599
|
+
lifecycleType: string2().optional(),
|
|
8600
|
+
lifecycleLabel: string2().optional(),
|
|
8601
|
+
rank: nullableString.optional(),
|
|
8416
8602
|
url: string2().optional()
|
|
8417
8603
|
});
|
|
8604
|
+
var workflowSummary = looseObject({
|
|
8605
|
+
id,
|
|
8606
|
+
name: string2(),
|
|
8607
|
+
summary: string2(),
|
|
8608
|
+
origin: string2().optional(),
|
|
8609
|
+
isDefault: boolean2().optional(),
|
|
8610
|
+
labels: array(jsonObject).optional(),
|
|
8611
|
+
createdAt: string2().optional(),
|
|
8612
|
+
updatedAt: string2().optional()
|
|
8613
|
+
});
|
|
8614
|
+
var transitionFrom = looseObject({
|
|
8615
|
+
label: string2(),
|
|
8616
|
+
name: string2(),
|
|
8617
|
+
type: string2(),
|
|
8618
|
+
description: string2().optional()
|
|
8619
|
+
});
|
|
8418
8620
|
var topic2 = looseObject({
|
|
8419
8621
|
id,
|
|
8420
8622
|
spaceId: id.optional(),
|
|
@@ -8714,14 +8916,16 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
8714
8916
|
topic_update: looseObject({
|
|
8715
8917
|
id,
|
|
8716
8918
|
title: string2().optional(),
|
|
8717
|
-
purpose: nullableString.optional()
|
|
8919
|
+
purpose: nullableString.optional(),
|
|
8920
|
+
workflowId: nullableString.optional()
|
|
8718
8921
|
}),
|
|
8719
8922
|
create_thread: looseObject({ threadId: id, url: string2().optional() }),
|
|
8720
8923
|
thread_update: looseObject({
|
|
8721
8924
|
id,
|
|
8722
8925
|
title: string2().optional(),
|
|
8723
8926
|
objective: string2().optional(),
|
|
8724
|
-
topicId: string2().optional()
|
|
8927
|
+
topicId: string2().optional(),
|
|
8928
|
+
rank: nullableString.optional()
|
|
8725
8929
|
}),
|
|
8726
8930
|
set_organization_computer: looseObject({ config: computerConfigLayer.nullable() }),
|
|
8727
8931
|
set_space_computer: looseObject({ config: computerConfigLayer.nullable() }),
|
|
@@ -8868,7 +9072,8 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
8868
9072
|
distillate: array(jsonObject).optional(),
|
|
8869
9073
|
watching: boolean2().optional(),
|
|
8870
9074
|
cursor: string2().optional(),
|
|
8871
|
-
unchanged: boolean2().optional()
|
|
9075
|
+
unchanged: boolean2().optional(),
|
|
9076
|
+
transitionsFrom: array(transitionFrom).optional()
|
|
8872
9077
|
}),
|
|
8873
9078
|
thread_assign: looseObject({
|
|
8874
9079
|
threadId: id,
|
|
@@ -8914,7 +9119,10 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
8914
9119
|
title: string2().optional(),
|
|
8915
9120
|
purpose: nullableString.optional(),
|
|
8916
9121
|
visibility: string2().optional(),
|
|
8917
|
-
stage: string2().optional()
|
|
9122
|
+
stage: string2().optional(),
|
|
9123
|
+
attached: jsonObject.optional(),
|
|
9124
|
+
defaulted: jsonObject.optional(),
|
|
9125
|
+
detached: jsonObject.optional()
|
|
8918
9126
|
}),
|
|
8919
9127
|
space_get: looseObject({
|
|
8920
9128
|
space: space3,
|
|
@@ -8922,11 +9130,14 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
8922
9130
|
members: array(member).optional(),
|
|
8923
9131
|
total: number2().int().min(0),
|
|
8924
9132
|
nextCursor: string2().optional(),
|
|
8925
|
-
computerConfig: resolvedComputerConfig.nullable().optional()
|
|
9133
|
+
computerConfig: resolvedComputerConfig.nullable().optional(),
|
|
9134
|
+
workflows: array(workflowSummary).optional(),
|
|
9135
|
+
defaultWorkflow: workflowSummary.optional()
|
|
8926
9136
|
}),
|
|
8927
9137
|
topic_get: looseObject({
|
|
8928
9138
|
topic: topic2,
|
|
8929
9139
|
space: space3,
|
|
9140
|
+
workflow: workflowSummary.optional(),
|
|
8930
9141
|
threads: array(thread3).optional(),
|
|
8931
9142
|
promotedArtifacts: array(artifact4).optional(),
|
|
8932
9143
|
total: number2().int().min(0),
|
|
@@ -9660,6 +9871,22 @@ var MCP_OUTPUT_SCHEMAS = {
|
|
|
9660
9871
|
namePath: string2().optional()
|
|
9661
9872
|
})),
|
|
9662
9873
|
truncated: boolean2()
|
|
9874
|
+
}),
|
|
9875
|
+
workflow_create: looseObject({
|
|
9876
|
+
id,
|
|
9877
|
+
name: string2(),
|
|
9878
|
+
summary: string2(),
|
|
9879
|
+
labels: array(jsonObject)
|
|
9880
|
+
}),
|
|
9881
|
+
workflow_update: looseObject({
|
|
9882
|
+
id,
|
|
9883
|
+
name: string2(),
|
|
9884
|
+
summary: string2(),
|
|
9885
|
+
labels: array(jsonObject)
|
|
9886
|
+
}),
|
|
9887
|
+
workflow_list: looseObject({
|
|
9888
|
+
builtins: array(workflowSummary),
|
|
9889
|
+
catalog: array(workflowSummary)
|
|
9663
9890
|
})
|
|
9664
9891
|
};
|
|
9665
9892
|
function outputSchemaFor(actionName) {
|
|
@@ -10029,6 +10256,9 @@ var MCP_TOOL_ANNOTATIONS = {
|
|
|
10029
10256
|
topic_update: additive,
|
|
10030
10257
|
create_thread: additive,
|
|
10031
10258
|
thread_update: additive,
|
|
10259
|
+
workflow_create: additive,
|
|
10260
|
+
workflow_update: additive,
|
|
10261
|
+
workflow_list: readOnly,
|
|
10032
10262
|
thread_assign: idempotent,
|
|
10033
10263
|
thread_list: readOnly,
|
|
10034
10264
|
set_organization_computer: destructiveIdempotent,
|
|
@@ -10387,7 +10617,7 @@ Arbor's MCP is the collaboration and durable-knowledge surface. Configure, autho
|
|
|
10387
10617
|
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). Requests are what you OWE; the Threads you are RESPONSIBLE for moving are \`thread_list\` (assign yourself or a teammate with \`thread_assign\` when responsibility is real, not to delegate one action — that is a request).
|
|
10388
10618
|
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").
|
|
10389
10619
|
5. EDIT, don't repost. \`edit\` your own contribution to sharpen it; the record stays audited. A genuinely different point is a NEW contribution.
|
|
10390
|
-
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 several threads (often across topics) ladder up to one outcome, link or create a GOAL — that's the cross-cut; don't rely on recall alone or fold them into one mega-thread (prefer linking an existing goal over minting a near-duplicate; complete it when the outcome is reached). 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.
|
|
10620
|
+
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 several threads (often across topics) ladder up to one outcome, link or create a GOAL — that's the cross-cut; don't rely on recall alone or fold them into one mega-thread (prefer linking an existing goal over minting a near-duplicate; complete it when the outcome is reached). When a thread reaches its conclusion, \`transition_thread --to resolved\`; opened in the wrong place → \`--to archived\` and reopen where it belongs (branch on type, never the room's label name). 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.
|
|
10391
10621
|
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.
|
|
10392
10622
|
|
|
10393
10623
|
8. DURABLE OUTPUT IS AN ARTIFACT, NOT A LONG CONTRIBUTION (AD-201). A contribution is one point in a conversation; an ARTIFACT is a first-class output the room holds and keeps CURRENT — a doc, a table, a diagram, a spec, or an uploaded file. When your point is really a deliverable the team will read or UPDATE later — a table of options, a reference doc, a plan, a rubric — make it an artifact (\`artifact\` verb=create with kind doc/table/diagram/html + \`source\`, or promote a file) instead of pasting it into prose. Text-kind artifacts are LIVING: \`artifact_get\` it, then \`artifact\` verb=edit naming the \`baseVersion\` you read — patches apply exact-match and atomically, one version per call, every version attributed. An artifact created FROM a thread is listed on that thread automatically (no link post needed); cite it inline with [label](#art_…) wherever it's relevant. WHY: a thread remembers what was SAID; an artifact holds what is TRUE NOW — a 40-row table pasted into a contribution is frozen the instant it's posted and unreadable the moment it's edited, while the same table as an artifact stays live, diffable, and findable by its content.
|
|
@@ -10513,6 +10743,14 @@ var PAGINATION_INPUT = {
|
|
|
10513
10743
|
cursor: string2().optional().describe("opaque cursor from a prior response's nextCursor (use with --limit)"),
|
|
10514
10744
|
all: boolean2().optional().describe("explicit complete retrieval — skip the bounded default page. Prefer limit+cursor unless you need the whole collection")
|
|
10515
10745
|
};
|
|
10746
|
+
var WORKFLOW_LABEL_INPUT = object({
|
|
10747
|
+
key: string2().min(1).describe("stable id within this workflow"),
|
|
10748
|
+
name: string2().min(1).describe("room-facing column name"),
|
|
10749
|
+
type: _enum(LIFECYCLE_TYPES).describe("protocol type this column occupies"),
|
|
10750
|
+
order: number2().int().describe("column order, 0-based"),
|
|
10751
|
+
isDefaultForType: boolean2().optional().describe("required when this type has more than one label"),
|
|
10752
|
+
description: string2().max(WORKFLOW_LABEL_DESCRIPTION_MAX).optional().describe("optional teaching prose; no consumer branches on it")
|
|
10753
|
+
});
|
|
10516
10754
|
var LIVE_PREVIEW_CONFIG_INPUT = {
|
|
10517
10755
|
livePreview: object({
|
|
10518
10756
|
command: string2().min(1).max(4000).describe("explicit project preview command"),
|
|
@@ -10897,11 +11135,12 @@ var ACTION_DEFINITIONS = [
|
|
|
10897
11135
|
{
|
|
10898
11136
|
name: "create_topic",
|
|
10899
11137
|
title: "Create a topic",
|
|
10900
|
-
description: "Create a Topic for a durable sub-area that will hold multiple Threads (check tree first so structure stays scarce); otherwise keep the work in a Thread. Give it one primary operating role
|
|
11138
|
+
description: "Create a Topic for a durable sub-area that will hold multiple Threads (check tree first so structure stays scarce); otherwise keep the work in a Thread. Give it one primary operating role, and pick `--workflow` from `space_get.workflows` by summary or omit to inherit the Space default.",
|
|
10901
11139
|
inputSchema: {
|
|
10902
11140
|
spaceId: string2().describe("the space to create the topic in, spc_…"),
|
|
10903
11141
|
title: string2().min(1).describe("the topic's name — an area of work, not a question"),
|
|
10904
|
-
purpose: string2().optional().describe("what this Topic accomplishes and what belongs here, leading with its primary role — Direction, Delivery, Operations, Intake, Coordination, or Learning; name an external or split source of truth or a handoff boundary only when it materially matters")
|
|
11142
|
+
purpose: string2().optional().describe("what this Topic accomplishes and what belongs here, leading with its primary role — Direction, Delivery, Operations, Intake, Coordination, or Learning; name an external or split source of truth or a handoff boundary only when it materially matters"),
|
|
11143
|
+
workflow: string2().optional().describe("catalog id from `space_get.workflows` (pick by summary); must already be attached to this Space")
|
|
10905
11144
|
},
|
|
10906
11145
|
surfaces: ["mcp", "cli"],
|
|
10907
11146
|
toolset: "structure",
|
|
@@ -10910,11 +11149,12 @@ var ACTION_DEFINITIONS = [
|
|
|
10910
11149
|
{
|
|
10911
11150
|
name: "topic_update",
|
|
10912
11151
|
title: "Edit a topic's title or purpose",
|
|
10913
|
-
description: "Edit a Topic's title or purpose facts, patching only supplied fields. Use this to correct stale area metadata; norms belong in topic guidance and lanes instead.",
|
|
11152
|
+
description: "Edit a Topic's title or purpose facts, or select `--workflow` from `space_get.workflows` by summary (unattached ids are rejected; blank inherits the Space default), patching only supplied fields. Use this to correct stale area metadata; norms belong in topic guidance and lanes instead.",
|
|
10914
11153
|
inputSchema: {
|
|
10915
11154
|
topicId: string2().describe("the topic to edit, top_…"),
|
|
10916
11155
|
title: string2().min(1).optional().describe("a new title — an area of work, not a question"),
|
|
10917
|
-
purpose: string2().optional().describe("a new purpose — what this Topic accomplishes and what belongs here, leading with its primary role (Direction, Delivery, Operations, Intake, Coordination, or Learning); name an external or split source of truth or a handoff boundary only when it materially matters")
|
|
11156
|
+
purpose: string2().optional().describe("a new purpose — what this Topic accomplishes and what belongs here, leading with its primary role (Direction, Delivery, Operations, Intake, Coordination, or Learning); name an external or split source of truth or a handoff boundary only when it materially matters"),
|
|
11157
|
+
workflow: string2().nullable().optional().describe("catalog id from `space_get.workflows` (pick by summary); must be attached to the Space; blank or null inherits the Space default")
|
|
10918
11158
|
},
|
|
10919
11159
|
surfaces: ["mcp", "cli"],
|
|
10920
11160
|
toolset: "spaces",
|
|
@@ -10985,12 +11225,13 @@ var ACTION_DEFINITIONS = [
|
|
|
10985
11225
|
{
|
|
10986
11226
|
name: "thread_update",
|
|
10987
11227
|
title: "Edit a thread's title, objective, or topic",
|
|
10988
|
-
description: "Correct a Thread's title or objective, or move it under another Topic of the same Space, patching only supplied fields; use it to make done clear or refile misfiled work instead of archiving and reopening. Status moves stay with `transition_thread`, and the temporary help list with `charter` ways_to_help.",
|
|
11228
|
+
description: "Correct a Thread's title or objective, or move it under another Topic of the same Space, patching only supplied fields; use it to make done clear or refile misfiled work instead of archiving and reopening. Status moves stay with `transition_thread`, column order with `--rank`, and the temporary help list with `charter` ways_to_help.",
|
|
10989
11229
|
inputSchema: {
|
|
10990
11230
|
threadId: string2().describe("the thread to edit, thr_…"),
|
|
10991
11231
|
title: string2().min(1).optional().describe("a new title — the question, outcome, investigation, instance, or standing concern"),
|
|
10992
11232
|
objective: string2().min(1).optional().describe("a new objective — what this Thread should accomplish; for finite work, what done means"),
|
|
10993
|
-
topicId: string2().optional().describe("move the thread under this topic of the same space, top_…")
|
|
11233
|
+
topicId: string2().optional().describe("move the thread under this topic of the same space, top_…"),
|
|
11234
|
+
rank: string2().max(THREAD_RANK_MAX).regex(THREAD_RANK_PATTERN).nullable().optional().describe("LexoRank string for card order inside one lifecycle column; omit to leave unchanged, null to restore recency")
|
|
10994
11235
|
},
|
|
10995
11236
|
surfaces: ["mcp", "cli"],
|
|
10996
11237
|
toolset: "loop",
|
|
@@ -11510,10 +11751,10 @@ var ACTION_DEFINITIONS = [
|
|
|
11510
11751
|
{
|
|
11511
11752
|
name: "transition_thread",
|
|
11512
11753
|
title: "Move a thread's lifecycle",
|
|
11513
|
-
description:
|
|
11754
|
+
description: transitionThreadActionDescription(),
|
|
11514
11755
|
inputSchema: {
|
|
11515
11756
|
threadId: string2().describe("the thread to move, thr_…"),
|
|
11516
|
-
to:
|
|
11757
|
+
to: string2().min(1).describe("label key, case-insensitive label name, or bare type (`resolved` still works as a type name)"),
|
|
11517
11758
|
reason: string2().optional().describe("optional one-line why, recorded on the event")
|
|
11518
11759
|
},
|
|
11519
11760
|
surfaces: ["mcp", "cli"],
|
|
@@ -12084,17 +12325,57 @@ var ACTION_DEFINITIONS = [
|
|
|
12084
12325
|
{
|
|
12085
12326
|
name: "space_update",
|
|
12086
12327
|
title: "Edit a space's config",
|
|
12087
|
-
description: "Edit a Space's purpose, title, or visibility; org owner/admin or that Space's admin only, and only supplied fields are patched. Use this for factual room metadata, including open/private
|
|
12328
|
+
description: "Edit a Space's purpose, title, or visibility; org owner/admin or that Space's admin only, and only supplied fields are patched. Use this for factual room metadata, including open/private, or org-admin `--attach-workflow` / `--detach-workflow` / `--default-workflow`; collaboration norms belong in Space guidance.",
|
|
12088
12329
|
inputSchema: {
|
|
12089
12330
|
spaceId: string2().describe("the space, spc_…"),
|
|
12090
12331
|
purpose: string2().optional().describe("why this boundary exists and what it is around — commonly a Product/System, Program/Function, Portfolio/Network, or Practice/Community — plus its dominant work modes (Build, Operate, Coordinate, Discuss, Share) when that helps; plain prose, not metadata syntax"),
|
|
12091
12332
|
title: string2().optional().describe("a new title for the space"),
|
|
12092
|
-
visibility: _enum(["open", "private"]).optional().describe("open or private (invite-only)")
|
|
12333
|
+
visibility: _enum(["open", "private"]).optional().describe("open or private (invite-only)"),
|
|
12334
|
+
attachWorkflow: string2().optional().describe("org-admin: attach this catalog workflow id to the Space allowlist"),
|
|
12335
|
+
detachWorkflow: string2().optional().describe("org-admin: detach this catalog workflow; rejected if a Topic still selects it"),
|
|
12336
|
+
defaultWorkflow: string2().optional().describe("org-admin: name which attached workflow new Topics inherit")
|
|
12093
12337
|
},
|
|
12094
12338
|
surfaces: ["mcp", "cli"],
|
|
12095
12339
|
toolset: "spaces",
|
|
12096
12340
|
run: forward("space.update")
|
|
12097
12341
|
},
|
|
12342
|
+
{
|
|
12343
|
+
name: "workflow_create",
|
|
12344
|
+
title: "Create a catalog workflow",
|
|
12345
|
+
description: "Copy a built-in into the org catalog (`--from-builtin`) or author name, summary, and labels. Org-admin; copy-then-edit — the built-in constant is never mutated in place.",
|
|
12346
|
+
inputSchema: {
|
|
12347
|
+
fromBuiltin: _enum(BUILTIN_WORKFLOW_IDS).optional().describe("copy this built-in template into the catalog"),
|
|
12348
|
+
name: string2().min(1).optional().describe("catalog name; defaults from the built-in"),
|
|
12349
|
+
summary: string2().max(WORKFLOW_SUMMARY_MAX).optional().describe("required unless `--from-builtin`; how an agent picks this workflow"),
|
|
12350
|
+
labels: array(WORKFLOW_LABEL_INPUT).optional().describe("required unless `--from-builtin`; ordered columns")
|
|
12351
|
+
},
|
|
12352
|
+
surfaces: ["mcp", "cli"],
|
|
12353
|
+
toolset: "structure",
|
|
12354
|
+
run: forward("workflow.create")
|
|
12355
|
+
},
|
|
12356
|
+
{
|
|
12357
|
+
name: "workflow_update",
|
|
12358
|
+
title: "Edit a catalog workflow",
|
|
12359
|
+
description: "Replace a catalog workflow's summary and labels (optional name); org-admin. A switch that would retype a live thread is rejected with the blocking threads enumerated.",
|
|
12360
|
+
inputSchema: {
|
|
12361
|
+
workflowId: string2().describe("the catalog workflow, wfl_…"),
|
|
12362
|
+
name: string2().min(1).optional().describe("a new catalog name"),
|
|
12363
|
+
summary: string2().min(1).max(WORKFLOW_SUMMARY_MAX).describe("required summary — how an agent picks this workflow"),
|
|
12364
|
+
labels: array(WORKFLOW_LABEL_INPUT).min(1).describe("the full replacement label set")
|
|
12365
|
+
},
|
|
12366
|
+
surfaces: ["mcp", "cli"],
|
|
12367
|
+
toolset: "structure",
|
|
12368
|
+
run: forward("workflow.update")
|
|
12369
|
+
},
|
|
12370
|
+
{
|
|
12371
|
+
name: "workflow_list",
|
|
12372
|
+
title: "List org workflows",
|
|
12373
|
+
description: "List built-in templates and this org's catalog copies, each with its required summary. Org-admin; members read the Space allowlist on `space_get`.",
|
|
12374
|
+
inputSchema: {},
|
|
12375
|
+
surfaces: ["mcp", "cli"],
|
|
12376
|
+
toolset: "structure",
|
|
12377
|
+
run: forward("workflow.list")
|
|
12378
|
+
},
|
|
12098
12379
|
{
|
|
12099
12380
|
name: "agent_register",
|
|
12100
12381
|
title: "Register an agent",
|
|
@@ -12189,7 +12470,7 @@ var ACTION_DEFINITIONS = [
|
|
|
12189
12470
|
{
|
|
12190
12471
|
name: "space_get",
|
|
12191
12472
|
title: "Read a space",
|
|
12192
|
-
description: "Read a Space's durable context—purpose, guidance, contribution lanes, Topics—and a paged member roster with roles, capabilities, and charters (default 50; `total` is the full roster size). Continue with `cursor`, or use `all=true` / `--all` only when you need every member; it cannot modify membership or guidance.",
|
|
12473
|
+
description: "Read a Space's durable context—purpose, guidance, contribution lanes, attached workflows with summaries, Topics—and a paged member roster with roles, capabilities, and charters (default 50; `total` is the full roster size). Continue with `cursor`, or use `all=true` / `--all` only when you need every member; it cannot modify membership or guidance.",
|
|
12193
12474
|
inputSchema: {
|
|
12194
12475
|
spaceId: string2().min(1).describe("the space id"),
|
|
12195
12476
|
...PAGINATION_INPUT
|
|
@@ -12201,7 +12482,7 @@ var ACTION_DEFINITIONS = [
|
|
|
12201
12482
|
{
|
|
12202
12483
|
name: "topic_get",
|
|
12203
12484
|
title: "Read a topic",
|
|
12204
|
-
description: "Read a Topic's durable context, guidance, open requests, promoted artifacts, and a paged Thread roster (default 50; `total` is the full roster size). Continue with `cursor`, or use `all=true` / `--all` only for intentional complete enumeration; for a concrete question in a large Topic, prefer Topic-scoped `recall`.",
|
|
12485
|
+
description: "Read a Topic's durable context, guidance, selected workflow summary, open requests, promoted artifacts, and a paged Thread roster (default 50; `total` is the full roster size). Continue with `cursor`, or use `all=true` / `--all` only for intentional complete enumeration; for a concrete question in a large Topic, prefer Topic-scoped `recall`.",
|
|
12205
12486
|
inputSchema: {
|
|
12206
12487
|
topicId: string2().min(1).describe("the topic id"),
|
|
12207
12488
|
...PAGINATION_INPUT
|
package/package.json
CHANGED