From 457c29b36a1a33528d81bd76b3435697e405dfad Mon Sep 17 00:00:00 2001 From: Gio Della-Libera Date: Fri, 8 May 2026 20:38:21 -0700 Subject: [PATCH] docs(path): scrub references to dropped grammar features --- docs/cli/path.md | 16 ++++++++-------- extensions/oc-path/src/oc-path/emit.ts | 3 +-- extensions/oc-path/src/oc-path/jsonc/resolve.ts | 3 --- extensions/oc-path/src/oc-path/jsonl/resolve.ts | 1 - extensions/oc-path/src/oc-path/resolve.ts | 2 +- .../oc-path/src/oc-path/tests/edit.test.ts | 2 +- .../tests/scenarios/frontmatter-edges.test.ts | 2 +- 7 files changed, 12 insertions(+), 17 deletions(-) diff --git a/docs/cli/path.md b/docs/cli/path.md index be3090d7571c..4053082bdd4c 100644 --- a/docs/cli/path.md +++ b/docs/cli/path.md @@ -11,7 +11,7 @@ title: "Path" Plugin-provided shell access to the `oc://` addressing substrate — one universal, kind-dispatched path scheme for inspecting and surgically editing workspace -files (markdown, jsonc, jsonl, yaml). Self-hosters and editor extensions use +files (markdown, jsonc, jsonl). Self-hosters and editor extensions use it to read or write a single leaf inside a workspace file without scripting against the SDK directly. @@ -45,17 +45,17 @@ Slot rules — `field` requires `item`, `item` requires `section`. Across all four slots: - **Quoted segments** — `"a/b.c"` survives `/` and `.` separators. - `"\\"` and `"\""` are the only escapes inside quotes. - The file slot is also quote-aware: `oc://"skills/email-drafter"/Tools/-1` + Content is byte-literal; `"` and `\` are not allowed inside quotes. + The file slot is also quote-aware: `oc://"skills/email-drafter"/Tools/$last` treats `skills/email-drafter` as a single file path. -- **Predicates** — `[k=v]`, `[k!=v]`, `[k*=v]`, `[k^=v]`, `[k$=v]`, - `[kv]`, `[k>=v]`. +- **Predicates** — `[k=v]`, `[k!=v]`, `[kv]`, + `[k>=v]`. Numeric ops require both sides to coerce to finite numbers. - **Unions** — `{a,b,c}` matches any of the alternatives. - **Wildcards** — `*` (single sub-segment) and `**` (zero-or-more, recursive). `find` accepts these; `resolve` and `set` reject them as ambiguous. -- **Positional** — `$first`, `$last`, `-N` (Nth from end). -- **Ordinal** — `#N` for Nth match. +- **Positional** — `$last` resolves to the last index / last-declared key. +- **Ordinal** — `#N` for Nth match by document order. - **Insertion markers** — `+`, `+key`, `+nnn` for keyed / indexed insertion (use with `set`). - **Session scope** — `?session=cron:daily` etc. Orthogonal to slot @@ -69,7 +69,7 @@ rejected anywhere. ```bash # Validate a path (no filesystem access) -openclaw path validate 'oc://AGENTS.md/Tools/-1/risk' +openclaw path validate 'oc://AGENTS.md/Tools/$last/risk' # Read a leaf openclaw path resolve 'oc://gateway.jsonc/version' diff --git a/extensions/oc-path/src/oc-path/emit.ts b/extensions/oc-path/src/oc-path/emit.ts index 89006237c08d..ad0ca54b0ac6 100644 --- a/extensions/oc-path/src/oc-path/emit.ts +++ b/extensions/oc-path/src/oc-path/emit.ts @@ -115,8 +115,7 @@ export function emitMd(ast: MdAst, opts: EmitOptions = {}): string { } function formatFrontmatterValue(value: string): string { - // Quote values containing characters that would confuse a YAML - // parser; otherwise emit bare. + // Frontmatter is yaml-ish; quote values with structural chars. if (value.length === 0) { return '""'; } diff --git a/extensions/oc-path/src/oc-path/jsonc/resolve.ts b/extensions/oc-path/src/oc-path/jsonc/resolve.ts index 5069d1de0a18..5533ed07abce 100644 --- a/extensions/oc-path/src/oc-path/jsonc/resolve.ts +++ b/extensions/oc-path/src/oc-path/jsonc/resolve.ts @@ -47,9 +47,6 @@ export function resolveJsoncOcPath(ast: JsoncAst, path: OcPath): JsoncOcPathMatc for (let seg of segments) { if (seg.length === 0) {return null;} - // `-N` on an indexable container is positional; on a keyed - // container it falls through to literal-key lookup (e.g. Telegram - // supergroup IDs — openclaw#59934). if (isPositionalSeg(seg)) { const concrete = positionalForJsonc(current, seg); if (concrete !== null) {seg = concrete;} diff --git a/extensions/oc-path/src/oc-path/jsonl/resolve.ts b/extensions/oc-path/src/oc-path/jsonl/resolve.ts index 788963f30a96..d74aa0e76225 100644 --- a/extensions/oc-path/src/oc-path/jsonl/resolve.ts +++ b/extensions/oc-path/src/oc-path/jsonl/resolve.ts @@ -84,7 +84,6 @@ export function resolveJsonlOcPath(ast: JsonlAst, path: OcPath): JsonlOcPathMatc if (seg.length === 0) { return null; } - // See openclaw#59934 — positional `-N` falls through on keyed containers. if (isPositionalSeg(seg)) { const concrete = positionalForJsonc(current, seg); if (concrete !== null) { diff --git a/extensions/oc-path/src/oc-path/resolve.ts b/extensions/oc-path/src/oc-path/resolve.ts index 6bd6f8f22424..25ae98fdbf46 100644 --- a/extensions/oc-path/src/oc-path/resolve.ts +++ b/extensions/oc-path/src/oc-path/resolve.ts @@ -47,7 +47,7 @@ export function resolveMdOcPath(ast: MdAst, path: OcPath): OcPathMatch | null { if (block === undefined) {return null;} if (path.item === undefined) {return { kind: "block", node: block };} - // Item dispatch: ordinal (#N) > positional ($first/$last/-N) > slug. + // Item dispatch: ordinal (#N) > positional ($last) > slug. // Ordinal uses document order so duplicate-slug items stay distinct. let item: AstItem | undefined; if (isOrdinalSeg(path.item)) { diff --git a/extensions/oc-path/src/oc-path/tests/edit.test.ts b/extensions/oc-path/src/oc-path/tests/edit.test.ts index 35d89b31b891..1db85f576b44 100644 --- a/extensions/oc-path/src/oc-path/tests/edit.test.ts +++ b/extensions/oc-path/src/oc-path/tests/edit.test.ts @@ -28,7 +28,7 @@ Body. expect(r).toEqual({ ok: false, reason: "unresolved" }); }); - it("quotes values that need YAML-escaping", () => { + it("quotes frontmatter values containing structural chars", () => { const { ast } = parseMd("---\nx: a\n---\n"); const r = setOcPath(ast, parseOcPath("oc://AGENTS.md/[frontmatter]/x"), "has: colon"); expect(r.ok).toBe(true); diff --git a/extensions/oc-path/src/oc-path/tests/scenarios/frontmatter-edges.test.ts b/extensions/oc-path/src/oc-path/tests/scenarios/frontmatter-edges.test.ts index d7b2cb2aac6e..1e9a3a414d49 100644 --- a/extensions/oc-path/src/oc-path/tests/scenarios/frontmatter-edges.test.ts +++ b/extensions/oc-path/src/oc-path/tests/scenarios/frontmatter-edges.test.ts @@ -125,7 +125,7 @@ describe("frontmatter-edges", () => { expect(ast.frontmatter).toEqual([]); }); - it("hash-prefixed lines skipped (not yaml comments — just don't match kv regex)", () => { + it("hash-prefixed lines skipped (don't match kv regex)", () => { const { ast } = parseMd("---\n# comment\nk: v\n---\n"); expect(ast.frontmatter.map((e) => e.key)).toEqual(["k"]); });