@deeplake/hivemind 0.7.22 → 0.7.24
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/bundle/cli.js +383 -254
- package/codex/bundle/session-start.js +58 -9
- package/codex/bundle/skillify-worker.js +118 -29
- package/codex/bundle/stop.js +1 -1
- package/cursor/bundle/capture.js +1 -1
- package/cursor/bundle/session-end.js +1 -1
- package/cursor/bundle/session-start.js +58 -9
- package/cursor/bundle/skillify-worker.js +118 -29
- package/hermes/bundle/capture.js +1 -1
- package/hermes/bundle/session-end.js +1 -1
- package/hermes/bundle/session-start.js +58 -9
- package/hermes/bundle/skillify-worker.js +118 -29
- package/openclaw/dist/index.js +3 -3
- package/openclaw/dist/skillify-worker.js +118 -29
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/openclaw/skills/SKILL.md +1 -1
- package/package.json +1 -1
- package/pi/extension-source/hivemind.ts +1 -1
|
@@ -90,9 +90,16 @@ function renderFrontmatter(fm) {
|
|
|
90
90
|
lines.push(`description: ${JSON.stringify(fm.description)}`);
|
|
91
91
|
if (fm.trigger)
|
|
92
92
|
lines.push(`trigger: ${JSON.stringify(fm.trigger)}`);
|
|
93
|
+
if (fm.author)
|
|
94
|
+
lines.push(`author: ${fm.author}`);
|
|
93
95
|
lines.push(`source_sessions:`);
|
|
94
96
|
for (const s of fm.source_sessions)
|
|
95
97
|
lines.push(` - ${s}`);
|
|
98
|
+
if (fm.contributors && fm.contributors.length > 0) {
|
|
99
|
+
lines.push(`contributors:`);
|
|
100
|
+
for (const c of fm.contributors)
|
|
101
|
+
lines.push(` - ${c}`);
|
|
102
|
+
}
|
|
96
103
|
lines.push(`version: ${fm.version}`);
|
|
97
104
|
lines.push(`created_by_agent: ${fm.created_by_agent}`);
|
|
98
105
|
lines.push(`created_at: ${fm.created_at}`);
|
|
@@ -109,18 +116,25 @@ function parseFrontmatter(text) {
|
|
|
109
116
|
const head = text.slice(4, end).trim();
|
|
110
117
|
const body = text.slice(end + 4).replace(/^\r?\n/, "");
|
|
111
118
|
const fm = { source_sessions: [] };
|
|
112
|
-
let
|
|
119
|
+
let arrayKey = null;
|
|
113
120
|
for (const raw of head.split(/\r?\n/)) {
|
|
114
|
-
if (
|
|
121
|
+
if (arrayKey) {
|
|
115
122
|
const m2 = raw.match(/^\s+-\s+(.+)$/);
|
|
116
123
|
if (m2) {
|
|
117
|
-
fm
|
|
124
|
+
const arr = fm[arrayKey] ?? [];
|
|
125
|
+
arr.push(m2[1].trim());
|
|
126
|
+
fm[arrayKey] = arr;
|
|
118
127
|
continue;
|
|
119
128
|
}
|
|
120
|
-
|
|
129
|
+
arrayKey = null;
|
|
121
130
|
}
|
|
122
131
|
if (raw.startsWith("source_sessions:")) {
|
|
123
|
-
|
|
132
|
+
arrayKey = "source_sessions";
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (raw.startsWith("contributors:")) {
|
|
136
|
+
arrayKey = "contributors";
|
|
137
|
+
fm.contributors = [];
|
|
124
138
|
continue;
|
|
125
139
|
}
|
|
126
140
|
const m = raw.match(/^([a-zA-Z_]+):\s*(.*)$/);
|
|
@@ -151,11 +165,15 @@ function writeNewSkill(args) {
|
|
|
151
165
|
}
|
|
152
166
|
mkdirSync(dir, { recursive: true });
|
|
153
167
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
168
|
+
const author = args.author && args.author.length > 0 ? args.author : void 0;
|
|
169
|
+
const contributors = author ? [author] : [];
|
|
154
170
|
const fm = {
|
|
155
171
|
name: args.name,
|
|
156
172
|
description: args.description,
|
|
157
173
|
trigger: args.trigger,
|
|
174
|
+
author,
|
|
158
175
|
source_sessions: args.sourceSessions,
|
|
176
|
+
contributors,
|
|
159
177
|
version: 1,
|
|
160
178
|
created_by_agent: args.agent,
|
|
161
179
|
created_at: now,
|
|
@@ -166,7 +184,15 @@ function writeNewSkill(args) {
|
|
|
166
184
|
${args.body.trim()}
|
|
167
185
|
`;
|
|
168
186
|
writeFileSync(path, text);
|
|
169
|
-
return {
|
|
187
|
+
return {
|
|
188
|
+
path,
|
|
189
|
+
action: "created",
|
|
190
|
+
version: 1,
|
|
191
|
+
createdAt: now,
|
|
192
|
+
updatedAt: now,
|
|
193
|
+
author,
|
|
194
|
+
contributors
|
|
195
|
+
};
|
|
170
196
|
}
|
|
171
197
|
function mergeSkill(args) {
|
|
172
198
|
assertValidSkillName(args.name);
|
|
@@ -179,12 +205,20 @@ function mergeSkill(args) {
|
|
|
179
205
|
const prevVersion = parsed?.fm.version ?? 1;
|
|
180
206
|
const prevSources = parsed?.fm.source_sessions ?? [];
|
|
181
207
|
const merged = Array.from(/* @__PURE__ */ new Set([...prevSources, ...args.newSourceSessions]));
|
|
208
|
+
const author = parsed?.fm.author;
|
|
209
|
+
const prevContribs = parsed?.fm.contributors && parsed.fm.contributors.length > 0 ? parsed.fm.contributors : author ? [author] : [];
|
|
210
|
+
const contributors = [...prevContribs];
|
|
211
|
+
if (args.editor && args.editor.length > 0 && !contributors.includes(args.editor)) {
|
|
212
|
+
contributors.push(args.editor);
|
|
213
|
+
}
|
|
182
214
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
183
215
|
const fm = {
|
|
184
216
|
name: args.name,
|
|
185
217
|
description: args.description ?? parsed?.fm.description ?? "",
|
|
186
218
|
trigger: parsed?.fm.trigger,
|
|
219
|
+
author,
|
|
187
220
|
source_sessions: merged,
|
|
221
|
+
contributors,
|
|
188
222
|
version: prevVersion + 1,
|
|
189
223
|
created_by_agent: parsed?.fm.created_by_agent ?? args.agent,
|
|
190
224
|
created_at: parsed?.fm.created_at ?? now,
|
|
@@ -195,7 +229,15 @@ function mergeSkill(args) {
|
|
|
195
229
|
${args.body.trim()}
|
|
196
230
|
`;
|
|
197
231
|
writeFileSync(path, text);
|
|
198
|
-
return {
|
|
232
|
+
return {
|
|
233
|
+
path,
|
|
234
|
+
action: "merged",
|
|
235
|
+
version: fm.version,
|
|
236
|
+
createdAt: fm.created_at,
|
|
237
|
+
updatedAt: fm.updated_at,
|
|
238
|
+
author,
|
|
239
|
+
contributors
|
|
240
|
+
};
|
|
199
241
|
}
|
|
200
242
|
function listSkills(skillsRoot) {
|
|
201
243
|
if (!existsSync(skillsRoot))
|
|
@@ -220,9 +262,14 @@ function resolveSkillsRoot(install, cwd) {
|
|
|
220
262
|
function listAllExistingSkills(cwd) {
|
|
221
263
|
const projectRoot = resolveSkillsRoot("project", cwd);
|
|
222
264
|
const globalRoot = resolveSkillsRoot("global", cwd);
|
|
265
|
+
const tag = (source) => (s) => {
|
|
266
|
+
const parsed = parseFrontmatter(s.body);
|
|
267
|
+
const author = typeof parsed?.fm.author === "string" && parsed.fm.author.length > 0 ? parsed.fm.author : void 0;
|
|
268
|
+
return { name: s.name, body: s.body, source, author };
|
|
269
|
+
};
|
|
223
270
|
const tagged = [
|
|
224
|
-
...listSkills(projectRoot).map((
|
|
225
|
-
...listSkills(globalRoot).map((
|
|
271
|
+
...listSkills(projectRoot).map(tag("project")),
|
|
272
|
+
...listSkills(globalRoot).map(tag("global"))
|
|
226
273
|
];
|
|
227
274
|
const seen = /* @__PURE__ */ new Set();
|
|
228
275
|
const out = [];
|
|
@@ -242,12 +289,13 @@ function renderExistingSkillsBlock(cwd, charCap) {
|
|
|
242
289
|
block: "(no existing skills \u2014 MERGE is NOT a valid choice; pick KEEP or SKIP only)"
|
|
243
290
|
};
|
|
244
291
|
}
|
|
245
|
-
const mergeTargetNames = skills.filter((s) => s.source === "project").map((s) => s.name);
|
|
246
292
|
let total = 0;
|
|
247
293
|
const out = [];
|
|
294
|
+
const mergeTargetNames = [];
|
|
248
295
|
for (const s of skills) {
|
|
249
|
-
const
|
|
250
|
-
const
|
|
296
|
+
const sourceTag = s.source === "project" ? "project" : "global, read-only";
|
|
297
|
+
const authorTag = s.author ? `, author=${s.author}` : "";
|
|
298
|
+
const block = `--- existing skill [${sourceTag}${authorTag}]: ${s.name} ---
|
|
251
299
|
${s.body}
|
|
252
300
|
`;
|
|
253
301
|
if (total + block.length > charCap) {
|
|
@@ -256,6 +304,8 @@ ${s.body}
|
|
|
256
304
|
}
|
|
257
305
|
out.push(block);
|
|
258
306
|
total += block.length;
|
|
307
|
+
if (s.source === "project")
|
|
308
|
+
mergeTargetNames.push(s.name);
|
|
259
309
|
}
|
|
260
310
|
return { mergeTargetNames, block: out.join("\n") };
|
|
261
311
|
}
|
|
@@ -274,7 +324,11 @@ function sqlIdent(name) {
|
|
|
274
324
|
// dist/src/skillify/skills-table.js
|
|
275
325
|
function createSkillsTableSql(tableName) {
|
|
276
326
|
const safe = sqlIdent(tableName);
|
|
277
|
-
return `CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', name TEXT NOT NULL DEFAULT '', project TEXT NOT NULL DEFAULT '', project_key TEXT NOT NULL DEFAULT '', local_path TEXT NOT NULL DEFAULT '', install TEXT NOT NULL DEFAULT 'project', source_sessions TEXT NOT NULL DEFAULT '[]', source_agent TEXT NOT NULL DEFAULT '', scope TEXT NOT NULL DEFAULT 'me', author TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', trigger_text TEXT NOT NULL DEFAULT '', body TEXT NOT NULL DEFAULT '', version BIGINT NOT NULL DEFAULT 1, created_at TEXT NOT NULL DEFAULT '', updated_at TEXT NOT NULL DEFAULT '') USING deeplake`;
|
|
327
|
+
return `CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', name TEXT NOT NULL DEFAULT '', project TEXT NOT NULL DEFAULT '', project_key TEXT NOT NULL DEFAULT '', local_path TEXT NOT NULL DEFAULT '', install TEXT NOT NULL DEFAULT 'project', source_sessions TEXT NOT NULL DEFAULT '[]', source_agent TEXT NOT NULL DEFAULT '', scope TEXT NOT NULL DEFAULT 'me', author TEXT NOT NULL DEFAULT '', contributors TEXT NOT NULL DEFAULT '[]', description TEXT NOT NULL DEFAULT '', trigger_text TEXT NOT NULL DEFAULT '', body TEXT NOT NULL DEFAULT '', version BIGINT NOT NULL DEFAULT 1, created_at TEXT NOT NULL DEFAULT '', updated_at TEXT NOT NULL DEFAULT '') USING deeplake`;
|
|
328
|
+
}
|
|
329
|
+
function addContributorsColumnSql(tableName) {
|
|
330
|
+
const safe = sqlIdent(tableName);
|
|
331
|
+
return `ALTER TABLE "${safe}" ADD COLUMN IF NOT EXISTS contributors TEXT NOT NULL DEFAULT '[]'`;
|
|
278
332
|
}
|
|
279
333
|
function esc(s) {
|
|
280
334
|
return s.replace(/\\/g, "\\\\").replace(/'/g, "''").replace(/[\x01-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
@@ -282,12 +336,20 @@ function esc(s) {
|
|
|
282
336
|
function isMissingTableError(message) {
|
|
283
337
|
if (!message)
|
|
284
338
|
return false;
|
|
339
|
+
if (/\bcolumn\b/i.test(message))
|
|
340
|
+
return false;
|
|
285
341
|
return /Table does not exist|relation .* does not exist|no such table/i.test(message);
|
|
286
342
|
}
|
|
343
|
+
function isMissingContributorsColumnError(message) {
|
|
344
|
+
if (!message)
|
|
345
|
+
return false;
|
|
346
|
+
return /contributors.*(?:does not exist|not found|unknown)/i.test(message) || /(?:does not exist|unknown column).*contributors/i.test(message);
|
|
347
|
+
}
|
|
287
348
|
async function insertSkillRow(args) {
|
|
288
349
|
const id = args.id ?? randomUUID();
|
|
289
350
|
const sourceSessionsJson = JSON.stringify(args.sourceSessions);
|
|
290
|
-
const
|
|
351
|
+
const contributorsJson = JSON.stringify(args.contributors);
|
|
352
|
+
const sql = `INSERT INTO "${sqlIdent(args.tableName)}" (id, name, project, project_key, local_path, install, source_sessions, source_agent, scope, author, contributors, description, trigger_text, body, version, created_at, updated_at) VALUES ('${esc(id)}', '${esc(args.name)}', '${esc(args.project)}', '${esc(args.projectKey)}', '${esc(args.localPath)}', '${esc(args.install)}', '${esc(sourceSessionsJson)}', '${esc(args.sourceAgent)}', '${esc(args.scope)}', '${esc(args.author)}', '${esc(contributorsJson)}', '${esc(args.description)}', '${esc(args.trigger ?? "")}', '${esc(args.body)}', ${args.version}, '${esc(args.createdAt)}', '${esc(args.updatedAt)}')`;
|
|
291
353
|
try {
|
|
292
354
|
await args.query(sql);
|
|
293
355
|
} catch (e) {
|
|
@@ -296,6 +358,11 @@ async function insertSkillRow(args) {
|
|
|
296
358
|
await args.query(sql);
|
|
297
359
|
return;
|
|
298
360
|
}
|
|
361
|
+
if (isMissingContributorsColumnError(e?.message)) {
|
|
362
|
+
await args.query(addContributorsColumnSql(args.tableName));
|
|
363
|
+
await args.query(sql);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
299
366
|
throw e;
|
|
300
367
|
}
|
|
301
368
|
}
|
|
@@ -447,6 +514,14 @@ function runGate(opts) {
|
|
|
447
514
|
}
|
|
448
515
|
}
|
|
449
516
|
|
|
517
|
+
// dist/src/skillify/scope-promotion.js
|
|
518
|
+
function isCrossAuthorMergeVerdict(args) {
|
|
519
|
+
return args.verdict === "MERGE" && args.resultAuthor !== void 0 && args.resultAuthor !== args.userName;
|
|
520
|
+
}
|
|
521
|
+
function resolveRecordScope(args) {
|
|
522
|
+
return args.isCrossAuthorMerge && args.configScope === "me" ? "team" : args.configScope;
|
|
523
|
+
}
|
|
524
|
+
|
|
450
525
|
// dist/src/skillify/state.js
|
|
451
526
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, writeSync, mkdirSync as mkdirSync2, renameSync as renameSync2, existsSync as existsSync4, unlinkSync, openSync, closeSync } from "node:fs";
|
|
452
527
|
import { execSync } from "node:child_process";
|
|
@@ -652,8 +727,6 @@ async function query(sql, retries = 4) {
|
|
|
652
727
|
return [];
|
|
653
728
|
}
|
|
654
729
|
function authorClause() {
|
|
655
|
-
if (cfg.scope === "org")
|
|
656
|
-
return "";
|
|
657
730
|
if (cfg.scope === "team" && cfg.team.length > 0) {
|
|
658
731
|
const list = cfg.team.map((n) => `'${esc2(n)}'`).join(", ");
|
|
659
732
|
return ` AND author IN (${list})`;
|
|
@@ -721,7 +794,7 @@ ${answer}
|
|
|
721
794
|
}
|
|
722
795
|
function buildPrompt(pairs) {
|
|
723
796
|
const existing = renderExistingSkillsBlock(cfg.cwd, EXISTING_SKILLS_CHAR_CAP);
|
|
724
|
-
const mergeTargetsClause = existing.mergeTargetNames.length > 0 ? `MERGE is allowed only if your "name" is EXACTLY one of: [${existing.mergeTargetNames.join(", ")}]. Any other name MUST use KEEP, not MERGE.` : `MERGE is FORBIDDEN \u2014 there are no
|
|
797
|
+
const mergeTargetsClause = existing.mergeTargetNames.length > 0 ? `MERGE is allowed only if your "name" is EXACTLY one of: [${existing.mergeTargetNames.join(", ")}]. Any other name MUST use KEEP, not MERGE.` : `MERGE is FORBIDDEN \u2014 there are no existing skills to merge into. Use KEEP or SKIP only.`;
|
|
725
798
|
return [
|
|
726
799
|
`You are a skill curator for the "${cfg.project}" project. You decide whether the recent`,
|
|
727
800
|
`agent activity below contains a recurring, non-trivial pattern worth crystallizing as a`,
|
|
@@ -731,18 +804,19 @@ function buildPrompt(pairs) {
|
|
|
731
804
|
`- KEEP only if the pattern recurs across at least 3 of the exchanges, is non-obvious to a`,
|
|
732
805
|
` competent engineer, and is not already covered by an existing skill below.`,
|
|
733
806
|
`- SKIP if the activity is one-off, generic engineering work, or already covered.`,
|
|
734
|
-
`- MERGE if the pattern is a meaningful extension of an existing
|
|
807
|
+
`- MERGE if the pattern is a meaningful extension of an existing skill \u2014 produce a`,
|
|
735
808
|
` merged body that incorporates the new evidence without exceeding ~3000 characters or`,
|
|
736
809
|
` covering unrelated domains.`,
|
|
737
810
|
`- ${mergeTargetsClause}`,
|
|
738
|
-
`-
|
|
739
|
-
`
|
|
740
|
-
`
|
|
741
|
-
`
|
|
811
|
+
`- Cross-author MERGE has a real cost: editing a skill authored by someone else is`,
|
|
812
|
+
` recorded as a team-level edit (scope=team, contributors+="${cfg.userName}"). Use it only`,
|
|
813
|
+
` when the new evidence genuinely extends the existing skill; otherwise pick KEEP or SKIP.`,
|
|
814
|
+
` Tags like [project, author=alice] / [global, author=bob] tell you whose skill it is.`,
|
|
742
815
|
`- Skill bodies should follow the existing style: short sections (When to use, Workflow,`,
|
|
743
816
|
` Anti-patterns), concrete commands and file paths drawn from the exchanges, no marketing.`,
|
|
744
817
|
``,
|
|
745
|
-
`=== EXISTING SKILLS (
|
|
818
|
+
`=== EXISTING SKILLS (all MERGE-eligible; [global, author=X] entries from teammate X mean`,
|
|
819
|
+
`cross-author MERGE auto-promotes scope to team) ===`,
|
|
746
820
|
existing.block,
|
|
747
821
|
``,
|
|
748
822
|
`=== RECENT EXCHANGES (prompt + answer pairs, tool calls already stripped) ===`,
|
|
@@ -865,6 +939,17 @@ async function main() {
|
|
|
865
939
|
const watermarkDate = oldest.lastMsg;
|
|
866
940
|
const sourceSessions = usable.map((c) => (c.path.split("/").pop() ?? "").replace(/\.[^.]+$/, ""));
|
|
867
941
|
async function recordToDeeplake(result, verdict2) {
|
|
942
|
+
const author = result.author ?? cfg.userName;
|
|
943
|
+
const isCrossAuthorMerge = isCrossAuthorMergeVerdict({
|
|
944
|
+
verdict: verdict2.verdict,
|
|
945
|
+
resultAuthor: result.author,
|
|
946
|
+
userName: cfg.userName
|
|
947
|
+
});
|
|
948
|
+
const scope = resolveRecordScope({
|
|
949
|
+
configScope: cfg.scope,
|
|
950
|
+
isCrossAuthorMerge
|
|
951
|
+
});
|
|
952
|
+
const contributors = result.contributors;
|
|
868
953
|
try {
|
|
869
954
|
await insertSkillRow({
|
|
870
955
|
query,
|
|
@@ -876,8 +961,9 @@ async function main() {
|
|
|
876
961
|
install: cfg.install,
|
|
877
962
|
sourceSessions,
|
|
878
963
|
sourceAgent: cfg.agent,
|
|
879
|
-
scope
|
|
880
|
-
author
|
|
964
|
+
scope,
|
|
965
|
+
author,
|
|
966
|
+
contributors,
|
|
881
967
|
description: verdict2.description ?? "",
|
|
882
968
|
trigger: verdict2.trigger,
|
|
883
969
|
body: verdict2.body,
|
|
@@ -885,7 +971,7 @@ async function main() {
|
|
|
885
971
|
createdAt: result.createdAt,
|
|
886
972
|
updatedAt: result.updatedAt
|
|
887
973
|
});
|
|
888
|
-
wlog(`recorded to skills table: name=${verdict2.name} v${result.version}`);
|
|
974
|
+
wlog(`recorded to skills table: name=${verdict2.name} v${result.version} author=${author} scope=${scope} contributors=${contributors.length}` + (isCrossAuthorMerge ? " [auto-promoted me->team]" : ""));
|
|
889
975
|
} catch (e) {
|
|
890
976
|
wlog(`skills table insert failed (non-fatal): ${e.message}`);
|
|
891
977
|
}
|
|
@@ -899,7 +985,8 @@ async function main() {
|
|
|
899
985
|
trigger: verdict.trigger,
|
|
900
986
|
body: verdict.body,
|
|
901
987
|
sourceSessions,
|
|
902
|
-
agent: cfg.agent
|
|
988
|
+
agent: cfg.agent,
|
|
989
|
+
author: cfg.userName
|
|
903
990
|
});
|
|
904
991
|
wlog(`wrote new skill: ${result.path}`);
|
|
905
992
|
recordSkill(cfg.projectKey, verdict.name, watermarkUuid, watermarkDate);
|
|
@@ -916,7 +1003,8 @@ async function main() {
|
|
|
916
1003
|
description: verdict.description,
|
|
917
1004
|
body: verdict.body,
|
|
918
1005
|
newSourceSessions: sourceSessions,
|
|
919
|
-
agent: cfg.agent
|
|
1006
|
+
agent: cfg.agent,
|
|
1007
|
+
editor: cfg.userName
|
|
920
1008
|
});
|
|
921
1009
|
wlog(`merged into skill: ${result.path} (v${result.version})`);
|
|
922
1010
|
recordSkill(cfg.projectKey, verdict.name, watermarkUuid, watermarkDate);
|
|
@@ -932,7 +1020,8 @@ async function main() {
|
|
|
932
1020
|
trigger: verdict.trigger,
|
|
933
1021
|
body: verdict.body,
|
|
934
1022
|
sourceSessions,
|
|
935
|
-
agent: cfg.agent
|
|
1023
|
+
agent: cfg.agent,
|
|
1024
|
+
author: cfg.userName
|
|
936
1025
|
});
|
|
937
1026
|
wlog(`wrote new skill (merge fallback): ${result.path}`);
|
|
938
1027
|
recordSkill(cfg.projectKey, verdict.name, watermarkUuid, watermarkDate);
|
package/openclaw/package.json
CHANGED
package/openclaw/skills/SKILL.md
CHANGED
|
@@ -62,7 +62,7 @@ Hivemind also mines reusable Claude skills from agent sessions and stores them i
|
|
|
62
62
|
- `hivemind skillify unpull --user <email>` — remove only that author's pulls
|
|
63
63
|
- `hivemind skillify unpull --not-mine` — remove all pulls except your own
|
|
64
64
|
- `hivemind skillify unpull --dry-run` — preview without touching disk
|
|
65
|
-
- `hivemind skillify scope <me|team
|
|
65
|
+
- `hivemind skillify scope <me|team>` — set sharing scope for new skills
|
|
66
66
|
- `hivemind skillify install <project|global>` — default install location
|
|
67
67
|
- `hivemind skillify team add|remove|list <name>` — manage team list
|
|
68
68
|
|
package/package.json
CHANGED
|
@@ -725,7 +725,7 @@ SKILLS (skillify) — mine + share reusable skills across the org. Run these in
|
|
|
725
725
|
- hivemind skillify unpull --user <email> — remove only that author's pulls
|
|
726
726
|
- hivemind skillify unpull --not-mine — remove all pulls except your own
|
|
727
727
|
- hivemind skillify unpull --dry-run — preview without touching disk
|
|
728
|
-
- hivemind skillify scope <me|team
|
|
728
|
+
- hivemind skillify scope <me|team> — sharing scope for new skills
|
|
729
729
|
- hivemind skillify install <project|global> — default install location
|
|
730
730
|
- hivemind skillify team add|remove|list <name> — manage team list`;
|
|
731
731
|
|