@younndai/lyt-skills 0.9.5 → 0.9.6
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 +5 -4
- package/package.json +3 -3
- package/skills/lyt-alias/SKILL.md +92 -0
- package/skills/lyt-capture/SKILL.md +1 -1
- package/skills/lyt-mesh-explore/SKILL.md +16 -57
- package/skills/lyt-pod/SKILL.md +11 -11
- package/skills/lyt-primer-context/SKILL.md +16 -16
- package/skills/lyt-search/SKILL.md +5 -5
- package/skills/lyt-sync/SKILL.md +10 -10
package/README.md
CHANGED
|
@@ -24,20 +24,20 @@
|
|
|
24
24
|
|
|
25
25
|
## What is this?
|
|
26
26
|
|
|
27
|
-
`@younndai/lyt-skills` is where [Lyt™](https://github.com/YounndAI/lyt)'s **AI-first** design becomes tangible:
|
|
27
|
+
`@younndai/lyt-skills` is where [Lyt™](https://github.com/YounndAI/lyt)'s **AI-first** design becomes tangible: sixteen harness skills that let AI agents — Claude Code, Codex, and generic agent runtimes — drive your markdown vaults as **first-class operators**. Install once and your agent can capture notes, search your pod, record decisions, write plans, retros, and handoffs, explore meshes, and sync vaults — through the same governed operation set you use, under the same permission semantics. This is the "install once, every agent runtime knows Lyt" layer.
|
|
28
28
|
|
|
29
|
-
Most skills wrap a pattern verb from the `lyt pattern run` runtime, so structured knowledge work (plans, results, decisions, captures) shows up as first-class agent skills inside any vault; the read/orient skills (`/lyt-pod`, `/lyt-search`, `/lyt-primer-context`, `/lyt-mesh-explore`, `/lyt-sync`) wrap the corresponding CLI verbs directly. Pairs with [`@younndai/lyt-vault`](https://www.npmjs.com/package/@younndai/lyt-vault), which ships the four default patterns the skills resolve against.
|
|
29
|
+
Most skills wrap a pattern verb from the `lyt pattern run` runtime, so structured knowledge work (plans, results, decisions, captures) shows up as first-class agent skills inside any vault; the read/orient + addressing skills (`/lyt-pod`, `/lyt-search`, `/lyt-primer-context`, `/lyt-mesh-explore`, `/lyt-sync`, `/lyt-alias`) wrap the corresponding CLI verbs directly. Pairs with [`@younndai/lyt-vault`](https://www.npmjs.com/package/@younndai/lyt-vault), which ships the four default patterns the skills resolve against.
|
|
30
30
|
|
|
31
31
|
## Install
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
npm install -g @younndai/lyt@alpha # the meta package bundles lyt-skills
|
|
35
|
-
lyt skills install # links the
|
|
35
|
+
lyt skills install # links the 16 SKILL.md files into your harness(es)
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
Tri-runtime: the installer detects Claude Code, Codex, and generic agent runtimes, and installs per-runtime (symlink by default, `--copy` for regular directories).
|
|
39
39
|
|
|
40
|
-
## The
|
|
40
|
+
## The 16 skills
|
|
41
41
|
|
|
42
42
|
| Skill | Wraps | Use it when |
|
|
43
43
|
| --------------------- | -------------------------------------------------- | ------------------------------------------------------------ |
|
|
@@ -46,6 +46,7 @@ Tri-runtime: the installer detects Claude Code, Codex, and generic agent runtime
|
|
|
46
46
|
| `/lyt-search` | `lyt search` (tiered cascade) | Ranked search across the whole pod, a mesh, or a vault. |
|
|
47
47
|
| `/lyt-pod` | `lyt mesh list` + `lyt vault list` | Enumerating every mesh + vault on the machine. |
|
|
48
48
|
| `/lyt-mesh-explore` | `lyt mesh info` | Drilling into one mesh's members and metadata. |
|
|
49
|
+
| `/lyt-alias` | `lyt alias` set/`--list`/`--remove` | Managing pod-local vault aliases (name → rid). |
|
|
49
50
|
| `/lyt-primer-context` | `lyt primer` + `lyt vault info` | Priming an agent with vault/mesh/pod context. |
|
|
50
51
|
| `/lyt-sync` | gated git pull/commit/push | Syncing a vault with its remote under the writable gate. |
|
|
51
52
|
| `/lyt-plan` | work-management + plan | Drafting a multi-phase plan before implementation. |
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@younndai/lyt-skills",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Lyt harness skills —
|
|
3
|
+
"version": "0.9.6",
|
|
4
|
+
"description": "Lyt harness skills — 16 skills (/lyt-plan, /lyt-progress, /lyt-result, /lyt-retro, /lyt-insight, /lyt-handoff, /lyt-decision, /lyt-pattern, /lyt-capture, /lyt-recall, /lyt-pod, /lyt-mesh-explore, /lyt-primer-context, /lyt-search, /lyt-sync, /lyt-alias) symlinked tri-runtime into ~/.claude/skills/, ~/.codex/skills/, ~/.agents/skills/. Composed into the `lyt skills install` and `lyt skills list` meta-CLI verbs.",
|
|
5
5
|
"homepage": "https://linkyourthink.com",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"prepublishOnly": "node ../../scripts/check-no-vendored-deps.mjs --root ../.. && node ../../scripts/public-release/scan-tarball.mjs lyt-skills"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@younndai/lyt-vault": "^0.9.
|
|
52
|
+
"@younndai/lyt-vault": "^0.9.6",
|
|
53
53
|
"commander": "^12.1.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lyt-alias
|
|
3
|
+
description: >
|
|
4
|
+
Manage pod-local vault aliases — bind a short handler-chosen name to a vault (alias → rid; survives rename + move), list the bindings, re-point one, or remove one. Trigger when the user runs /lyt-alias, or says "alias this vault as X", "give <vault> a short name", "what aliases do I have", "list my aliases", "rename my alias", "re-point alias X", "remove alias X", "drop the alias for X". Wraps `lyt alias <name> <target>` / `lyt alias --list` / `lyt alias --remove <name>` (all `--json`). Aliases are pod-local: synced across your own pod's machines, never to subscribers. Read-only on the target — works on a subscribed/read-only vault. Pairs with /lyt-pod and /lyt-search (which resolve `@alias` addresses).
|
|
5
|
+
visibility: public
|
|
6
|
+
lyt-version: 0.9.5
|
|
7
|
+
capabilities: [read, write]
|
|
8
|
+
runtimes: [claude, codex, agents]
|
|
9
|
+
requires_writable_vault: false
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# /lyt-alias
|
|
13
|
+
|
|
14
|
+
Manage **pod-local aliases** — a short, handler-chosen name that resolves to a vault. An alias binds a name to the vault's **`rid` (its UUIDv7 identity)**, not to its `{mesh}/{vault}` display name, so the alias keeps working after the vault is renamed or moved between meshes. Aliases are a convenience layer over the one addressing chokepoint every `lyt` verb resolves through (`{mesh}/{vault}` → bare leaf → alias → origin coordinate).
|
|
15
|
+
|
|
16
|
+
This skill is pure prose around three existing CLI forms of one verb — it adds no new command and changes no `lyt-vault` code:
|
|
17
|
+
|
|
18
|
+
- `lyt alias <name> <target>` — **set / re-point** (bind, or rebind, `name` → the vault `target` resolves to)
|
|
19
|
+
- `lyt alias --list` (or bare `lyt alias`) — **list** every pod-local alias
|
|
20
|
+
- `lyt alias --remove <name>` — **remove** an alias
|
|
21
|
+
|
|
22
|
+
All three accept `--json` for a machine-readable emission. The CLI does the resolution and validation; this skill resolves the user's intent into the right form, runs it (preferring `--json`), and formats the result for the handler.
|
|
23
|
+
|
|
24
|
+
**Pod-local, never federated.** Aliases live in your local registry and sync across **your own pod's** machines — they are filtered out of the publish surface, so a subscriber never sees them. They are per-pod, individual naming. (Mechanically each set/remove appends a convergent `@ALIAS` record to this writer's own append-only shard, HLC-stamped, so re-point and remove converge correctly across your machines — but that is invisible at the skill surface.)
|
|
25
|
+
|
|
26
|
+
## When to invoke
|
|
27
|
+
|
|
28
|
+
When the user runs `/lyt-alias [...]`, or says something like:
|
|
29
|
+
|
|
30
|
+
- "alias `<vault>` as `<name>`" / "give `<mesh>/<vault>` the short name `<name>`" — _set_
|
|
31
|
+
- "what aliases do I have" / "list my aliases" / "show my pod-local names" — _list_
|
|
32
|
+
- "re-point `<name>` to `<other-vault>`" / "make `<name>` point at `<vault>` instead" — _re-point (same as set)_
|
|
33
|
+
- "remove the alias `<name>`" / "drop my `<name>` alias" / "unbind `<name>`" — _remove_
|
|
34
|
+
|
|
35
|
+
If the user wants to browse what vaults exist (to pick a target), prefer `/lyt-pod`. If they want to search content, prefer `/lyt-search`. This skill only manages the name→vault bindings.
|
|
36
|
+
|
|
37
|
+
## Phase 1 — Classify the intent
|
|
38
|
+
|
|
39
|
+
Pick the form from the user's wording:
|
|
40
|
+
|
|
41
|
+
1. **Set / re-point** — a `name` AND a `target` are present ("alias `ro` to `company/company-ro`"). Re-pointing is the same verb: running `lyt alias <name> <newtarget>` again supersedes the prior binding (the fold is a name-keyed register — no separate "rename" verb, no need to remove first).
|
|
42
|
+
2. **List** — no name given, or the user asks to see bindings.
|
|
43
|
+
3. **Remove** — the user wants a binding gone.
|
|
44
|
+
|
|
45
|
+
If the user names a target ambiguously, resolve it the way the CLI will (see Phase 2) rather than guessing.
|
|
46
|
+
|
|
47
|
+
## Phase 2 — Validate the inputs you control
|
|
48
|
+
|
|
49
|
+
The CLI enforces these and will error cleanly, but check first so you can ask instead of emitting a failed command:
|
|
50
|
+
|
|
51
|
+
- **Alias `name`** must be non-empty, contain **no `/`** (slash is reserved for `{mesh}/{vault}`), **no whitespace**, and **must not start with `@`**. The `@` is the chat-surface sigil — an address like `@ro` resolves to the alias `ro`; aliases are stored **raw** (sigil-free), so a leading `@` is rejected at the write boundary. If the user says "alias it as `@ro`", store `ro` and explain `@ro` is how they'll _reference_ it.
|
|
52
|
+
- **`target`** (for set) may be a `{mesh}/{vault}` qualified address, a **bare leaf** (unique vault name across meshes), or **another alias**. It is resolved through the addressing chokepoint; if it resolves to nothing the CLI raises `alias-target-not-found` (exit 2). Surface that to the user with `lyt vault list` as the next step — don't retry blindly.
|
|
53
|
+
|
|
54
|
+
## Phase 3 — Run the verb
|
|
55
|
+
|
|
56
|
+
Prefer `--json` so you parse a typed result rather than scraping prose.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# set / re-point
|
|
60
|
+
lyt alias <name> <target> --json # → { alias, vaultRidHex, targetDisplayName }
|
|
61
|
+
|
|
62
|
+
# list
|
|
63
|
+
lyt alias --list --json # → { aliases: [{ alias, vaultRidHex, targetDisplayName }] }
|
|
64
|
+
|
|
65
|
+
# remove
|
|
66
|
+
lyt alias --remove <name> --json # → { removed: <bool>, alias }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Phase 4 — Present the result
|
|
70
|
+
|
|
71
|
+
- **Set / re-point:** confirm the binding, e.g. _"Aliased `ro` → `company/company-ro` (`vault:0a1b…`). Reference it anywhere as `@ro` or `ro`."_ If it was a re-point, say what it now points at.
|
|
72
|
+
- **List:** render one line per alias — `name → targetDisplayName (vault:<ridHex>)`. If `targetDisplayName` is **`(dangling — target removed)`**, flag it: the target vault is gone but the binding lingers — offer `lyt alias --remove <name>`. If there are none, say so and show the set form.
|
|
73
|
+
- **Remove:** confirm removal. If `removed` is `false` (no such alias), tell the user plainly — don't claim success.
|
|
74
|
+
|
|
75
|
+
## Notes on lifecycle
|
|
76
|
+
|
|
77
|
+
- **Aliases self-clean on vault teardown.** When a vault is removed via `lyt vault delete` / `lyt vault forget`, every pod-local alias pointing at it is **warned about and dropped** as part of that flow — you don't need to pre-remove aliases before deleting a vault. (`lyt vault disconnect` does _not_ drop aliases; it only flips a status flag.)
|
|
78
|
+
- **Re-point and remove converge across your pod's machines** by HLC-LWW — the newest set/remove wins per name. After a cross-machine change, a reconstitution (`lyt reindex` / the next sync-driven cache rebuild) refreshes the derived cache; the ledger is the source of truth.
|
|
79
|
+
|
|
80
|
+
## Rules
|
|
81
|
+
|
|
82
|
+
- **Never invent a target.** If the user's target doesn't resolve, surface the CLI's `alias-target-not-found` error and point them at `lyt vault list` — do not silently pick a different vault.
|
|
83
|
+
- **Strip the `@` sigil before storing.** Store `ro`, never `@ro`. Explain the `@` is for referencing.
|
|
84
|
+
- **Don't gate on vault writability.** Aliases are your own pod-local registry; you can alias a read-only or subscribed vault. `requires_writable_vault` is false by design.
|
|
85
|
+
- **Prefer `--json`** and report the typed fields; don't paraphrase a binding you didn't read back.
|
|
86
|
+
- **Removal/re-point is not destructive to the vault** — it only changes a local name binding. No handler-confirmation gate is required for alias set/list/remove (unlike `vault delete`/`forget`).
|
|
87
|
+
|
|
88
|
+
## Companion skills
|
|
89
|
+
|
|
90
|
+
- `/lyt-pod` — enumerate the vaults you might alias (and pick a target).
|
|
91
|
+
- `/lyt-search` — query across the pod; resolves `@alias` addresses.
|
|
92
|
+
- `/lyt-sync` — propagate alias changes across your pod's machines.
|
|
@@ -64,7 +64,7 @@ Per yai.lyt v1 frontmatter contract (arc §3), every captured Figment carries 8
|
|
|
64
64
|
| `mesh-visibility` | default `local` | one of `local` / `parent` / `public` — ask only if user signals a non-default visibility |
|
|
65
65
|
| `weight` | default `3` | int 1–5 importance signal — ask only if user signals a non-default weight |
|
|
66
66
|
|
|
67
|
-
**Do NOT author-fill `links-out-of-vault`.** That field is reserved for the lyt scanner
|
|
67
|
+
**Do NOT author-fill `links-out-of-vault`.** That field is reserved for the lyt scanner; it is intentionally absent at capture-write time. The contract is "scanner-filled, not author-filled."
|
|
68
68
|
|
|
69
69
|
The `meta:` blob is a free-form escape hatch (`{}` by default) — fill it only when the content carries a field the 8-field contract does not cover.
|
|
70
70
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lyt-mesh-explore
|
|
3
3
|
description: >
|
|
4
|
-
Drill into a single Lyt mesh — surface mesh metadata
|
|
4
|
+
Drill into a single Lyt mesh — surface mesh metadata and member home vaults for one named mesh. Trigger when the user runs /lyt-mesh-explore <mesh>, or says "show me the X mesh", "what's in mesh X", "drill into X mesh", "explore the X mesh", "give me X mesh details", or similar phrasing on mesh-scoped browsing. Wraps `lyt mesh info <mesh> [--remote] [--json]` — local mode reads the mesh's `.lyt/mesh.yon` SoT; `--remote` peeks at the remote mesh.yon via gh api without cloning. Read-only; pairs with /lyt-pod (pod-level enumeration across all meshes) for breadth and /lyt-search (tiered query) for content.
|
|
5
5
|
visibility: public
|
|
6
6
|
lyt-version: 0.8.0
|
|
7
7
|
capabilities: [read]
|
|
@@ -11,12 +11,14 @@ requires_writable_vault: false
|
|
|
11
11
|
|
|
12
12
|
# /lyt-mesh-explore
|
|
13
13
|
|
|
14
|
-
Render a handler-facing overview of a single Lyt **mesh** — its metadata
|
|
14
|
+
Render a handler-facing overview of a single Lyt **mesh** — its metadata and its home vaults — by wrapping one primary CLI verb (plus an upstream `lyt mesh list --json` for mesh-name resolution per Phase 1):
|
|
15
15
|
|
|
16
|
-
- `lyt mesh info <mesh> [--remote] [--json]
|
|
16
|
+
- `lyt mesh info <mesh> [--remote] [--json]`. The canonical mesh-info verb. Local mode reads the registered mesh's main-vault `.lyt/mesh.yon` source of truth; `--remote` peeks at the published mesh.yon via `gh api repos/<owner>/<mesh-main>/contents/.lyt/mesh.yon` without cloning the repo.
|
|
17
17
|
|
|
18
18
|
The skill is pure prose around existing CLI verbs — no new CLI verb, no new helper, no lyt-vault change. The CLI does the parsing (mesh.yon → typed `MeshInfoResult`); the skill resolves the user's intent (mesh name + local-or-remote), invokes the verb with `--json`, and formats the deterministic emission into a handler-facing mesh summary.
|
|
19
19
|
|
|
20
|
+
> **Note:** `publicMeta`, `updateCadences`, and `defaultVaultUpdateCadence` were removed from `MeshInfoResult`. The JSON schema and rendering template below reflect the current post-deletion shape.
|
|
21
|
+
|
|
20
22
|
User-facing language uses **"mesh"** throughout per the LYT vocabulary convention — "pod" is reserved for the user's _full_ set of meshes (which is `/lyt-pod`'s scope); "mesh" is the individual group of vaults sharing a GitHub push target.
|
|
21
23
|
|
|
22
24
|
## When to invoke
|
|
@@ -42,12 +44,12 @@ The CLI verb takes one required positional `<mesh>` (the mesh name). Pick by the
|
|
|
42
44
|
|
|
43
45
|
**Resolve the candidate against `lyt mesh list --json` before passing it.** Don't guess — when the user names a mesh:
|
|
44
46
|
|
|
45
|
-
1. Run `lyt mesh list --json` first (canonical mesh-enumeration verb
|
|
47
|
+
1. Run `lyt mesh list --json` first (the canonical mesh-enumeration verb). The output's `meshes[].name` field is the source of truth for registered mesh names.
|
|
46
48
|
2. Match the user's term to the listed names (exact, then case-insensitive, then prefix).
|
|
47
|
-
3. **Reject any resolved name that begins with `-` or `--`** before passing it to the positional `<mesh>` argument — closes the flag-injection surface the same way lyt-sync, lyt-search, and lyt-pod close theirs (
|
|
49
|
+
3. **Reject any resolved name that begins with `-` or `--`** before passing it to the positional `<mesh>` argument — closes the flag-injection surface the same way lyt-sync, lyt-search, and lyt-pod close theirs (the gh-flag-injection defense family). Mesh names are user-controlled at `lyt mesh init` time; a mesh literally named `--evil` would otherwise smuggle a flag-shaped token into the verb's argv.
|
|
48
50
|
4. If no match (or the only match is `--`-leading), tell the user the available mesh names from `lyt mesh list --json` and stop — do not invent a name.
|
|
49
51
|
|
|
50
|
-
**Decide `--remote` from explicit user signal only.** Pass `--remote` ONLY when the user explicitly says "without cloning" / "from GitHub" / "peek at the published mesh.yon" / "remote mesh info". The default is LOCAL invocation (no `--remote`) — it reads the locally-registered mesh's `.lyt/mesh.yon` SoT, which is faster, offline-safe, and authoritative for meshes the user owns. `--remote` requires the mesh to be registered locally with a `push_target` (the verb resolves the remote owner from the registry; it does NOT take a `--owner` override
|
|
52
|
+
**Decide `--remote` from explicit user signal only.** Pass `--remote` ONLY when the user explicitly says "without cloning" / "from GitHub" / "peek at the published mesh.yon" / "remote mesh info". The default is LOCAL invocation (no `--remote`) — it reads the locally-registered mesh's `.lyt/mesh.yon` SoT, which is faster, offline-safe, and authoritative for meshes the user owns. `--remote` requires the mesh to be registered locally with a `push_target` (the verb resolves the remote owner from the registry; it does NOT take a `--owner` override).
|
|
51
53
|
|
|
52
54
|
## Phase 2 — Invoke `lyt mesh info`
|
|
53
55
|
|
|
@@ -70,7 +72,7 @@ Key rules:
|
|
|
70
72
|
- `--json` is **mandatory** for this skill. The deterministic JSON emission is the contract the skill parses below; human-readable output is not.
|
|
71
73
|
- `--remote` is a boolean flag; pass it (or omit) per the Phase 1 decision. Never pass `--remote=true` or `--remote=<anything>` — the flag is bare.
|
|
72
74
|
|
|
73
|
-
The CLI emits
|
|
75
|
+
The CLI emits stable, deterministically key-ordered JSON on stdout (exit 0 on success). The emitted shape (the `MeshInfoResult` interface):
|
|
74
76
|
|
|
75
77
|
```json
|
|
76
78
|
{
|
|
@@ -82,33 +84,8 @@ The CLI emits Lock 0.3 stable-key-ordered JSON on stdout (exit 0 on success). Th
|
|
|
82
84
|
"pushTarget": "<gh-target>" | null,
|
|
83
85
|
"pushKind": "handle" | "org" | null,
|
|
84
86
|
"mainVaultRid": "vault:<uuid-dashed>",
|
|
85
|
-
"createdAt": "<iso>",
|
|
86
|
-
"defaultVaultUpdateCadence": "<cadence-string>" | null
|
|
87
|
-
},
|
|
88
|
-
"publicMeta": {
|
|
89
|
-
"description": "<string>",
|
|
90
|
-
"topics": "<comma-separated>",
|
|
91
|
-
"maintainerContact": "<string>",
|
|
92
|
-
"maintainerHandle": "<string>",
|
|
93
|
-
"licenseOverride": "<spdx-id>",
|
|
94
|
-
"acceptContributions": true,
|
|
95
|
-
"contributionUrl": "<url>",
|
|
96
|
-
"homepageUrl": "<url>",
|
|
97
|
-
"chatUrl": "<url>",
|
|
98
87
|
"createdAt": "<iso>"
|
|
99
|
-
}
|
|
100
|
-
"updateCadences": [
|
|
101
|
-
{
|
|
102
|
-
"vaultRid": "vault:<uuid-dashed>",
|
|
103
|
-
"vaultRidHex": "<hex>",
|
|
104
|
-
"cadenceType": "cron" | "interval" | "on-demand",
|
|
105
|
-
"cron": "<expr>",
|
|
106
|
-
"intervalSeconds": <number>,
|
|
107
|
-
"timezone": "<tz>",
|
|
108
|
-
"peakHours": "<expr>",
|
|
109
|
-
"onDemandAllowed": <boolean>
|
|
110
|
-
}
|
|
111
|
-
],
|
|
88
|
+
},
|
|
112
89
|
"homeVaults": [
|
|
113
90
|
{
|
|
114
91
|
"vaultRid": "vault:<uuid-dashed>",
|
|
@@ -119,13 +96,11 @@ The CLI emits Lock 0.3 stable-key-ordered JSON on stdout (exit 0 on success). Th
|
|
|
119
96
|
}
|
|
120
97
|
```
|
|
121
98
|
|
|
122
|
-
Within `publicMeta` and `updateCadences[]`, every field except `description` (in publicMeta) and `vaultRid` / `vaultRidHex` / `cadenceType` (in updateCadences[]) is omitted from the emission when undefined — they are conditional object-literal spreads at flow-emission time. Treat missing keys as "field not set on this mesh", not "field is null".
|
|
123
|
-
|
|
124
99
|
Failure modes (CLI emits to stderr; exits non-zero):
|
|
125
100
|
|
|
126
101
|
- **Mesh not registered locally** (`MeshInfoNotFoundError`, exit 2) → `{ "error": "mesh-info-not-found", "mesh_name": "<name>", "message": "..." }`. Surface the message verbatim and suggest `lyt mesh list --json` to see registered meshes.
|
|
127
102
|
- **--remote requested, gh unavailable** (`MeshInfoRemoteGhUnavailableError`, exit 4) → `{ "error": "remote-gh-unavailable", "mesh_name": "<name>", "message": "..." }`. Most common causes: the mesh has no `push_target` (initialized with `--no-push`), or `gh` is not authenticated. Surface the message and suggest dropping `--remote` to fall back to LOCAL mode.
|
|
128
|
-
- **--remote requested, remote mesh.yon missing** (`MeshInfoRemoteMeshYonMissingError`, exit 4) → `{ "error": "remote-mesh-yon-missing", "mesh_name": "<name>", "message": "..." }`. The remote repo exists but `.lyt/mesh.yon` is absent at the repo root
|
|
103
|
+
- **--remote requested, remote mesh.yon missing** (`MeshInfoRemoteMeshYonMissingError`, exit 4) → `{ "error": "remote-mesh-yon-missing", "mesh_name": "<name>", "message": "..." }`. The remote repo exists but `.lyt/mesh.yon` is absent at the repo root. Surface verbatim and suggest LOCAL mode.
|
|
129
104
|
|
|
130
105
|
## Phase 3 — Format mesh-overview for handler
|
|
131
106
|
|
|
@@ -139,43 +114,27 @@ Render the mesh summary as a markdown block. The handler-facing layout:
|
|
|
139
114
|
- push target: `<mesh.pushKind>:<mesh.pushTarget>` (omit line when pushTarget is null)
|
|
140
115
|
- main vault rid: `<mesh.mainVaultRid>`
|
|
141
116
|
- created: `<mesh.createdAt>`
|
|
142
|
-
- default cadence: `<mesh.defaultVaultUpdateCadence>` (omit line when null)
|
|
143
|
-
|
|
144
|
-
**Public description:** (omit entire block when publicMeta is null)
|
|
145
|
-
- description: <publicMeta.description>
|
|
146
|
-
- topics: <publicMeta.topics> (omit when undefined)
|
|
147
|
-
- maintainer: <publicMeta.maintainerContact> (omit when undefined)
|
|
148
|
-
- license: <publicMeta.licenseOverride> (omit when undefined)
|
|
149
|
-
- homepage: <publicMeta.homepageUrl> (omit when undefined)
|
|
150
|
-
- chat: <publicMeta.chatUrl> (omit when undefined)
|
|
151
117
|
|
|
152
118
|
**Home vaults:** (count = homeVaults.length)
|
|
153
119
|
- ★ `<main-vault-name>` (`vault:<vaultRidHex>`) — main vault, marked ★
|
|
154
120
|
- `<vault-name>` (`vault:<vaultRidHex>`)
|
|
155
121
|
- ...
|
|
156
|
-
|
|
157
|
-
**Update cadences:** (count = updateCadences.length; omit entire block when length is 0)
|
|
158
|
-
- `<vault-ridHex truncated to 12 chars>…` — <cadenceType> <detail>
|
|
159
|
-
- ...
|
|
160
122
|
```
|
|
161
123
|
|
|
162
124
|
Synthesis rules:
|
|
163
125
|
|
|
164
126
|
- **Source line.** Render `(local)` or `(remote)` next to the mesh name based on `source` — handlers seeing the rendered output should know whether they're looking at on-disk SoT or a remote peek.
|
|
165
|
-
- **Main-vault marker.** The home vault whose `vaultRid` equals `mesh.mainVaultRid` is the main vault — render it first with a `★` marker (parity with `lyt mesh list`'s human output
|
|
166
|
-
- **
|
|
167
|
-
- **Optional-field omission.** Treat absent keys in `publicMeta` + `updateCadences[]` as "field not set on this mesh"; omit those lines entirely rather than rendering `undefined` or `null` placeholders.
|
|
168
|
-
- **No edges / subscriptions sections.** `lyt mesh info` surfaces mesh metadata + publicMeta + home vaults + update cadences ONLY — it does not emit mesh-edges (`@MESH_EDGE`) or cross-mesh subscriptions (`@MESH_SUBSCRIPTION`). Those are inspected via other surfaces (`lyt mesh list` exposes per-mesh `subscribed_vaults`; mesh-edges live in `.lyt/mesh.yon` but are not surfaced by this verb). Do NOT invent edge / subscription bullets — the verb does not expose them. Mention `/lyt-pod` as the path to subscription overview if the user asks.
|
|
169
|
-
- **Empty publicMeta.** When `publicMeta === null`, the mesh was initialized without a `@MESH_PUBLIC` block. Omit the entire "Public description" section — do NOT render an empty heading.
|
|
127
|
+
- **Main-vault marker.** The home vault whose `vaultRid` equals `mesh.mainVaultRid` is the main vault — render it first with a `★` marker (parity with `lyt mesh list`'s human output). Other home vaults follow, sorted alphabetically by `vaultName`. Do not double-render the main vault.
|
|
128
|
+
- **No edges / subscriptions sections.** `lyt mesh info` surfaces mesh metadata + home vaults ONLY — it does not emit mesh-edges (`@MESH_EDGE`) or cross-mesh subscriptions. Those are inspected via other surfaces (`lyt mesh list` exposes per-mesh `subscribed_vaults`). Do NOT invent edge / subscription bullets — the verb does not expose them. Mention `/lyt-pod` as the path to subscription overview if the user asks.
|
|
170
129
|
- **Use "mesh" framing throughout.** Never write "federation" or "pod" in this skill's user-facing prose. "Mesh" is the unit of grouping; "pod" is the user's full set of meshes (different scope; that's `/lyt-pod`'s domain).
|
|
171
|
-
- **Remote-mode caveat.** When `source === "remote"`, the data is whatever the remote `.lyt/mesh.yon` currently advertises — it may be stale relative to the mesh's owner's local state if they haven't
|
|
130
|
+
- **Remote-mode caveat.** When `source === "remote"`, the data is whatever the remote `.lyt/mesh.yon` currently advertises — it may be stale relative to the mesh's owner's local state if they haven't pushed recently. Mention this when the user explicitly asked for `--remote`, so they know what they're looking at.
|
|
172
131
|
|
|
173
132
|
## Rules
|
|
174
133
|
|
|
175
134
|
- **MUST pass the mesh name as a separate argv argument**, not template-interpolated into a shell command string. Mesh names are user-controlled at init time; argv-array protects against shell-meta or flag-shaped tokens.
|
|
176
135
|
- **MUST pass `--json`** on every invocation. Human-readable output is not a contract this skill parses.
|
|
177
|
-
- **MUST resolve mesh names via `lyt mesh list --json` before passing them.** The canonical mesh-enumeration verb is `lyt mesh list
|
|
178
|
-
- **MUST reject `--`-leading resolved mesh names** before passing them to the positional `<mesh>` argument (
|
|
136
|
+
- **MUST resolve mesh names via `lyt mesh list --json` before passing them.** The canonical mesh-enumeration verb is `lyt mesh list`. Do not guess names.
|
|
137
|
+
- **MUST reject `--`-leading resolved mesh names** before passing them to the positional `<mesh>` argument (the flag-injection defense family).
|
|
179
138
|
- **MUST NOT cite `lyt mesh status`** as a verb. It does not exist. The canonical mesh-listing verb is `lyt mesh list`; the canonical single-mesh-inspection verb is `lyt mesh info` (this skill).
|
|
180
139
|
- **MUST NOT modify or write any vault file.** This is a read-only skill (`requires_writable_vault: false`). If the user wants the mesh overview persisted to a Figment, run `/lyt-capture` separately on the formatted output.
|
|
181
140
|
- **MUST NOT pass `--remote` by default.** LOCAL is the default; pass `--remote` only on explicit user signal ("without cloning", "from GitHub", "peek at the published mesh.yon", "remote").
|
package/skills/lyt-pod/SKILL.md
CHANGED
|
@@ -13,8 +13,8 @@ requires_writable_vault: false
|
|
|
13
13
|
|
|
14
14
|
Render an agent-facing overview of the user's Lyt **pod** — every mesh and every vault on this machine — by composing two CLI verbs:
|
|
15
15
|
|
|
16
|
-
1. `lyt mesh list --json`
|
|
17
|
-
2. `lyt vault list --json`
|
|
16
|
+
1. `lyt mesh list --json` — enumerates meshes the user participates in, including each mesh's main vault, home vaults, and subscribed vaults. This is the canonical mesh-enumeration verb.
|
|
17
|
+
2. `lyt vault list --json` — enumerates every registered vault on the machine, with status, path, and per-vault metadata (mesh role, parent vault, tier hint). This is the canonical vault-enumeration verb.
|
|
18
18
|
|
|
19
19
|
The skill is pure prose around two existing CLI verbs — there is no new CLI verb, no new helper, no lyt-vault change. Both verbs always run on every invocation (default = full pod overview); user signal can narrow the synthesis focus post-facto but does NOT change which verbs run.
|
|
20
20
|
|
|
@@ -35,7 +35,7 @@ When the user runs `/lyt-pod`, or says something like:
|
|
|
35
35
|
|
|
36
36
|
Invoke this skill **proactively** as the first move whenever the user asks a pod-scoped enumeration question or seems to want a survey of what's installed. Don't bypass it and start grep'ing the filesystem — the registry is the source of truth.
|
|
37
37
|
|
|
38
|
-
If the user wants to drill into a single mesh (vault list + edges for one mesh), prefer `/lyt-mesh-explore
|
|
38
|
+
If the user wants to drill into a single mesh (vault list + edges for one mesh), prefer `/lyt-mesh-explore`. If the user wants per-vault writable status or agent priming, use `/lyt-primer-context`.
|
|
39
39
|
|
|
40
40
|
## Phase 1 — Determine pod-scope intent
|
|
41
41
|
|
|
@@ -43,7 +43,7 @@ The default is **full pod overview** — both verbs run, every mesh and vault re
|
|
|
43
43
|
|
|
44
44
|
- **Default — full pod overview.** Use when the user says "my pod", "show me everything", "list all vaults", "what meshes do I have", or omits scope entirely. Run both verbs (Phase 2 + Phase 3) and synthesize a complete pod summary in Phase 4.
|
|
45
45
|
- **Narrow framing on a single mesh.** Use when the user says "focus on the `<name>` mesh", "just show me the `<name>` mesh's vaults", "what's in the `<name>` mesh". **Still run BOTH `lyt mesh list --json` and `lyt vault list --json`** — the CLI verbs do not support `--mesh` filtering on `lyt vault list`. Apply the user's narrow framing at **synthesis time** (Phase 4) by filtering the rendered output. Do NOT invent a CLI flag.
|
|
46
|
-
- **Tombstoned-vault inclusion.** Default = hide soft-tombstoned rollup aggregates (matches CLI default
|
|
46
|
+
- **Tombstoned-vault inclusion.** Default = hide soft-tombstoned rollup aggregates (matches the CLI default). Pass `--include-tombstones` ONLY when the user explicitly says "show tombstoned vaults too", "include deleted vaults", "show buried vaults". Hard-tombstoned vaults (`status='tombstoned'`) are included in the default `lyt vault list` output already; `--no-tombstones` filters them out (do NOT pass by default — they are part of the pod's recent history).
|
|
47
47
|
|
|
48
48
|
The skill never invents mesh or vault names. If the user names one and the post-Phase-2/3 synthesis can't match it, surface the available names and stop — do not guess.
|
|
49
49
|
|
|
@@ -59,7 +59,7 @@ lyt mesh list --json
|
|
|
59
59
|
spawnSync("lyt", ["mesh", "list", "--json"]);
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
The CLI emits
|
|
62
|
+
The CLI emits stable, deterministically key-ordered JSON on stdout (exit 0 on success). The emitted shape:
|
|
63
63
|
|
|
64
64
|
```json
|
|
65
65
|
{
|
|
@@ -105,7 +105,7 @@ spawnSync("lyt", ["vault", "list", "--json"]);
|
|
|
105
105
|
spawnSync("lyt", ["vault", "list", "--json", "--include-tombstones"]);
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
The CLI emits
|
|
108
|
+
The CLI emits stable, deterministically key-ordered JSON on stdout:
|
|
109
109
|
|
|
110
110
|
```json
|
|
111
111
|
{
|
|
@@ -136,7 +136,7 @@ The CLI emits Lock 0.3 stable-key-ordered JSON on stdout (per `packages/lyt-vaul
|
|
|
136
136
|
}
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
**Field-type note
|
|
139
|
+
**Field-type note.** The four byte-typed fields (`rid`, `memscopeRid`, `parentVault`, `homeMeshRid`) are `Uint8Array` instances at the source and pass through `JSON.stringify(result, null, 2)` raw. `JSON.stringify` serializes a `Uint8Array` as a **byte-indexed object** (`{"0": 123, "1": 45, ..., "15": 254}`), NOT a hex string. **Always match on the `*Hex` companion fields** (`ridHex`, `memscopeRidHex`, `parentVaultHex`, `homeMeshRidHex`) — those are guaranteed-string and stable. Treat the raw byte-fields as opaque implementation detail.
|
|
140
140
|
|
|
141
141
|
The vault-list output is the source of truth for **per-vault mesh membership** — match each vault's `homeMeshRidHex` (string) against each mesh's `rid_hex` (string) from Phase 2 to group vaults under their mesh in Phase 4. A vault with `homeMeshRidHex === null` is an **orphan** (registered but not adopted into any mesh — see Phase 4's orphan section).
|
|
142
142
|
|
|
@@ -174,7 +174,7 @@ Render the pod summary as a markdown block. The handler-facing layout:
|
|
|
174
174
|
Synthesis rules:
|
|
175
175
|
|
|
176
176
|
- **Summary line.** `N meshes` = `meshes.length` from Phase 2. `M vaults` = `vaults.length` from Phase 3 (filter out `status='tombstoned'` unless the user explicitly asked for tombstoned inclusion). The `(P pushable · S subscriber · O orphan)` breakdown counts each vault **once** by primary role, with precedence **home > subscriber > orphan** (a vault appearing in BOTH a `home_vaults` array AND any `subscribed_vaults` array is counted as **home**, not subscriber): a vault is **pushable** if it appears in any mesh's `home_vaults` AND that mesh has a non-null `push_target`; **subscriber** if it appears ONLY in `subscribed_vaults` arrays across all meshes (never as a home vault); **orphan** if its `homeMeshRidHex === null` (no mesh role at all).
|
|
177
|
-
- **Mesh grouping.** Sort meshes by name (alphabetical) for stable rendering. Within each mesh: main vault first (marked `★`
|
|
177
|
+
- **Mesh grouping.** Sort meshes by name (alphabetical) for stable rendering. Within each mesh: main vault first (marked `★`), then other home vaults sorted alphabetically (exclude the main-vault entry from this alphabetic list — it already rendered above with `★`; `home_vaults` includes the main vault per Phase 2 shape, so an LLM iterating the array verbatim would otherwise double-render the main vault), then subscribed vaults grouped at the end with a "subscribed (cross-mesh)" hint.
|
|
178
178
|
- **Push-target hint.** Surface `push target: <push_kind>:<push_target>` next to the main vault when `push_target !== null`. Skip the hint when null (mesh is local-only).
|
|
179
179
|
- **Orphan section.** Always include the heading even when empty (rendering "(none)" under it) — handlers parsing the output can rely on the section's presence. Each orphan vault gets a one-line heal suggestion: `lyt repair --target <orphan-vault-name> --apply --mesh <mesh>` (the canonical heal — binds a registered vault to a known mesh). A vault that is _registered-but-mesh-unlinked_ (the adopt mesh-link drift) heals via `lyt repair --apply` with **no args** (`lyt doctor` flags it). `lyt mesh adopt` remains for gh **cluster-discovery** of un-registered repos — not for re-linking an already-registered vault.
|
|
180
180
|
- **User narrow framing.** If the user signaled a single mesh in Phase 1, render only that mesh's section under `## Meshes` plus the orphan section. Surface a one-line "(showing 1 of N meshes — re-invoke /lyt-pod for full overview)" hint.
|
|
@@ -189,8 +189,8 @@ Synthesis rules:
|
|
|
189
189
|
- **MUST run BOTH verbs on every invocation.** The default is full pod overview; even when the user signals a narrow mesh framing, the vault list is needed to compute the orphan section and the summary-line counts. Do not skip one verb to "save time" — synthesis quality drops.
|
|
190
190
|
- **MUST use "pod" framing in user-facing output.** Never write "federation" in handler-facing prose; "federation" is internal data-layer vocabulary only.
|
|
191
191
|
- **MUST surface the orphan-vault section** even when empty (render "(none)" under the heading) so handlers can rely on its presence.
|
|
192
|
-
- **MUST cite `lyt mesh list` as the canonical mesh-enumeration verb.**
|
|
193
|
-
- **MUST cite `lyt vault info <name>` with a positional argument only.** The verb accepts a positional `<name
|
|
192
|
+
- **MUST cite `lyt mesh list` as the canonical mesh-enumeration verb.** The canonical verb is `lyt mesh list`. Do not invent a different mesh-enumeration verb.
|
|
193
|
+
- **MUST cite `lyt vault info <name>` with a positional argument only.** The verb accepts a positional `<name>`; the only flag is `--json`. The pod skill does not call `vault info` at all (per-vault writable status is `/lyt-primer-context`'s job — pulling it here would duplicate that surface).
|
|
194
194
|
- **MUST NOT pass `--include-tombstones` by default.** Pass only on explicit user signal ("show tombstoned vaults", "include deleted vaults", "show buried vaults"). Default = hide soft-tombstoned rollup aggregates per CLI default.
|
|
195
195
|
- **MUST NOT pass `--no-tombstones` by default.** Hard-tombstoned vaults (`status='tombstoned'`) are part of the pod's recent history; rendering them with a `[tombstoned]` status marker is the correct default. Pass `--no-tombstones` only on explicit user signal ("hide tombstones", "skip buried vaults").
|
|
196
196
|
- **MUST NOT modify or write any file.** This is a read-only skill (`requires_writable_vault: false`). If the user wants the pod overview persisted to a Figment, run `/lyt-capture` separately on the formatted output.
|
|
@@ -199,7 +199,7 @@ Synthesis rules:
|
|
|
199
199
|
|
|
200
200
|
## Companion skills
|
|
201
201
|
|
|
202
|
-
- **/lyt-mesh-explore** — drill into a single mesh (vault list + edges + subscriptions). Pair after `/lyt-pod` when the user picks one mesh to investigate
|
|
202
|
+
- **/lyt-mesh-explore** — drill into a single mesh (vault list + edges + subscriptions). Pair after `/lyt-pod` when the user picks one mesh to investigate.
|
|
203
203
|
- **/lyt-primer-context** — prime an agent with Lyt-scoped context (top keywords, active arcs, writable status). Pair after `/lyt-pod` when the user wants the agent to start working in a specific vault — use `--scope vault --target <name>` per the chosen vault.
|
|
204
204
|
- **/lyt-search** — query across the pod with the tiered-cascade engine. Pair after `/lyt-pod` when the user wants to look up specific content rather than survey what exists.
|
|
205
205
|
- **/lyt-sync** — pull/commit/push a vault. Run before `/lyt-pod` if the user has unpushed local edits and wants the registry to reflect them (registry rows update on vault init/adopt; `/lyt-sync` doesn't change the pod shape but does freshen `lastVerifiedAt`).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lyt-primer-context
|
|
3
3
|
description: >
|
|
4
|
-
Prime an agent with Lyt-scoped context — for a vault, a mesh, or the whole pod — by composing `lyt primer` (top keywords + active arcs + recent activity + top lanes) and `lyt vault info --json` (writable status for vault-scope). Trigger when the user runs /lyt-primer-context, or says "prime me for X", "give me context on this vault", "what's been happening in my pod lately", "what arcs are active in mesh Y", "give the agent context before X", or similar phrasing on a scope they want surfaced for agent priming. Wraps `lyt primer`
|
|
4
|
+
Prime an agent with Lyt-scoped context — for a vault, a mesh, or the whole pod — by composing `lyt primer` (top keywords + active arcs + recent activity + top lanes) and `lyt vault info --json` (writable status for vault-scope). Trigger when the user runs /lyt-primer-context, or says "prime me for X", "give me context on this vault", "what's been happening in my pod lately", "what arcs are active in mesh Y", "give the agent context before X", or similar phrasing on a scope they want surfaced for agent priming. Wraps `lyt primer` + `lyt vault info --json` (6-reason writable contract) — composes both into an agent-facing summary. Read-only; pairs with /lyt-search (query-driven recall) and /lyt-capture (write).
|
|
5
5
|
visibility: public
|
|
6
6
|
lyt-version: 0.6.0
|
|
7
7
|
capabilities: [read]
|
|
@@ -13,10 +13,10 @@ requires_writable_vault: false
|
|
|
13
13
|
|
|
14
14
|
Prime an agent with Lyt-scoped context for a **vault**, a **mesh**, or the whole **pod** by composing two CLI verbs:
|
|
15
15
|
|
|
16
|
-
1. `lyt primer --scope <vault|mesh|federation> [--target <name>] --json --dry-run`
|
|
17
|
-
2. `lyt vault info <name> --json` (
|
|
16
|
+
1. `lyt primer --scope <vault|mesh|federation> [--target <name>] --json --dry-run` — aggregates top keywords, active arcs, recent activity, and top lanes across the scope into a stable, deterministically key-ordered JSON payload (including the full primer markdown body).
|
|
17
|
+
2. `lyt vault info <name> --json` (6-reason writable contract) — only for vault-scope priming, fetches `writable` + `writableDetermination` so the skill can surface a capability hint to the agent ("you can /lyt-capture here" vs reason-specific guidance).
|
|
18
18
|
|
|
19
|
-
The skill is pure prose around two existing CLI verbs — there is no new CLI verb, no new helper, no lyt-vault change. The skill READS; it does not write (except the CLI's atomic primer-file write on non-dry-run, which is opt-in per Phase 2
|
|
19
|
+
The skill is pure prose around two existing CLI verbs — there is no new CLI verb, no new helper, no lyt-vault change. The skill READS; it does not write (except the CLI's atomic primer-file write on non-dry-run, which is opt-in per Phase 2's default).
|
|
20
20
|
|
|
21
21
|
## When to invoke
|
|
22
22
|
|
|
@@ -42,9 +42,9 @@ The `lyt primer` verb requires `--scope` and rejects ambiguity. Pick by the user
|
|
|
42
42
|
|
|
43
43
|
**Resolve names before passing them.** Don't guess at mesh/vault names — when the user names one:
|
|
44
44
|
|
|
45
|
-
1. Run `lyt vault list --json` (vaults) or `lyt mesh list --json` (meshes) first. `lyt mesh list` is the canonical mesh-enumeration verb
|
|
45
|
+
1. Run `lyt vault list --json` (vaults) or `lyt mesh list --json` (meshes) first. `lyt mesh list` is the canonical mesh-enumeration verb; both verbs emit stable, deterministically key-ordered JSON on `--json`.
|
|
46
46
|
2. Match the user's term to the listed names (exact, then case-insensitive, then prefix).
|
|
47
|
-
3. **Reject any resolved name that begins with `-` or `--`** before passing it to `--target <name>` — closes the flag-injection surface the same way lyt-sync (Phase 1) and lyt-search (Phase 1) do (
|
|
47
|
+
3. **Reject any resolved name that begins with `-` or `--`** before passing it to `--target <name>` — closes the flag-injection surface the same way lyt-sync (Phase 1) and lyt-search (Phase 1) do (the gh-flag-injection defense family). Vault and mesh names are user-controlled at vault-init / mesh-create time; a vault literally named `--evil` would otherwise smuggle a flag-shaped token into the verb's argv.
|
|
48
48
|
4. If no match (or the only match is `--`-leading), tell the user the available names and stop — do not invent a name.
|
|
49
49
|
|
|
50
50
|
The `--scope federation` invocation MUST NOT pass `--target` — the CLI ignores it for federation scope but it's noise; only pass `--target` for vault/mesh scopes.
|
|
@@ -68,12 +68,12 @@ Key rules:
|
|
|
68
68
|
- `--scope` is **mandatory** (CLI rejects with `error: "invalid-scope"`, exit 1, if missing or unrecognised). The skill always passes one; default to `federation` when no user signal.
|
|
69
69
|
- `--target <name>` is **required** for `--scope vault` and `--scope mesh`; **omitted** for `--scope federation`. CLI rejects missing target with `error: "missing-target"`, exit 1.
|
|
70
70
|
- `--json` is **mandatory** for this skill. Without it, the CLI prints human-readable output that the skill can't reliably parse.
|
|
71
|
-
- `--dry-run` is the **default for this skill
|
|
71
|
+
- `--dry-run` is the **default for this skill**. The CLI's non-dry-run mode atomically writes the primer markdown to `<vault>/.lyt/primers/{scope}-primer.md`; the skill READS the result for agent priming and does not need that persisted file as a side-effect of every invocation. Pass `--dry-run` unless the user explicitly asks to regenerate the on-disk primer ("refresh the primer file", "regenerate the on-disk primer" — then omit `--dry-run`).
|
|
72
72
|
- `--top-keywords <n>`, `--top-arcs <n>`, `--provenance-days <n>` are advanced flags. Apply only when the user explicitly signals a cap ("top 50 keywords", "last 30 days of activity"); otherwise rely on CLI defaults (20 / 10 / 7).
|
|
73
73
|
|
|
74
74
|
## Phase 3 — Parse the JSON output
|
|
75
75
|
|
|
76
|
-
The CLI emits
|
|
76
|
+
The CLI emits stable, deterministically key-ordered JSON on stdout (exit 0 on success). The emitted shape:
|
|
77
77
|
|
|
78
78
|
```json
|
|
79
79
|
{
|
|
@@ -124,7 +124,7 @@ Failure modes (CLI emits to stderr; exit non-zero):
|
|
|
124
124
|
|
|
125
125
|
## Phase 4 — Fetch writable status (vault-scope ONLY)
|
|
126
126
|
|
|
127
|
-
**Skip this phase for `--scope mesh` and `--scope federation`** — those scopes span multiple vaults and there's no single writable status to surface
|
|
127
|
+
**Skip this phase for `--scope mesh` and `--scope federation`** — those scopes span multiple vaults and there's no single writable status to surface. For mesh/federation, jump to Phase 5 and present the primer summary alone. The agent can re-invoke `/lyt-primer-context` per-vault with `--scope vault --target <name>` if it needs write-action guidance for a specific vault.
|
|
128
128
|
|
|
129
129
|
For `--scope vault --target <name>`, invoke `lyt vault info <name> --json` via Bash (argv-array form):
|
|
130
130
|
|
|
@@ -139,7 +139,7 @@ lyt vault info <name> --json
|
|
|
139
139
|
spawnSync("lyt", ["vault", "info", vaultName, "--json"]);
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
-
Parse the `vault.writable` + `vault.writableDetermination` fields per the
|
|
142
|
+
Parse the `vault.writable` + `vault.writableDetermination` fields per the read-only-awareness contract. The verdict is tri-state (`true | false | "unknown"`); the determination is one of **6 reasons** the skill must branch on explicitly in Phase 5.
|
|
143
143
|
|
|
144
144
|
## Phase 5 — Synthesize agent-facing context
|
|
145
145
|
|
|
@@ -171,7 +171,7 @@ Render the agent-priming output as a markdown block. Layout:
|
|
|
171
171
|
|
|
172
172
|
### Capability hint — 6-reason writable contract (vault-scope only)
|
|
173
173
|
|
|
174
|
-
For vault-scope invocations, surface a reason-specific capability hint based on `writable` + `writableDetermination`. The actual reason strings emitted by `vault info --json`
|
|
174
|
+
For vault-scope invocations, surface a reason-specific capability hint based on `writable` + `writableDetermination`. The actual reason strings emitted by `vault info --json` are listed in the **emitted name** column. The **semantic name** column gives the human-readable synonym; the SKILL.md handler-facing prose uses the semantic name, but the comparison MUST be against the emitted name.
|
|
175
175
|
|
|
176
176
|
| Emitted name (writableDetermination) | Semantic name | writable | Phase 5 capability hint |
|
|
177
177
|
| ------------------------------------ | --------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -182,20 +182,20 @@ For vault-scope invocations, surface a reason-specific capability hint based on
|
|
|
182
182
|
| `no-remote` | (no-remote) | `"unknown"` | ⚠ Writable status unknown — vault has no git remote configured. Configure with `gh repo create` or `git remote add origin <url>`. |
|
|
183
183
|
| `orphan-vault` | (orphan) | `"unknown"` | ⚠ Writable status unknown — vault has no mesh role (orphan). Heal: `lyt repair --apply` (fixes the adopt mesh-link drift, no args needed); a truly un-adopted vault: `lyt repair --target <vault> --apply --mesh <mesh>`. `lyt doctor` diagnoses. |
|
|
184
184
|
|
|
185
|
-
**Note on emitted vs semantic names.** The
|
|
185
|
+
**Note on emitted vs semantic names.** The semantic names `home-pushable-true` / `home-not-pushable-false` are documentation aliases for the first two emitted strings `gh-viewerCanPush-true` / `gh-viewerCanPush-false`, kept so future renames of the underlying enum don't silently break the skill prose. The 4 other reason strings (`subscriber-default-false`, `gh-unavailable`, `no-remote`, `orphan-vault`) are identical in both surfaces. **Comparison code MUST use the emitted name; handler-facing prose uses either.**
|
|
186
186
|
|
|
187
187
|
## Rules
|
|
188
188
|
|
|
189
189
|
- **MUST pass `--scope`, `--target` (if applicable), and `--json` as separate argv arguments**, not template-interpolated into a shell command string. Mesh/vault names CAN contain shell metacharacters (backticks, `$()`, `;`, `&&`) — those MUST be conveyed as one argv element per name.
|
|
190
190
|
- **MUST pass `--json`** on every invocation. Human-readable output is not a contract this skill parses.
|
|
191
|
-
- **MUST pass `--dry-run`** UNLESS the user explicitly asks to regenerate the on-disk primer file
|
|
191
|
+
- **MUST pass `--dry-run`** UNLESS the user explicitly asks to regenerate the on-disk primer file. Otherwise every priming call pollutes `<vault>/.lyt/primers/`.
|
|
192
192
|
- **MUST resolve mesh/vault names via `lyt vault list --json` or `lyt mesh list --json` before passing `--target`.** Do not guess names.
|
|
193
|
-
- **MUST reject `--`-leading names** from `lyt vault list --json` / `lyt mesh list --json` results before passing them to `--target` (
|
|
193
|
+
- **MUST reject `--`-leading names** from `lyt vault list --json` / `lyt mesh list --json` results before passing them to `--target` (the gh-flag-injection defense family).
|
|
194
194
|
- **MUST branch on all 6 writable reasons in Phase 5 (vault-scope).** Each has a distinct capability hint; collapsing them into a generic "can't write" message loses semantic signal the agent needs to recover.
|
|
195
195
|
- **MUST NOT call `lyt primer` without `--scope`.** The CLI rejects with `error: "invalid-scope"`, exit 1.
|
|
196
196
|
- **MUST NOT call `lyt primer` with `--scope vault` or `--scope mesh` without `--target`.** The CLI rejects with `error: "missing-target"`, exit 1.
|
|
197
|
-
- **MUST NOT call `lyt vault info` for `--scope mesh` or `--scope federation`.** Phase 4 is skipped for those scopes
|
|
198
|
-
- **MUST NOT modify or write any file.** This is a read-only skill (`requires_writable_vault: false`). The CLI's atomic primer-file write on non-dry-run is opt-in
|
|
197
|
+
- **MUST NOT call `lyt vault info` for `--scope mesh` or `--scope federation`.** Phase 4 is skipped for those scopes; the primer summary alone is the output.
|
|
198
|
+
- **MUST NOT modify or write any file.** This is a read-only skill (`requires_writable_vault: false`). The CLI's atomic primer-file write on non-dry-run is opt-in only when the user explicitly asks; the skill itself never writes.
|
|
199
199
|
- **MUST NOT compose shell command strings.** Argv-array always (parity with lyt-sync + lyt-search).
|
|
200
200
|
- **MUST NOT silently degrade `writable === "unknown"` to a "writable" hint.** Surface the reason-specific guidance.
|
|
201
201
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lyt-search
|
|
3
3
|
description: >
|
|
4
|
-
Search a Lyt pod (or a single mesh or vault) using the tiered-cascade engine — Tier 0 arcs (0.95) → Tier 1 lanes (0.90) → Tier 2 FTS5 (0.70) → Tier 3 edges (0.50) — with confidence ranking. Trigger when the user runs /lyt-search <query>, or says "search my pod for X", "find anything about X across my vaults", "search across all meshes for X", "what's in my pod about X", or similar phrasing on a query wider than a single vault. Wraps the `lyt search` CLI verb
|
|
4
|
+
Search a Lyt pod (or a single mesh or vault) using the tiered-cascade engine — Tier 0 arcs (0.95) → Tier 1 lanes (0.90) → Tier 2 FTS5 (0.70) → Tier 3 edges (0.50) — with confidence ranking. Trigger when the user runs /lyt-search <query>, or says "search my pod for X", "find anything about X across my vaults", "search across all meshes for X", "what's in my pod about X", or similar phrasing on a query wider than a single vault. Wraps the `lyt search` CLI verb — federation scope by default; --vault / --mesh narrow scope; --limit caps results. Returns ranked Figments with vault, mesh, snippet, and confidence. Companion to lyt-recall (single-vault keyword grep) for narrower local searches.
|
|
5
5
|
visibility: public
|
|
6
6
|
lyt-version: 0.5.0
|
|
7
7
|
capabilities: [search]
|
|
@@ -11,7 +11,7 @@ requires_writable_vault: false
|
|
|
11
11
|
|
|
12
12
|
# /lyt-search
|
|
13
13
|
|
|
14
|
-
Search a Lyt **pod** (default: every vault across every mesh) using the tiered-cascade engine. The skill is a thin LLM-driven wrapper around the `lyt search` CLI verb
|
|
14
|
+
Search a Lyt **pod** (default: every vault across every mesh) using the tiered-cascade engine. The skill is a thin LLM-driven wrapper around the `lyt search` CLI verb; the heavy lifting — arc/lane/FTS5/edge cascade, confidence scoring, deterministic JSON emission — already lives in the CLI. The skill resolves the user's intent (query string + scope), invokes the verb with `--json`, parses the stable, deterministically key-ordered output, and presents ranked results to the handler.
|
|
15
15
|
|
|
16
16
|
## When to invoke
|
|
17
17
|
|
|
@@ -39,7 +39,7 @@ The CLI verb supports three mutually-exclusive scope flags; the default (no flag
|
|
|
39
39
|
|
|
40
40
|
1. Run `lyt vault list --json` (vaults) or `lyt mesh list --json` (meshes) first.
|
|
41
41
|
2. Match the user's term to the listed names (exact, then case-insensitive, then prefix).
|
|
42
|
-
3. **Reject any resolved name that begins with `-` or `--`** before passing it to `--vault <name>` / `--mesh <name>` — closes the flag-injection surface the same way lyt-sync does at its Phase 1 (
|
|
42
|
+
3. **Reject any resolved name that begins with `-` or `--`** before passing it to `--vault <name>` / `--mesh <name>` — closes the flag-injection surface the same way lyt-sync does at its Phase 1 (the gh-flag-injection defense family). Vault names are user-controlled at vault-init time; a vault literally named `--evil` would otherwise smuggle a flag-shaped token into the verb's argv.
|
|
43
43
|
4. If no match (or the only match is `--`-leading), tell the user the available names and stop — do not invent a name.
|
|
44
44
|
|
|
45
45
|
Do **NOT** pass `--all` as an explicit flag — it's an alias for the default scope. Bare `lyt search` already searches federation; adding `--all` is redundant.
|
|
@@ -63,13 +63,13 @@ The Bash-tool variant: pass the argv array form to the tool's `args` field if th
|
|
|
63
63
|
Key rules:
|
|
64
64
|
|
|
65
65
|
- The first positional argument is the query — a single string. Multi-word queries are implicit AND. Quote the query so the shell treats it as one argv element.
|
|
66
|
-
- `--json` is **mandatory** for this skill. It yields the deterministic
|
|
66
|
+
- `--json` is **mandatory** for this skill. It yields the deterministic, stable key-ordered output the skill parses below; without it, the CLI prints human-readable lines that the skill can't reliably parse.
|
|
67
67
|
- `--limit <n>` defaults to 20 (CLI default), capped at 1000. Apply caller's `--limit` only when the user explicitly signals a cap ("top 5 results", "first 10"); otherwise rely on the CLI default.
|
|
68
68
|
- Never combine `--vault` AND `--mesh` — the CLI rejects it with `error: "conflicting-scope-flags"` and exits 1.
|
|
69
69
|
|
|
70
70
|
## Phase 3 — Parse the JSON output
|
|
71
71
|
|
|
72
|
-
The CLI emits
|
|
72
|
+
The CLI emits stable, deterministically key-ordered JSON on stdout (exit 0 on success). Expected shape:
|
|
73
73
|
|
|
74
74
|
```json
|
|
75
75
|
{
|
package/skills/lyt-sync/SKILL.md
CHANGED
|
@@ -11,7 +11,7 @@ requires_writable_vault: false
|
|
|
11
11
|
|
|
12
12
|
# /lyt-sync
|
|
13
13
|
|
|
14
|
-
Sync a Lyt vault — pull, detect-and-commit local changes, push (gated on the
|
|
14
|
+
Sync a Lyt vault — pull, detect-and-commit local changes, push (gated on the writable verdict). The skill always runs; the push step gates internally on the 6-reason `writable` contract from `lyt vault info --json`, so even read-only / subscriber / orphan / no-remote vaults pull cleanly without touching origin.
|
|
15
15
|
|
|
16
16
|
## When to invoke
|
|
17
17
|
|
|
@@ -40,7 +40,7 @@ If the resolved path **does not exist or is not a Lyt vault** (no `.lyt/vault.yo
|
|
|
40
40
|
|
|
41
41
|
> The target vault `<path>` doesn't exist (or isn't a Lyt vault — no `.lyt/vault.yon`). Use `lyt vault init <name>`, or pass `--vault <existing-path>`.
|
|
42
42
|
|
|
43
|
-
**Path-shape safety check.** Before invoking `git -C <vault-path>`, reject any resolved path that begins with `-` or `--` (defensive against a crafted `--vault` argument, `$LYT_ACTIVE_VAULT` env value, or any other resolver-input that could smuggle a flag-shaped token into the git positional). The `.lyt/vault.yon` existence check above already filters most invalid paths; this `--`-leading rejection closes the remaining flag-injection surface (
|
|
43
|
+
**Path-shape safety check.** Before invoking `git -C <vault-path>`, reject any resolved path that begins with `-` or `--` (defensive against a crafted `--vault` argument, `$LYT_ACTIVE_VAULT` env value, or any other resolver-input that could smuggle a flag-shaped token into the git positional). The `.lyt/vault.yon` existence check above already filters most invalid paths; this `--`-leading rejection closes the remaining flag-injection surface (the gh-flag-injection defense family). Resolved paths MUST be absolute and MUST start with a drive letter (Windows) or `/` (POSIX) before they enter any `git` argv.
|
|
44
44
|
|
|
45
45
|
## Phase 2 — Pull with rebase
|
|
46
46
|
|
|
@@ -52,7 +52,7 @@ git -C <vault-path> pull --rebase
|
|
|
52
52
|
|
|
53
53
|
(On Windows, `git -C <path>` works with quoted paths, but the lyt-vault precedent — `flows/clone.ts`, `flows/repair.ts`, `util/git-history.ts` — uses `spawnSync` with `cwd: <vault-path>` so the path doesn't need to be embedded in argv. Skill prose recommends the `cwd` shape for cross-platform stability.)
|
|
54
54
|
|
|
55
|
-
**On rebase conflict** (`git pull --rebase` exits non-zero with conflict markers):
|
|
55
|
+
**On rebase conflict** (`git pull --rebase` exits non-zero with conflict markers): do NOT attempt auto-resolution. Surface a structured result to the handler and halt:
|
|
56
56
|
|
|
57
57
|
```json
|
|
58
58
|
{
|
|
@@ -72,7 +72,7 @@ Run `git -C <vault-path> status --porcelain`. If the output is empty, skip to Ph
|
|
|
72
72
|
1. Parse the porcelain output into a `GitDiffSummary`-shaped object (`{staged: string[], modified: string[]}`). Porcelain v1 (the default) emits one line per change with a 2-character prefix: column 1 is the index/staged status, column 2 is the working-tree status. Treat any line whose column-1 char is not space or `?` as **staged** (e.g. `A `, `M `, `MM`, `D `); treat any line whose column-2 char is not space (or whose prefix is `??`) as **modified**. Strip the 3-character prefix to recover the file path. Files that appear staged AND modified land in both arrays — that's tolerated; the helper sorts and de-orders naturally and the resulting message just lists the file once or twice depending on its multi-state shape.
|
|
73
73
|
2. Decide on a commit message. The skill exposes one **caller-options**-style choice:
|
|
74
74
|
|
|
75
|
-
- `options.commit-message: "auto"` _(default
|
|
75
|
+
- `options.commit-message: "auto"` _(default)_ — call the `inferCommitMessage(diff)` heuristic to summarise the diff:
|
|
76
76
|
- 0 files → `"no changes"` _(defensive; unreached because porcelain was non-empty)_
|
|
77
77
|
- 1 file (non-mesh.yon) → `"sync: <filename>"`
|
|
78
78
|
- 1 file (mesh.yon, at any depth) → `"sync: mesh.yon update"`
|
|
@@ -80,7 +80,7 @@ Run `git -C <vault-path> status --porcelain`. If the output is empty, skip to Ph
|
|
|
80
80
|
- > 4 files → `"sync: N files (<first 3>, +M more)"`
|
|
81
81
|
- `options.commit-message: "prompt-handler"` — pause and ask the handler for a one-line message; do not invent one.
|
|
82
82
|
|
|
83
|
-
The heuristic
|
|
83
|
+
The heuristic is `inferCommitMessage`; the skill prose reproduces the rules above so an agent can run them inline without importing.
|
|
84
84
|
|
|
85
85
|
3. Stage and commit. **Pass the message via argv, NOT through shell interpolation.** The shell-syntax pseudocode below is for documentation only; agents executing this skill MUST translate it to an argv-safe `spawnSync` / `execFileSync` call so a filename containing shell metacharacters (backticks, `$()`, `;`, `"`) inside the inferred message can't escape into command execution. Concretely:
|
|
86
86
|
|
|
@@ -94,15 +94,15 @@ spawnSync("git", ["-C", vaultPath, "add", "-A"]);
|
|
|
94
94
|
spawnSync("git", ["-C", vaultPath, "commit", "-m", message]);
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
The matching precedent
|
|
97
|
+
The matching precedent is `execFileSync("git", ["clone", opts.url, target])` — the same argv-array shape used everywhere the lyt-vault flow layer shells to git.
|
|
98
98
|
|
|
99
99
|
Do **not** add a `Co-Authored-By` trailer (per the project's `CLAUDE.md` commit conventions). Do **not** add an `@STAMP` block — that is a `.yon`-write concern handled by lyt-runner, not the sync skill.
|
|
100
100
|
|
|
101
101
|
## Phase 4 — Push (gated on the 6-reason writable verdict)
|
|
102
102
|
|
|
103
|
-
Invoke `lyt vault info <vault-name> --json` and parse the `vault.writable` and `vault.writableDetermination` fields per the
|
|
103
|
+
Invoke `lyt vault info <vault-name> --json` and parse the `vault.writable` and `vault.writableDetermination` fields per the read-only-awareness contract. The verdict is tri-state (`true | false | "unknown"`); the determination is one of **6 reasons** the skill must branch on explicitly.
|
|
104
104
|
|
|
105
|
-
The actual reason strings emitted by `vault info --json`
|
|
105
|
+
The actual reason strings emitted by `vault info --json` are listed in the **emitted name** column. The **semantic name** column gives the human-readable synonym; the SKILL.md surface uses the semantic name in handler-facing prose, but the comparison MUST be against the emitted name.
|
|
106
106
|
|
|
107
107
|
| Emitted name (writableDetermination) | Semantic name | writable | Phase 4 behavior |
|
|
108
108
|
| ------------------------------------ | --------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -113,7 +113,7 @@ The actual reason strings emitted by `vault info --json` (per writability.ts at
|
|
|
113
113
|
| `no-remote` | (no-remote) | `"unknown"` | Skip push. Report: _"Skipped push: vault has no git remote configured. Configure a remote with `gh repo create` or `git remote add origin <url>`."_ |
|
|
114
114
|
| `orphan-vault` | (orphan) | `"unknown"` | Skip push. Report: _"Skipped push: vault has no mesh role (orphan). Adopt into a mesh with `lyt mesh adopt --cluster <name>`."_ |
|
|
115
115
|
|
|
116
|
-
**Note on emitted vs semantic names.** The
|
|
116
|
+
**Note on emitted vs semantic names.** The semantic names `home-pushable-true` and `home-not-pushable-false` are documentation aliases for the actual emitted strings `gh-viewerCanPush-true` and `gh-viewerCanPush-false`, kept so future renames of the underlying enum don't silently break the skill prose. The 4 other reason strings (`subscriber-default-false`, `gh-unavailable`, `no-remote`, `orphan-vault`) are identical in both surfaces.
|
|
117
117
|
|
|
118
118
|
Final handler-facing result shape:
|
|
119
119
|
|
|
@@ -131,7 +131,7 @@ Final handler-facing result shape:
|
|
|
131
131
|
|
|
132
132
|
## Rules
|
|
133
133
|
|
|
134
|
-
- **MUST NOT auto-resolve a rebase conflict.** Halt with the structured-output shape in Phase 2 and let the handler resolve manually.
|
|
134
|
+
- **MUST NOT auto-resolve a rebase conflict.** Halt with the structured-output shape in Phase 2 and let the handler resolve manually.
|
|
135
135
|
- **MUST gate push on `vault.writable` / `vault.writableDetermination`.** Never `git push` unless `writableDetermination === "gh-viewerCanPush-true"` (equivalently, `writable === true`). The other 5 reasons all skip push.
|
|
136
136
|
- **MUST branch on all 6 reasons.** Each has a distinct handler-facing message; collapsing them into a generic "can't push" message loses semantic signal the handler needs to recover.
|
|
137
137
|
- **MUST NOT add a `Co-Authored-By` trailer** to the auto-commit. Per the project's `CLAUDE.md` commit conventions, unless the user explicitly requests one.
|