superbee 0.1.4 → 0.1.5-pre.2
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/README.md +26 -14
- package/dist/publication-bridge.mjs +148 -40
- package/dist/publication.mjs +182 -45
- package/dist/superbee.mjs +27640 -25020
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -40,24 +40,36 @@ know invisible to the humans they work for. Superbee fixes all three:
|
|
|
40
40
|
The npm package ships one self-contained executable with zero runtime dependencies, plus an
|
|
41
41
|
Agent Skill that teaches agents how to use it.
|
|
42
42
|
|
|
43
|
-
##
|
|
43
|
+
## How do I download Superbee on Windows?
|
|
44
44
|
|
|
45
|
-
**Requirements: Node.js 20 or newer on macOS, Linux, or Windows.**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
the globally installed `superbee.cmd` entrypoint are covered by the required CI contract.
|
|
45
|
+
**Requirements: Node.js 20 or newer on macOS, Linux, or native Windows.** You do not need WSL,
|
|
46
|
+
Ubuntu, or Docker. On Windows, Superbee keeps per-user operational state under
|
|
47
|
+
`%LOCALAPPDATA%\Superbee`; npm installs the command as `superbee.cmd`.
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
Superbee currently has two npm release channels:
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
- `latest` is the stable channel selected by bare `superbee`. Its current release predates native
|
|
52
|
+
Windows support.
|
|
53
|
+
- `next` is the prerelease channel. It contains the current native-Windows build.
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
Install the current prerelease on Windows:
|
|
56
|
+
|
|
57
|
+
```powershell
|
|
58
|
+
npm install -g superbee@next
|
|
59
|
+
superbee.cmd setup
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
On macOS or Linux, the stable channel remains available with `npm install -g superbee`. To test the
|
|
63
|
+
same prerelease as Windows, install `superbee@next` instead.
|
|
64
|
+
|
|
65
|
+
After installation, ask your AI agent to run `superbee setup` (`superbee.cmd setup` when invoking
|
|
66
|
+
the Windows shim explicitly). Setup walks the agent through Agent Skill, SessionStart hook, and MCP
|
|
67
|
+
registration. It is read-only: it inspects your configuration and returns one safe next command at
|
|
68
|
+
a time, so the agent performs any actual changes with your approval.
|
|
69
|
+
|
|
70
|
+
The managed Agent Skill works in Claude Code, Codex, and OpenCode. OpenCode discovers Superbee from
|
|
71
|
+
its documented Claude-compatible Skill path. It shares Claude Code's Skill bytes by default; if
|
|
72
|
+
Claude Code is explicitly relocated, the installer manages the two documented host paths separately.
|
|
61
73
|
|
|
62
74
|
Upgrading from the legacy `@holaxis/aslite` package or the retired marketplace plugin? Install
|
|
63
75
|
`superbee` alongside it, have your agent run `superbee setup` to migrate the exact legacy
|
|
@@ -1153,7 +1153,7 @@ var require_omap = __commonJS({
|
|
|
1153
1153
|
var _toString = Object.prototype.toString;
|
|
1154
1154
|
function resolveYamlOmap(data) {
|
|
1155
1155
|
if (data === null) return true;
|
|
1156
|
-
var objectKeys =
|
|
1156
|
+
var objectKeys = {}, index, length, pair, pairKey, pairHasKey, object = data;
|
|
1157
1157
|
for (index = 0, length = object.length; index < length; index += 1) {
|
|
1158
1158
|
pair = object[index];
|
|
1159
1159
|
pairHasKey = false;
|
|
@@ -1165,8 +1165,8 @@ var require_omap = __commonJS({
|
|
|
1165
1165
|
}
|
|
1166
1166
|
}
|
|
1167
1167
|
if (!pairHasKey) return false;
|
|
1168
|
-
if (
|
|
1169
|
-
|
|
1168
|
+
if (_hasOwnProperty.call(objectKeys, pairKey)) return false;
|
|
1169
|
+
Object.defineProperty(objectKeys, pairKey, { value: true });
|
|
1170
1170
|
}
|
|
1171
1171
|
return true;
|
|
1172
1172
|
}
|
|
@@ -1603,17 +1603,22 @@ var require_loader = __commonJS({
|
|
|
1603
1603
|
state.result += _result;
|
|
1604
1604
|
}
|
|
1605
1605
|
}
|
|
1606
|
+
function chargeMergeWork(state) {
|
|
1607
|
+
state.totalMergeKeys += 1;
|
|
1608
|
+
if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) {
|
|
1609
|
+
throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1606
1612
|
function mergeMappings(state, destination, source, overridableKeys) {
|
|
1607
1613
|
var sourceKeys, key, index, quantity;
|
|
1608
1614
|
if (!common.isObject(source)) {
|
|
1609
1615
|
throwError(state, "cannot merge mappings; the provided source object is unacceptable");
|
|
1610
1616
|
}
|
|
1617
|
+
chargeMergeWork(state);
|
|
1611
1618
|
sourceKeys = Object.keys(source);
|
|
1612
1619
|
for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
|
|
1613
1620
|
key = sourceKeys[index];
|
|
1614
|
-
|
|
1615
|
-
throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
|
|
1616
|
-
}
|
|
1621
|
+
chargeMergeWork(state);
|
|
1617
1622
|
if (!_hasOwnProperty.call(destination, key)) {
|
|
1618
1623
|
setProperty(destination, key, source[key]);
|
|
1619
1624
|
overridableKeys[key] = true;
|
|
@@ -1642,6 +1647,9 @@ var require_loader = __commonJS({
|
|
|
1642
1647
|
}
|
|
1643
1648
|
if (keyTag === "tag:yaml.org,2002:merge") {
|
|
1644
1649
|
if (Array.isArray(valueNode)) {
|
|
1650
|
+
if (valueNode.length > 100) {
|
|
1651
|
+
throwError(state, "abnormal merge sequence size");
|
|
1652
|
+
}
|
|
1645
1653
|
for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {
|
|
1646
1654
|
mergeMappings(state, _result, valueNode[index], overridableKeys);
|
|
1647
1655
|
}
|
|
@@ -3582,6 +3590,13 @@ var MalformedDocumentError = class extends Error {
|
|
|
3582
3590
|
}
|
|
3583
3591
|
};
|
|
3584
3592
|
function parseMarkdown(raw, context) {
|
|
3593
|
+
if (/^---(?:\r?\n|$)/.test(raw)) {
|
|
3594
|
+
const firstLineEnd = raw.indexOf("\n");
|
|
3595
|
+
const afterOpening = firstLineEnd === -1 ? "" : raw.slice(firstLineEnd + 1);
|
|
3596
|
+
if (!/^---\r?$/m.test(afterOpening)) {
|
|
3597
|
+
throw new MalformedDocumentError(context, new Error("unterminated YAML frontmatter delimiter"));
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3585
3600
|
let parsed;
|
|
3586
3601
|
try {
|
|
3587
3602
|
parsed = (0, import_gray_matter.default)(raw, { engines: { yaml: yamlEngine } });
|
|
@@ -3591,16 +3606,20 @@ function parseMarkdown(raw, context) {
|
|
|
3591
3606
|
const frontmatter2 = normalizeFrontmatter(parsed.data ?? {});
|
|
3592
3607
|
return { frontmatter: frontmatter2, body: parsed.content };
|
|
3593
3608
|
}
|
|
3609
|
+
function normalizeDocumentBodyForStorage(body) {
|
|
3610
|
+
return body.endsWith("\n") ? body : `${body}
|
|
3611
|
+
`;
|
|
3612
|
+
}
|
|
3594
3613
|
function stringifyWithData(data, body) {
|
|
3595
3614
|
const engines2 = import_gray_matter.default.engines;
|
|
3596
3615
|
const yaml3 = engines2.yaml.stringify(data).trim();
|
|
3597
3616
|
const content = body ?? "";
|
|
3598
3617
|
const newline = (value) => value.endsWith("\n") ? value : `${value}
|
|
3599
3618
|
`;
|
|
3600
|
-
if (yaml3 === "{}") return
|
|
3619
|
+
if (yaml3 === "{}") return normalizeDocumentBodyForStorage(content);
|
|
3601
3620
|
return `---
|
|
3602
3621
|
${newline(yaml3)}---
|
|
3603
|
-
${
|
|
3622
|
+
${normalizeDocumentBodyForStorage(content)}`;
|
|
3604
3623
|
}
|
|
3605
3624
|
function stringifyDoc(frontmatter2, body) {
|
|
3606
3625
|
return stringifyWithData(frontmatter2, body);
|
|
@@ -3885,6 +3904,33 @@ function processExists(pid) {
|
|
|
3885
3904
|
return err.code !== "ESRCH";
|
|
3886
3905
|
}
|
|
3887
3906
|
}
|
|
3907
|
+
function staleLockQuarantinePath(lockPath, owner) {
|
|
3908
|
+
const tokenHash = createHash("sha256").update(owner.token).digest("hex");
|
|
3909
|
+
return `${lockPath}.stale-${tokenHash}`;
|
|
3910
|
+
}
|
|
3911
|
+
async function pathExists(candidate) {
|
|
3912
|
+
try {
|
|
3913
|
+
await fs.lstat(candidate);
|
|
3914
|
+
return true;
|
|
3915
|
+
} catch (err) {
|
|
3916
|
+
if (err.code === "ENOENT") return false;
|
|
3917
|
+
throw err;
|
|
3918
|
+
}
|
|
3919
|
+
}
|
|
3920
|
+
async function quarantineStaleLock(lockPath, owner) {
|
|
3921
|
+
if (owner.hostname !== hostname() || processExists(owner.pid)) return false;
|
|
3922
|
+
const quarantinePath = staleLockQuarantinePath(lockPath, owner);
|
|
3923
|
+
try {
|
|
3924
|
+
await fs.rename(lockPath, quarantinePath);
|
|
3925
|
+
return true;
|
|
3926
|
+
} catch (err) {
|
|
3927
|
+
const code = err.code;
|
|
3928
|
+
if (code === "ENOENT") return false;
|
|
3929
|
+
if (await pathExists(quarantinePath)) return false;
|
|
3930
|
+
if (process.platform === "win32" && WINDOWS_DIRECTORY_CONTENTION_CODES.has(code ?? "")) return false;
|
|
3931
|
+
throw err;
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3888
3934
|
function delay(ms) {
|
|
3889
3935
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3890
3936
|
}
|
|
@@ -3947,46 +3993,74 @@ async function selectLockRoot(options2) {
|
|
|
3947
3993
|
await ensurePrivateLockRoot(lockRoot);
|
|
3948
3994
|
return lockRoot;
|
|
3949
3995
|
}
|
|
3996
|
+
var WINDOWS_DIRECTORY_CONTENTION_CODES = /* @__PURE__ */ new Set(["EACCES", "EBUSY", "EPERM"]);
|
|
3997
|
+
async function classifyLockClaimFailure(error, lockPath) {
|
|
3998
|
+
const code = error.code;
|
|
3999
|
+
if (code === "EEXIST") return "contention";
|
|
4000
|
+
if (process.platform !== "win32" || !WINDOWS_DIRECTORY_CONTENTION_CODES.has(code ?? "")) return "terminal";
|
|
4001
|
+
try {
|
|
4002
|
+
await fs.lstat(lockPath);
|
|
4003
|
+
return "contention";
|
|
4004
|
+
} catch (probeError) {
|
|
4005
|
+
const probeCode = probeError.code;
|
|
4006
|
+
return probeCode === "ENOENT" || probeCode === "ENOTDIR" ? "unwitnessed-windows-sharing-error" : "terminal";
|
|
4007
|
+
}
|
|
4008
|
+
}
|
|
3950
4009
|
async function claimLockPath(lockPath, owner, waitMs, pollMs) {
|
|
3951
4010
|
const started = owner.created_at_ms;
|
|
4011
|
+
let unwitnessedWindowsRetryUsed = false;
|
|
3952
4012
|
while (true) {
|
|
3953
4013
|
try {
|
|
3954
4014
|
await fs.mkdir(lockPath, { mode: 448 });
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
}
|
|
3963
|
-
|
|
3964
|
-
});
|
|
3965
|
-
throw err;
|
|
4015
|
+
} catch (err) {
|
|
4016
|
+
const failure = await classifyLockClaimFailure(err, lockPath);
|
|
4017
|
+
if (failure === "terminal") throw err;
|
|
4018
|
+
if (failure === "unwitnessed-windows-sharing-error") {
|
|
4019
|
+
if (unwitnessedWindowsRetryUsed) throw err;
|
|
4020
|
+
unwitnessedWindowsRetryUsed = true;
|
|
4021
|
+
continue;
|
|
4022
|
+
} else {
|
|
4023
|
+
unwitnessedWindowsRetryUsed = false;
|
|
3966
4024
|
}
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
if (
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
}
|
|
3984
|
-
};
|
|
4025
|
+
let existingOwner = await readOwner(lockPath);
|
|
4026
|
+
if (existingOwner !== null) {
|
|
4027
|
+
if (await quarantineStaleLock(lockPath, existingOwner)) continue;
|
|
4028
|
+
existingOwner = await readOwner(lockPath);
|
|
4029
|
+
}
|
|
4030
|
+
if (Date.now() - started >= waitMs) throw timeoutError(lockPath, existingOwner, owner.target);
|
|
4031
|
+
await delay(pollMs);
|
|
4032
|
+
continue;
|
|
4033
|
+
}
|
|
4034
|
+
try {
|
|
4035
|
+
await fs.writeFile(path.join(lockPath, OWNER_FILE), `${JSON.stringify(owner)}
|
|
4036
|
+
`, {
|
|
4037
|
+
encoding: "utf8",
|
|
4038
|
+
flag: "wx",
|
|
4039
|
+
mode: 384
|
|
4040
|
+
});
|
|
3985
4041
|
} catch (err) {
|
|
3986
|
-
|
|
4042
|
+
await fs.rm(lockPath, { recursive: true, force: true }).catch(() => {
|
|
4043
|
+
});
|
|
4044
|
+
throw err;
|
|
3987
4045
|
}
|
|
3988
|
-
|
|
3989
|
-
|
|
4046
|
+
return async () => {
|
|
4047
|
+
const current = await readOwner(lockPath);
|
|
4048
|
+
if (current?.token !== owner.token) {
|
|
4049
|
+
throw new FilesystemMutationLockError(
|
|
4050
|
+
`refusing to release filesystem mutation lock '${lockPath}' because its owner token changed; the mutation may have completed, inspect the lock before retrying.`,
|
|
4051
|
+
{ lockPath, owner: current, stale: false, malformed: current === null }
|
|
4052
|
+
);
|
|
4053
|
+
}
|
|
4054
|
+
try {
|
|
4055
|
+
await fs.rm(lockPath, { recursive: true, force: false });
|
|
4056
|
+
} catch (err) {
|
|
4057
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4058
|
+
throw new FilesystemMutationLockError(
|
|
4059
|
+
`mutation completed but filesystem lock '${lockPath}' could not be removed (${message}); inspect the lock before retrying.`,
|
|
4060
|
+
{ lockPath, owner: current, stale: false, malformed: false }
|
|
4061
|
+
);
|
|
4062
|
+
}
|
|
4063
|
+
};
|
|
3990
4064
|
}
|
|
3991
4065
|
}
|
|
3992
4066
|
function newOwner(target) {
|
|
@@ -5038,6 +5112,10 @@ var VALID_FIELDS_KEYS = /* @__PURE__ */ new Set([
|
|
|
5038
5112
|
"descriptions"
|
|
5039
5113
|
]);
|
|
5040
5114
|
var MISPLACED_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["enum", "enums", "values", "constraints"]);
|
|
5115
|
+
var CLAIM_COORDINATE_KEYS = [
|
|
5116
|
+
["owner_field", "ownerField"],
|
|
5117
|
+
["state_field", "stateField"]
|
|
5118
|
+
];
|
|
5041
5119
|
function parseConventionDoc(doc) {
|
|
5042
5120
|
const fm = doc.frontmatter;
|
|
5043
5121
|
const governs = typeof fm.governs === "string" ? fm.governs.trim() : "";
|
|
@@ -5346,6 +5424,35 @@ function parseConventionDoc(doc) {
|
|
|
5346
5424
|
if (Object.keys(parsed).length > 0) expectsInbound = parsed;
|
|
5347
5425
|
}
|
|
5348
5426
|
}
|
|
5427
|
+
const claimSource = fm.claim;
|
|
5428
|
+
let claim;
|
|
5429
|
+
if (claimSource !== void 0) {
|
|
5430
|
+
if (!isPlainObject(claimSource)) {
|
|
5431
|
+
warnings.push({
|
|
5432
|
+
code: "KIND_CONVENTION_BAD_SHAPE",
|
|
5433
|
+
message: `kind convention '${doc.id}' has a non-map 'claim' key (${describeShape(claimSource)}; expected a map declaring 'owner_field' and/or 'state_field'); ignoring it.`,
|
|
5434
|
+
field: "claim",
|
|
5435
|
+
severity: "warning"
|
|
5436
|
+
});
|
|
5437
|
+
} else {
|
|
5438
|
+
const parsed = {};
|
|
5439
|
+
for (const [key, target] of CLAIM_COORDINATE_KEYS) {
|
|
5440
|
+
const declared = claimSource[key];
|
|
5441
|
+
if (declared === void 0) continue;
|
|
5442
|
+
if (!isScalar(declared) || String(declared).trim() === "") {
|
|
5443
|
+
warnings.push({
|
|
5444
|
+
code: "KIND_CONVENTION_BAD_MEMBER",
|
|
5445
|
+
message: `kind convention '${doc.id}' has a malformed 'claim.${key}' (${describeShape(declared)}; expected a declared field name); skipping it.`,
|
|
5446
|
+
field: `claim.${key}`,
|
|
5447
|
+
severity: "warning"
|
|
5448
|
+
});
|
|
5449
|
+
continue;
|
|
5450
|
+
}
|
|
5451
|
+
parsed[target] = String(declared).trim();
|
|
5452
|
+
}
|
|
5453
|
+
if (parsed.ownerField !== void 0 || parsed.stateField !== void 0) claim = parsed;
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5349
5456
|
const sections = Array.isArray(fm.sections) ? fm.sections.filter((s) => typeof s === "string" && s.trim() !== "") : void 0;
|
|
5350
5457
|
const title = typeof fm.title === "string" && fm.title.trim() !== "" ? fm.title.trim() : governs;
|
|
5351
5458
|
let description;
|
|
@@ -5378,6 +5485,7 @@ function parseConventionDoc(doc) {
|
|
|
5378
5485
|
if (sections && sections.length > 0) kind.sections = sections;
|
|
5379
5486
|
if (freshnessHorizon !== void 0) kind.freshnessHorizon = freshnessHorizon;
|
|
5380
5487
|
if (browseCollapsed !== void 0) kind.browseCollapsed = browseCollapsed;
|
|
5488
|
+
if (claim !== void 0) kind.claim = claim;
|
|
5381
5489
|
return {
|
|
5382
5490
|
ok: true,
|
|
5383
5491
|
kind,
|