superbee 0.4.4-pre.14 → 0.4.4-pre.16
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 +48 -1
- package/SKILL.md +2 -2
- package/dist/publication-bridge.mjs +47 -21
- package/dist/publication.mjs +47 -21
- package/dist/superbee.mjs +37021 -35907
- package/package.json +2 -2
- package/references/hosted-checkout.md +31 -0
- package/references/modeling-and-delivery.md +32 -0
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ first-party support promise for native Windows. An older installed version is no
|
|
|
78
78
|
removed by this source change, and existing bundle files are not migrated by it. Review the affected release's notes before changing an existing
|
|
79
79
|
Windows installation. macOS/Linux users can continue using the normal installation and setup flow.
|
|
80
80
|
|
|
81
|
-
Run `superbee version --check`
|
|
81
|
+
Run `superbee version` to see which build you have. `superbee version --check` is not available on published builds yet: it exits 1 with `policy_disabled` and makes no network request. Check the npm page or `npm view superbee version` for the current release.
|
|
82
82
|
|
|
83
83
|
## First run: let your agent finish setup
|
|
84
84
|
|
|
@@ -127,6 +127,51 @@ In a hosted checkout, `superbee view read <id>` prints a View page's version on
|
|
|
127
127
|
`superbee view update <id> --expected-version <version>` replaces the page there (sync never sends
|
|
128
128
|
`views/`). Uploading a page never approves its execution.
|
|
129
129
|
|
|
130
|
+
## Copying documents between bundles
|
|
131
|
+
|
|
132
|
+
`superbee doc import` copies chosen documents from another bundle with new ids and rewritten links.
|
|
133
|
+
Declare the source first, then review the plan before applying it:
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
superbee deps add wave --bundle-id <source-bundle-id> --path ../wave
|
|
137
|
+
superbee doc import --from wave --with wave=../wave --select type=Theme --prefix wave
|
|
138
|
+
superbee doc import --from wave --with wave=../wave --select type=Theme --prefix wave --apply <plan-token>
|
|
139
|
+
superbee doc import --from wave --with wave=../wave --refresh <record-id>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The first import command only prints the plan and its token. Applying writes new documents and one
|
|
143
|
+
Promotion record, and never overwrites a document. `--resume <record-id>` finishes an interrupted
|
|
144
|
+
run. `--refresh <record-id>` updates the copies from their sources with the same plan and apply
|
|
145
|
+
steps; a copy edited since the import is a conflict until you name it with `--overwrite <id>` or
|
|
146
|
+
`--skip <id>`. The target must be a local bundle or Git board. `superbee doc import --help` has the
|
|
147
|
+
full reference.
|
|
148
|
+
|
|
149
|
+
## When a document cannot be read
|
|
150
|
+
|
|
151
|
+
Superbee bounds how much frontmatter it parses: 262,144 characters of YAML, 32 levels of nesting, and limits on
|
|
152
|
+
YAML alias use. Ordinary documents are far below these limits. A write over a limit is refused with
|
|
153
|
+
`USAGE` and nothing is stored. A document already in the bundle that is over a limit, or whose YAML
|
|
154
|
+
is invalid, cannot be read:
|
|
155
|
+
|
|
156
|
+
- `doc read` on it fails with `RUNTIME`. `details.frontmatter.code` is `FRONTMATTER_TOO_LARGE`,
|
|
157
|
+
`FRONTMATTER_TOO_DEEP`, `FRONTMATTER_ALIAS_LIMIT`, `FRONTMATTER_CYCLE` or
|
|
158
|
+
`FRONTMATTER_MALFORMED`, and `details.frontmatter.document` names the file.
|
|
159
|
+
- To find every affected document, run `superbee status` (the `malformed` count and rows) or
|
|
160
|
+
`superbee list` (the `skipped` rows). `search`, `query`, `index generate`, `link list`,
|
|
161
|
+
`link show`, `view list` and `kinds --coverage` also skip it, say so, and keep working.
|
|
162
|
+
- To fix it, edit the lines between the `---` markers in a text editor, or remove the document with
|
|
163
|
+
`superbee doc delete <id>`. `doc update` and `doc field` cannot change a document they cannot read.
|
|
164
|
+
|
|
165
|
+
On a Git board, `sync` holds a changed file it cannot read: it exits 5, names the file, and commits
|
|
166
|
+
and pushes nothing until you fix it. If a conflict kept a version that cannot be read, the receipt
|
|
167
|
+
tells you to copy your saved export over the document.
|
|
168
|
+
|
|
169
|
+
In a hosted checkout, a host document this client cannot store comes back as a `held` row named with
|
|
170
|
+
its `FRONTMATTER_*` code, exit 5, and everything else proceeds. The next sync places it once it is
|
|
171
|
+
repaired on the host. If the checkout's own local store holds a copy it cannot read, sync stops with
|
|
172
|
+
`store_damaged` and sends and places nothing. Reads continue and `status` reports it. Copy out any
|
|
173
|
+
unsent edits and make a fresh checkout, as the error's help describes.
|
|
174
|
+
|
|
130
175
|
## Upgrading from aslite
|
|
131
176
|
|
|
132
177
|
If you installed the earlier `@holaxis/aslite` package or its marketplace plugin: install
|
|
@@ -139,6 +184,8 @@ run `npm uninstall -g @holaxis/aslite`. Existing `.agentstate-lite/` bundles and
|
|
|
139
184
|
The [repository](https://github.com/Holaxis-ai/superbee) holds the source, the
|
|
140
185
|
[CLI contract](https://github.com/Holaxis-ai/superbee/blob/main/packages/superbee/AXI-CONTRACT.md),
|
|
141
186
|
and the [wire protocol](https://github.com/Holaxis-ai/superbee/blob/main/docs/WIRE-PROTOCOL.md).
|
|
187
|
+
Site builders can read a publication's Site declaration through `superbee/publication/site-manifest`;
|
|
188
|
+
see [Site declarations](https://github.com/Holaxis-ai/superbee/blob/main/packages/publication/SITE-MANIFEST.md).
|
|
142
189
|
|
|
143
190
|
## License
|
|
144
191
|
|
package/SKILL.md
CHANGED
|
@@ -74,7 +74,7 @@ files, and stop. Use `superbee <command> --help` for exact current syntax rather
|
|
|
74
74
|
copied command manual. Use `--body-file` for multiline Markdown. `list` / `query` filter metadata, not body text; `doc update` / `doc field` patch metadata while preserving omitted fields and body. For body edits, read the complete body with `doc read <id> --body-out <temp-file>` outside the bundle, edit that temporary file, then `doc update <id> --body-file <temp-file> --expected-version <head_version> --actor <actor>` using the version from the read. Re-read and reconcile on a version conflict. Never feed a truncated preview or a full-document `--out` export to `--body-file`: body input is Markdown only; tooling owns YAML frontmatter. With MCP, use available tools and version preconditions; check tool schemas rather than inventing search or patch verbs.
|
|
75
75
|
|
|
76
76
|
Focused shipped material is available under `$REFS/recipes/` for portable examples,
|
|
77
|
-
`$REFS/views/` for View authoring and examples, and `$REFS/sample-bundle/` for OKF interop. Integration authoring and explicit local source bind/run use `$REFS/author-an-integration.md`; recorded `$REFS/integrations/` examples need no credentials.
|
|
77
|
+
`$REFS/views/` for View authoring and examples, and `$REFS/sample-bundle/` for OKF interop. Integration authoring and explicit local source bind/run use `$REFS/author-an-integration.md`; recorded `$REFS/integrations/` examples need no credentials. `RUNTIME` with `details.frontmatter.code` means a document cannot be read: see "When a document cannot be read" in `$REFS/modeling-and-delivery.md`, which also covers `superbee doc import`.
|
|
78
78
|
Read only what the accepted work requires.
|
|
79
79
|
|
|
80
80
|
## Make the value visible
|
|
@@ -93,7 +93,7 @@ When the tone fits, a single 🐝 may mark a successful Superbee outcome.
|
|
|
93
93
|
|
|
94
94
|
## Sync conflicts
|
|
95
95
|
|
|
96
|
-
- A Git board and a hosted checkout share one playbook. When `superbee sync` exits 5 with conflict rows, run `superbee sync --inspect --doc <id>` to see your version and theirs, then `superbee sync --resolve keep|take|revise --doc <id>`: keep writes yours over theirs, take keeps theirs, revise keeps the document as you edited it to the merged result. `--resolve` never sends: run `superbee sync` after keep or revise. A Git board has already kept the teammate's version and saved yours aside;
|
|
96
|
+
- A Git board and a hosted checkout share one playbook. When `superbee sync` exits 5 with conflict rows, run `superbee sync --inspect --doc <id>` to see your version and theirs, then `superbee sync --resolve keep|take|revise --doc <id>`: keep writes yours over theirs, take keeps theirs, revise keeps the document as you edited it to the merged result. `--resolve` never sends: run `superbee sync` after keep or revise. A Git board has already kept the teammate's version and saved yours aside, and only the new conflict exits 5: `status` and later `sync` runs keep naming the saved copy, with the command that discards it, until it is settled; keep is refused when your copy also differs in frontmatter, so edit the document to the result and use revise. A hosted checkout keeps your file, treats any concurrent change to one document (even different frontmatter keys) as a conflict, and is explained in `$REFS/hosted-checkout.md`.
|
|
97
97
|
|
|
98
98
|
## Host setup
|
|
99
99
|
|
|
@@ -3175,8 +3175,18 @@ function parseFrontmatter(source, context, options = {}) {
|
|
|
3175
3175
|
}
|
|
3176
3176
|
return normalizeFrontmatter(parsed, options);
|
|
3177
3177
|
}
|
|
3178
|
+
function isStackExhaustion(error) {
|
|
3179
|
+
if (error instanceof RangeError) return /call stack/i.test(error.message);
|
|
3180
|
+
return error?.name === "InternalError" && /recursion/i.test(error.message);
|
|
3181
|
+
}
|
|
3178
3182
|
function stringifyFrontmatter(data) {
|
|
3179
|
-
|
|
3183
|
+
let dumped;
|
|
3184
|
+
try {
|
|
3185
|
+
dumped = import_js_yaml2.default.safeDump(data).trim();
|
|
3186
|
+
} catch (error) {
|
|
3187
|
+
if (isStackExhaustion(error)) throw new FrontmatterRefusedError("FRONTMATTER_TOO_DEEP", `YAML nesting is deeper than ${FRONTMATTER_LIMITS.depth} levels`);
|
|
3188
|
+
throw error;
|
|
3189
|
+
}
|
|
3180
3190
|
try {
|
|
3181
3191
|
yamlEngine.parse(`${dumped}
|
|
3182
3192
|
`);
|
|
@@ -3268,6 +3278,17 @@ function isReservedFile(relPath) {
|
|
|
3268
3278
|
const base = toPosix(relPath).split("/").pop() ?? "";
|
|
3269
3279
|
return RESERVED_FILENAMES.includes(base);
|
|
3270
3280
|
}
|
|
3281
|
+
function isHiddenWalkEntry(name) {
|
|
3282
|
+
return name.startsWith(".");
|
|
3283
|
+
}
|
|
3284
|
+
function hasMarkdownExtension(name) {
|
|
3285
|
+
return name.toLowerCase().endsWith(".md");
|
|
3286
|
+
}
|
|
3287
|
+
function classifyWalkPath(relPath) {
|
|
3288
|
+
const segments = toPosix(relPath).split("/").filter((segment) => segment !== "");
|
|
3289
|
+
if (segments.some(isHiddenWalkEntry)) return "hidden";
|
|
3290
|
+
return hasMarkdownExtension(segments.at(-1) ?? "") ? "markdown" : "other";
|
|
3291
|
+
}
|
|
3271
3292
|
function conceptIdFromPath(relPath) {
|
|
3272
3293
|
const norm = toPosix(relPath).replace(/^\.?\//, "").split("/").filter((segment) => segment !== ".").join("/");
|
|
3273
3294
|
return norm.endsWith(".md") ? norm.slice(0, -3) : norm;
|
|
@@ -3998,24 +4019,7 @@ function hasSourceIdentity(sources, identity) {
|
|
|
3998
4019
|
return Array.isArray(sources) && sources.some((entry) => matchesSourceIdentity(entry, identity));
|
|
3999
4020
|
}
|
|
4000
4021
|
|
|
4001
|
-
// ../core/src/
|
|
4002
|
-
async function readBundleOkfVersion(backend) {
|
|
4003
|
-
const index = await backend.readReserved("", "index.md");
|
|
4004
|
-
if (!index) return void 0;
|
|
4005
|
-
const value = parseLeadingFrontmatter(index.content, "index.md").okf_version;
|
|
4006
|
-
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
4007
|
-
}
|
|
4008
|
-
function assertReadableConceptId(id) {
|
|
4009
|
-
assertSafeConceptId(id);
|
|
4010
|
-
const rel = pathFromConceptId(id);
|
|
4011
|
-
if (isReservedFile(rel)) {
|
|
4012
|
-
throw new InvalidInputError(`'${id}' is a reserved file (index.md / log.md), not a concept document.`);
|
|
4013
|
-
}
|
|
4014
|
-
}
|
|
4015
|
-
async function readDocVersioned(backend, id) {
|
|
4016
|
-
assertReadableConceptId(id);
|
|
4017
|
-
return backend.read(id);
|
|
4018
|
-
}
|
|
4022
|
+
// ../core/src/document-scan.ts
|
|
4019
4023
|
function isEnoent(err) {
|
|
4020
4024
|
return typeof err === "object" && err !== null && err.code === "ENOENT";
|
|
4021
4025
|
}
|
|
@@ -4046,6 +4050,25 @@ async function readManyExisting(backend, ids, onMalformed, onAliased) {
|
|
|
4046
4050
|
return out;
|
|
4047
4051
|
}
|
|
4048
4052
|
}
|
|
4053
|
+
|
|
4054
|
+
// ../core/src/engine.ts
|
|
4055
|
+
async function readBundleOkfVersion(backend) {
|
|
4056
|
+
const index = await backend.readReserved("", "index.md");
|
|
4057
|
+
if (!index) return void 0;
|
|
4058
|
+
const value = parseLeadingFrontmatter(index.content, "index.md").okf_version;
|
|
4059
|
+
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
4060
|
+
}
|
|
4061
|
+
function assertReadableConceptId(id) {
|
|
4062
|
+
assertSafeConceptId(id);
|
|
4063
|
+
const rel = pathFromConceptId(id);
|
|
4064
|
+
if (isReservedFile(rel)) {
|
|
4065
|
+
throw new InvalidInputError(`'${id}' is a reserved file (index.md / log.md), not a concept document.`);
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
async function readDocVersioned(backend, id) {
|
|
4069
|
+
assertReadableConceptId(id);
|
|
4070
|
+
return backend.read(id);
|
|
4071
|
+
}
|
|
4049
4072
|
async function scanMatching(backend, filter, onSkip) {
|
|
4050
4073
|
const ids = await backend.list(filter.prefix);
|
|
4051
4074
|
const results = [];
|
|
@@ -5321,7 +5344,7 @@ async function walkFiles(port, root, keep, sub = "") {
|
|
|
5321
5344
|
const entries = await port.entries(path3.join(root, sub)) ?? [];
|
|
5322
5345
|
const out = [];
|
|
5323
5346
|
for (const entry of entries) {
|
|
5324
|
-
if (entry.name
|
|
5347
|
+
if (isHiddenWalkEntry(entry.name)) continue;
|
|
5325
5348
|
const rel = sub === "" ? entry.name : `${sub}/${entry.name}`;
|
|
5326
5349
|
if (entry.kind === "directory") {
|
|
5327
5350
|
out.push(...await walkFiles(port, root, keep, rel));
|
|
@@ -5580,12 +5603,15 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
5580
5603
|
return observed.state === "exact" && observed.value.kind === "file";
|
|
5581
5604
|
}
|
|
5582
5605
|
async listBlobs(prefix) {
|
|
5583
|
-
const files = await walkFiles(this.#port, this.#root, (name) => !name
|
|
5606
|
+
const files = await walkFiles(this.#port, this.#root, (name) => !hasMarkdownExtension(name));
|
|
5584
5607
|
const keys2 = files.map(toPosix);
|
|
5585
5608
|
const filtered = prefix ? keys2.filter((k) => k.startsWith(prefix)) : keys2;
|
|
5586
5609
|
filtered.sort(compareStorageKeys);
|
|
5587
5610
|
return filtered;
|
|
5588
5611
|
}
|
|
5612
|
+
classifyChangedPath(relPath) {
|
|
5613
|
+
return classifyWalkPath(relPath);
|
|
5614
|
+
}
|
|
5589
5615
|
capabilities() {
|
|
5590
5616
|
return {
|
|
5591
5617
|
history: false,
|
package/dist/publication.mjs
CHANGED
|
@@ -31129,8 +31129,18 @@ function parseFrontmatter(source, context, options = {}) {
|
|
|
31129
31129
|
}
|
|
31130
31130
|
return normalizeFrontmatter(parsed, options);
|
|
31131
31131
|
}
|
|
31132
|
+
function isStackExhaustion(error) {
|
|
31133
|
+
if (error instanceof RangeError) return /call stack/i.test(error.message);
|
|
31134
|
+
return error?.name === "InternalError" && /recursion/i.test(error.message);
|
|
31135
|
+
}
|
|
31132
31136
|
function stringifyFrontmatter(data) {
|
|
31133
|
-
|
|
31137
|
+
let dumped;
|
|
31138
|
+
try {
|
|
31139
|
+
dumped = import_js_yaml2.default.safeDump(data).trim();
|
|
31140
|
+
} catch (error) {
|
|
31141
|
+
if (isStackExhaustion(error)) throw new FrontmatterRefusedError("FRONTMATTER_TOO_DEEP", `YAML nesting is deeper than ${FRONTMATTER_LIMITS.depth} levels`);
|
|
31142
|
+
throw error;
|
|
31143
|
+
}
|
|
31134
31144
|
try {
|
|
31135
31145
|
yamlEngine.parse(`${dumped}
|
|
31136
31146
|
`);
|
|
@@ -31222,6 +31232,17 @@ function isReservedFile(relPath) {
|
|
|
31222
31232
|
const base = toPosix(relPath).split("/").pop() ?? "";
|
|
31223
31233
|
return RESERVED_FILENAMES.includes(base);
|
|
31224
31234
|
}
|
|
31235
|
+
function isHiddenWalkEntry(name) {
|
|
31236
|
+
return name.startsWith(".");
|
|
31237
|
+
}
|
|
31238
|
+
function hasMarkdownExtension(name) {
|
|
31239
|
+
return name.toLowerCase().endsWith(".md");
|
|
31240
|
+
}
|
|
31241
|
+
function classifyWalkPath(relPath) {
|
|
31242
|
+
const segments = toPosix(relPath).split("/").filter((segment) => segment !== "");
|
|
31243
|
+
if (segments.some(isHiddenWalkEntry)) return "hidden";
|
|
31244
|
+
return hasMarkdownExtension(segments.at(-1) ?? "") ? "markdown" : "other";
|
|
31245
|
+
}
|
|
31225
31246
|
function conceptIdFromPath(relPath) {
|
|
31226
31247
|
const norm = toPosix(relPath).replace(/^\.?\//, "").split("/").filter((segment) => segment !== ".").join("/");
|
|
31227
31248
|
return norm.endsWith(".md") ? norm.slice(0, -3) : norm;
|
|
@@ -31959,24 +31980,7 @@ function hasSourceIdentity(sources, identity) {
|
|
|
31959
31980
|
return Array.isArray(sources) && sources.some((entry) => matchesSourceIdentity(entry, identity));
|
|
31960
31981
|
}
|
|
31961
31982
|
|
|
31962
|
-
// ../core/src/
|
|
31963
|
-
async function readBundleOkfVersion(backend) {
|
|
31964
|
-
const index2 = await backend.readReserved("", "index.md");
|
|
31965
|
-
if (!index2) return void 0;
|
|
31966
|
-
const value = parseLeadingFrontmatter(index2.content, "index.md").okf_version;
|
|
31967
|
-
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
31968
|
-
}
|
|
31969
|
-
function assertReadableConceptId(id) {
|
|
31970
|
-
assertSafeConceptId(id);
|
|
31971
|
-
const rel = pathFromConceptId(id);
|
|
31972
|
-
if (isReservedFile(rel)) {
|
|
31973
|
-
throw new InvalidInputError(`'${id}' is a reserved file (index.md / log.md), not a concept document.`);
|
|
31974
|
-
}
|
|
31975
|
-
}
|
|
31976
|
-
async function readDocVersioned(backend, id) {
|
|
31977
|
-
assertReadableConceptId(id);
|
|
31978
|
-
return backend.read(id);
|
|
31979
|
-
}
|
|
31983
|
+
// ../core/src/document-scan.ts
|
|
31980
31984
|
function isEnoent(err) {
|
|
31981
31985
|
return typeof err === "object" && err !== null && err.code === "ENOENT";
|
|
31982
31986
|
}
|
|
@@ -32007,6 +32011,25 @@ async function readManyExisting(backend, ids, onMalformed, onAliased) {
|
|
|
32007
32011
|
return out;
|
|
32008
32012
|
}
|
|
32009
32013
|
}
|
|
32014
|
+
|
|
32015
|
+
// ../core/src/engine.ts
|
|
32016
|
+
async function readBundleOkfVersion(backend) {
|
|
32017
|
+
const index2 = await backend.readReserved("", "index.md");
|
|
32018
|
+
if (!index2) return void 0;
|
|
32019
|
+
const value = parseLeadingFrontmatter(index2.content, "index.md").okf_version;
|
|
32020
|
+
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
32021
|
+
}
|
|
32022
|
+
function assertReadableConceptId(id) {
|
|
32023
|
+
assertSafeConceptId(id);
|
|
32024
|
+
const rel = pathFromConceptId(id);
|
|
32025
|
+
if (isReservedFile(rel)) {
|
|
32026
|
+
throw new InvalidInputError(`'${id}' is a reserved file (index.md / log.md), not a concept document.`);
|
|
32027
|
+
}
|
|
32028
|
+
}
|
|
32029
|
+
async function readDocVersioned(backend, id) {
|
|
32030
|
+
assertReadableConceptId(id);
|
|
32031
|
+
return backend.read(id);
|
|
32032
|
+
}
|
|
32010
32033
|
async function scanMatching(backend, filter, onSkip) {
|
|
32011
32034
|
const ids = await backend.list(filter.prefix);
|
|
32012
32035
|
const results = [];
|
|
@@ -33282,7 +33305,7 @@ async function walkFiles(port, root, keep, sub = "") {
|
|
|
33282
33305
|
const entries = await port.entries(path3.join(root, sub)) ?? [];
|
|
33283
33306
|
const out = [];
|
|
33284
33307
|
for (const entry of entries) {
|
|
33285
|
-
if (entry.name
|
|
33308
|
+
if (isHiddenWalkEntry(entry.name)) continue;
|
|
33286
33309
|
const rel = sub === "" ? entry.name : `${sub}/${entry.name}`;
|
|
33287
33310
|
if (entry.kind === "directory") {
|
|
33288
33311
|
out.push(...await walkFiles(port, root, keep, rel));
|
|
@@ -33541,12 +33564,15 @@ var FilesystemBackend = class _FilesystemBackend {
|
|
|
33541
33564
|
return observed.state === "exact" && observed.value.kind === "file";
|
|
33542
33565
|
}
|
|
33543
33566
|
async listBlobs(prefix) {
|
|
33544
|
-
const files = await walkFiles(this.#port, this.#root, (name) => !name
|
|
33567
|
+
const files = await walkFiles(this.#port, this.#root, (name) => !hasMarkdownExtension(name));
|
|
33545
33568
|
const keys2 = files.map(toPosix);
|
|
33546
33569
|
const filtered = prefix ? keys2.filter((k) => k.startsWith(prefix)) : keys2;
|
|
33547
33570
|
filtered.sort(compareStorageKeys);
|
|
33548
33571
|
return filtered;
|
|
33549
33572
|
}
|
|
33573
|
+
classifyChangedPath(relPath) {
|
|
33574
|
+
return classifyWalkPath(relPath);
|
|
33575
|
+
}
|
|
33550
33576
|
capabilities() {
|
|
33551
33577
|
return {
|
|
33552
33578
|
history: false,
|