From 9488b2716cb01fbace4d82dfc7e2ef3fc3a6e431 Mon Sep 17 00:00:00 2001 From: aaltshuler Date: Tue, 7 Jul 2026 00:45:30 +0300 Subject: [PATCH 1/2] docs(skill): align the omnigraph skill with 0.8.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Undirected traversal documented (SKILL.md quick-rules + embedded grammar + references/queries.md worked example, marked >= 0.8.1). - Enum widening documented as a supported metadata-only apply (references/schema.md), with the still-refused shapes listed. - Two standing inaccuracies fixed: `{1,}` was documented as unbounded traversal but the typechecker rejects unbounded (T15); the required-property recipe's final "tighten to required" step is refused by the planner (OG-MF-106) — the recipe now says to keep the property optional until required-tightening ships. - Skill metadata version -> 0.8.1; compatibility note marks the version-gated features. --- skills/omnigraph/SKILL.md | 12 +++++++----- skills/omnigraph/references/queries.md | 20 ++++++++++++++++++++ skills/omnigraph/references/schema.md | 12 +++++++++++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/skills/omnigraph/SKILL.md b/skills/omnigraph/SKILL.md index 2bd0fb98..49a19b65 100644 --- a/skills/omnigraph/SKILL.md +++ b/skills/omnigraph/SKILL.md @@ -2,10 +2,10 @@ name: omnigraph description: Store, retrieve, and query knowledge, memory, and relationships in an Omnigraph graph, and operate a local or remote Omnigraph deployment. Use when the user wants to capture or recall facts, notes, or entities, build or query a knowledge graph or agent memory, or run Omnigraph — and whenever you see Omnigraph CLI commands (omnigraph init/query/mutate/load/schema/lint/embed/branch/commit/login/profile/cluster), .pg schema or .gq query files, s3:// graph URIs, bearer-authed graph endpoints, 504 errors, or a cluster.yaml / omnigraph.yaml / ~/.omnigraph/config.yaml. Covers cluster-mode deployments (cluster.yaml plan/apply, omnigraph-server --cluster), the two config surfaces (cluster.yaml + ~/.omnigraph/config.yaml), schema evolution, query linting, data writes (mutate; load needs --mode/--from), branches, embeddings, Cedar policy, and remote ops. Especially important before schema apply (plan first), any load (--mode required), any .gq/.pg edit (lint after), or any remote write (verify via commit list). license: MIT (see LICENSE at repo root) -compatibility: Requires omnigraph CLI >= 0.7.0 — the unified `load`, the two config surfaces (cluster.yaml + ~/.omnigraph/config.yaml), and cluster apply/serve all require 0.7.0. +compatibility: Requires omnigraph CLI >= 0.7.0 — the unified `load`, the two config surfaces (cluster.yaml + ~/.omnigraph/config.yaml), and cluster apply/serve all require 0.7.0. Version-gated features are marked inline (undirected traversal `` and enum widening in `schema apply` require >= 0.8.1). metadata: author: ModernRelay - version: "0.7.0" + version: "0.8.1" repository: https://github.com/ModernRelay/omnigraph --- @@ -96,7 +96,8 @@ The non-obvious facts that bite, then the full grammar: - **Scalar param types**: `String Bool I32 I64 U32 U64 F32 F64 DateTime Date Blob`. Modifiers: `T?` (optional), `[T]` (list), `Vector(N)`. There is **no `Int`** — use `I64`. - **A read query needs `match` *and* `return`** (`order`/`limit` optional); a mutation has neither — only `insert`/`update`/`delete`. - **`limit` takes an integer literal, not a param** — `limit 50`, never `limit $n`. -- **Variable-hop traversal**: `$p knows{1,3} $f` (`{1,}` = unbounded). +- **Variable-hop traversal**: `$p knows{1,3} $f` — bounds are **required to be finite** (`{1,}` is rejected: "unbounded traversal is disabled"). +- **Undirected traversal** (omnigraph >= 0.8.1): `$p $f` matches the edge in either direction, deduplicated (a pair connected both ways appears once). Same-endpoint-type edges only (e.g. `Related: Issue -> Issue`) — asymmetric edges are rejected (T22). Composes with bounds (`$p {1,3} $f`) and `not { }`. Replaces the query-both-directions-and-merge workaround for symmetric relations. - **Literals & calls**: `now()`, `date("2026-04-29")`, `datetime("…T00:00:00Z")`, list `[…]`. - **Filters** `= != > < >= <= contains`; **aggregates** `count/sum/avg/min/max` (`count($f) as n`). - **Stored-query metadata**: `@description("…")` / `@instruction("…")` may follow the param list. @@ -159,8 +160,9 @@ prop_match_list = { prop_match ~ ("," ~ prop_match)* ~ ","? } prop_match = { ident ~ ":" ~ match_value } match_value = { literal | variable | now_call } -// Traversal: $p knows $f -traversal = { variable ~ edge_ident ~ traversal_bounds? ~ variable } +// Traversal: $p knows $f (directional) or $p $f (undirected, >= 0.8.1) +traversal = { variable ~ (undirected_edge | edge_ident) ~ traversal_bounds? ~ variable } +undirected_edge = { "<" ~ edge_ident ~ ">" } traversal_bounds = { "{" ~ integer ~ "," ~ integer? ~ "}" } // Filter: $f.age > 25 diff --git a/skills/omnigraph/references/queries.md b/skills/omnigraph/references/queries.md index f9f84e08..32498ab0 100644 --- a/skills/omnigraph/references/queries.md +++ b/skills/omnigraph/references/queries.md @@ -115,6 +115,26 @@ query employees_of($company: String) { } ``` +### Undirected traversal (omnigraph >= 0.8.1) + +For symmetric relations (same-endpoint-type edges like `Related: Issue -> Issue`), +angle brackets match the edge in **either direction**, deduplicated — one +pattern replaces querying both directions and merging: + +```gq +query related_to($slug: String) { + match { + $i: Issue { slug: $slug } + $i $r + } + return { $r.slug } +} +``` + +Composes with hop bounds (`$a {1,3} $b`) and `not { }` ("no edge in +either direction"). Asymmetric edges (e.g. `Comment -> Issue`) are rejected at +typecheck (T22) — use the directional form there. + ### Negation ```gq diff --git a/skills/omnigraph/references/schema.md b/skills/omnigraph/references/schema.md index b30745b5..fc882dcf 100644 --- a/skills/omnigraph/references/schema.md +++ b/skills/omnigraph/references/schema.md @@ -106,7 +106,17 @@ Adding a non-nullable property to an existing node is rejected as unsupported. P 1. Add as optional: `new_prop: String?` 2. Apply 3. Backfill via a `mutate` or `load --mode merge` -4. Tighten to required in a follow-up apply: `new_prop: String` +4. Keep it optional: tightening `T?` -> `T` is currently refused by the planner + (a property-type change, OG-MF-106). Enforce presence at write time by + convention until required-tightening ships as a migration step. + +### Enum widening is a supported apply (omnigraph >= 0.8.1) + +Adding variants to an `enum(...)` property is a metadata-only migration step: +`schema plan` shows `extend enum ...`, `apply` touches no table data, and new +variants are accepted immediately on every write surface. Narrowing, renaming +a variant, or converting enum <-> `String` still refuse (OG-MF-106) — those +remain rebuild territory. Value *order* never matters (values are normalized). ### Keep `@key` stable From 5ea0e6ba2eeae33f86f909aa92a914df6c5f0556 Mon Sep 17 00:00:00 2001 From: aaltshuler Date: Tue, 7 Jul 2026 01:43:49 +0300 Subject: [PATCH 2/2] =?UTF-8?q?docs(skill):=20review=20follow-ups=20?= =?UTF-8?q?=E2=80=94=20gotcha-table=20consistency,=20stale=20D2=20note,=20?= =?UTF-8?q?example=20naming?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Devin caught the gotchas table still advising the tighten-in-follow-up recipe this PR corrects elsewhere; the D2 note claiming deletes inline-commit (staged since 0.8.0 — the rule is a deliberate boundary, not an implementation gap); and the undirected example describing `Related` while traversing `` (text now names `IssueRelated` per the PascalCase->lowerCamelCase convention). --- skills/omnigraph/SKILL.md | 2 +- skills/omnigraph/references/queries.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/skills/omnigraph/SKILL.md b/skills/omnigraph/SKILL.md index 49a19b65..ffbf9522 100644 --- a/skills/omnigraph/SKILL.md +++ b/skills/omnigraph/SKILL.md @@ -377,7 +377,7 @@ These are the traps most likely to bite. Scan this table before debugging any pa | `load --mode merge` after `@embed` source change | stale embeddings | `omnigraph embed --reembed_all` or `load --mode overwrite` | | `schema apply` with feature branches open | rejected | Merge or delete branches first | | `nearest(...)` / `bm25(...)` / `rrf(...)` without `limit` | compile error | Add `limit N` | -| Adding non-nullable property without backfill | unsupported migration | Make optional → backfill → tighten in follow-up apply | +| Adding non-nullable property without backfill | unsupported migration | Make optional → backfill; keep it optional (tightening `T?` → `T` is refused, OG-MF-106) | | `omnigraph init --json` | `unexpected argument --json` | `init` doesn't support `--json`; drop the flag | | `omnigraph init` on an already-initialized URI | `AlreadyInitialized` error (v0.6.0+) | `--force` to re-init (skips the schema preflight; does **not** purge data) | | `schema apply` dropping a property/type | soft-dropped or rejected (no data loss) | add `--allow-data-loss` to actually drop the column | diff --git a/skills/omnigraph/references/queries.md b/skills/omnigraph/references/queries.md index 32498ab0..f2415786 100644 --- a/skills/omnigraph/references/queries.md +++ b/skills/omnigraph/references/queries.md @@ -117,7 +117,7 @@ query employees_of($company: String) { ### Undirected traversal (omnigraph >= 0.8.1) -For symmetric relations (same-endpoint-type edges like `Related: Issue -> Issue`), +For symmetric relations (same-endpoint-type edges like `IssueRelated: Issue -> Issue`), angle brackets match the edge in **either direction**, deduplicated — one pattern replaces querying both directions and merging: @@ -291,7 +291,7 @@ query add_and_link($slug: String, $pattern: String, $createdAt: DateTime, $updat There's no `upsert` keyword at the query level — use `load --mode merge` for bulk upsert. -> **Insert/update-only OR delete-only (the D₂ rule).** A single mutation query may contain inserts and updates, **or** deletes — never both. Mixing a `delete` with an `insert`/`update` in the same query is rejected at parse time. (Inserts/updates go through a staged two-phase publish; deletes inline-commit — omnigraph doesn't yet use Lance's two-phase delete API (it shipped in Lance 7.0.0 but isn't wired in) — so they can't share one atomic statement.) Split a delete-then-insert into two separate mutations. +> **Insert/update-only OR delete-only (the D₂ rule).** A single mutation query may contain inserts and updates, **or** deletes — never both. Mixing a `delete` with an `insert`/`update` in the same query is rejected at parse time. (Deletes stage through the same two-phase publish as inserts/updates since 0.8.0; the D₂ split is a deliberate semantic boundary — one mutation query is constructive XOR destructive, keeping read-your-writes unambiguous — not an implementation gap.) Split a delete-then-insert into two separate mutations. ### Date and DateTime values