@younndai/lyt-skills 0.9.0
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/LICENSE +200 -0
- package/NOTICE +23 -0
- package/README.md +124 -0
- package/dist/commands/skills-install.d.ts +3 -0
- package/dist/commands/skills-install.d.ts.map +1 -0
- package/dist/commands/skills-install.js +89 -0
- package/dist/commands/skills-install.js.map +1 -0
- package/dist/commands/skills-list.d.ts +3 -0
- package/dist/commands/skills-list.d.ts.map +1 -0
- package/dist/commands/skills-list.js +79 -0
- package/dist/commands/skills-list.js.map +1 -0
- package/dist/commands/skills.d.ts +3 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +26 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/list.d.ts +19 -0
- package/dist/list.d.ts.map +1 -0
- package/dist/list.js +65 -0
- package/dist/list.js.map +1 -0
- package/dist/symlink.d.ts +41 -0
- package/dist/symlink.d.ts.map +1 -0
- package/dist/symlink.js +233 -0
- package/dist/symlink.js.map +1 -0
- package/package.json +72 -0
- package/skills/lyt-capture/SKILL.md +137 -0
- package/skills/lyt-decision/SKILL.md +52 -0
- package/skills/lyt-handoff/SKILL.md +52 -0
- package/skills/lyt-insight/SKILL.md +55 -0
- package/skills/lyt-mesh-explore/SKILL.md +190 -0
- package/skills/lyt-pattern/SKILL.md +71 -0
- package/skills/lyt-plan/SKILL.md +60 -0
- package/skills/lyt-pod/SKILL.md +205 -0
- package/skills/lyt-primer-context/SKILL.md +206 -0
- package/skills/lyt-progress/SKILL.md +48 -0
- package/skills/lyt-recall/SKILL.md +98 -0
- package/skills/lyt-result/SKILL.md +49 -0
- package/skills/lyt-retro/SKILL.md +54 -0
- package/skills/lyt-search/SKILL.md +144 -0
- package/skills/lyt-sync/SKILL.md +145 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lyt-retro
|
|
3
|
+
description: >
|
|
4
|
+
Write a deliberate retrospective on a session, sprint, or completed plan. Trigger when the user runs /lyt-retro, or says "retro this", "what did we learn", "lessons from this sprint", "post-mortem". Wraps `lyt pattern run work-management retro`. Writes to <vault>/Projects/<project>/work/<date>-retro-<slug>.md.
|
|
5
|
+
visibility: public
|
|
6
|
+
lyt-version: 0.2.0
|
|
7
|
+
capabilities: [write]
|
|
8
|
+
runtimes: [claude, codex, agents]
|
|
9
|
+
requires_writable_vault: true
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# /lyt-retro
|
|
13
|
+
|
|
14
|
+
Capture a deliberate retrospective. What worked. What didn't. What we'd change next time. Distinct from `/lyt-result` (which records WHAT shipped); a retro records WHY it went the way it did.
|
|
15
|
+
|
|
16
|
+
## When to invoke
|
|
17
|
+
|
|
18
|
+
- `/lyt-retro` slash trigger
|
|
19
|
+
- "let's retro this"
|
|
20
|
+
- end of a sprint, arc, project, or contentious decision
|
|
21
|
+
- after a meaningful handoff (often required by the handoff-execute protocol)
|
|
22
|
+
|
|
23
|
+
## Phase 1 — Resolve target
|
|
24
|
+
|
|
25
|
+
Same chain as `/lyt-plan`. Slug usually matches the artifact being retro'd (e.g., `phase-7-session-2-bulk-init-patterns-skills-retro`).
|
|
26
|
+
|
|
27
|
+
If retro'ing a specific session/sprint/handoff, set `retro-of:` frontmatter to its wikilink.
|
|
28
|
+
|
|
29
|
+
## Phase 2 — Run the verb
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
lyt pattern run work-management retro --vault <vault> --project <project> --slug <slug>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Phase 3 — Fill the body
|
|
36
|
+
|
|
37
|
+
Sections to fill:
|
|
38
|
+
|
|
39
|
+
- **What worked** — bullets, specific
|
|
40
|
+
- **What didn't** — bullets, specific (no euphemisms)
|
|
41
|
+
- **What we'd change next time** — bullets, actionable
|
|
42
|
+
- **Lessons (durable enough to keep)** — if any rise to insight-level, promote
|
|
43
|
+
|
|
44
|
+
## Promotion
|
|
45
|
+
|
|
46
|
+
A retro's durable lessons promote either to:
|
|
47
|
+
|
|
48
|
+
- `<date>-insight-<slug>.md` in the same `work/` folder (project-specific)
|
|
49
|
+
- `Nuggets/<subject>/<date>-nugget-<slug>.md` at vault root (project-agnostic)
|
|
50
|
+
|
|
51
|
+
## Companion skills
|
|
52
|
+
|
|
53
|
+
- `/lyt-result` — what shipped (this retro reflects on)
|
|
54
|
+
- `/lyt-insight` — durable lessons promoted from this retro
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lyt-search
|
|
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 (v1.D.3b) — 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
|
+
visibility: public
|
|
6
|
+
lyt-version: 0.5.0
|
|
7
|
+
capabilities: [search]
|
|
8
|
+
runtimes: [claude, codex, agents]
|
|
9
|
+
requires_writable_vault: false
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# /lyt-search
|
|
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 (shipped v1.D.3b); 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 Lock 0.3 stable-key-ordered output, and presents ranked results to the handler.
|
|
15
|
+
|
|
16
|
+
## When to invoke
|
|
17
|
+
|
|
18
|
+
When the user runs `/lyt-search <query>`, or says something like:
|
|
19
|
+
|
|
20
|
+
- "search my pod for <topic>"
|
|
21
|
+
- "search across all my vaults for <topic>"
|
|
22
|
+
- "find anything about <topic>"
|
|
23
|
+
- "what's in my pod about <topic>"
|
|
24
|
+
- "what did I write about <topic>" — _if the user's pod has multiple vaults_; for a single-vault keyword grep, prefer `/lyt-recall`
|
|
25
|
+
- "search the `<mesh-name>` mesh for <topic>"
|
|
26
|
+
- "search vault `<vault-name>` for <topic>"
|
|
27
|
+
|
|
28
|
+
If the user's question depends on prior captured knowledge across multiple vaults, invoke this skill proactively — don't fabricate; check the pod first.
|
|
29
|
+
|
|
30
|
+
## Phase 1 — Determine scope from user signal
|
|
31
|
+
|
|
32
|
+
The CLI verb supports three mutually-exclusive scope flags; the default (no flag) is federation. Pick by the user's wording:
|
|
33
|
+
|
|
34
|
+
- **Default — federation (entire pod, every vault across every mesh).** No scope flag. Use when the user says "my pod", "all my vaults", "everywhere", "across all meshes", or omits scope entirely. Invocation: `lyt search "<query>" --json`.
|
|
35
|
+
- **Single mesh.** Use `--mesh <name>` when the user says "in mesh `<name>`", "across the `<name>` mesh", "in my `<name>` mesh". Invocation: `lyt search "<query>" --mesh <name> --json`.
|
|
36
|
+
- **Single vault.** Use `--vault <name>` when the user says "in vault `<name>`", "in my `<name>` vault". Invocation: `lyt search "<query>" --vault <name> --json`.
|
|
37
|
+
|
|
38
|
+
**Resolve names before passing them.** Don't guess at mesh/vault names — when the user names one:
|
|
39
|
+
|
|
40
|
+
1. Run `lyt vault list --json` (vaults) or `lyt mesh list --json` (meshes) first.
|
|
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 (family: G.2 CR-1 gh-flag-injection). 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
|
+
4. If no match (or the only match is `--`-leading), tell the user the available names and stop — do not invent a name.
|
|
44
|
+
|
|
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.
|
|
46
|
+
|
|
47
|
+
## Phase 2 — Invoke the CLI verb
|
|
48
|
+
|
|
49
|
+
Run the verb via the Bash tool (or your runtime's shell equivalent). **Pass the query as a single quoted argv argument; never shell-compose the command.** This matters because the user's query CAN contain shell metacharacters (backticks, `$()`, `;`, `&&`) — those MUST be conveyed as one argv element, not template-interpolated into a shell string.
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
# Shell-syntax (DOCUMENTATION ONLY — do NOT compose this as a string):
|
|
53
|
+
lyt search "<user-query>" --json [--vault <name> | --mesh <name>] [--limit <n>]
|
|
54
|
+
|
|
55
|
+
# Actual exec shape (argv array; cross-platform-safe):
|
|
56
|
+
spawnSync("lyt", ["search", userQuery, "--json", "--vault", vaultName]);
|
|
57
|
+
# or with no scope flag (federation default):
|
|
58
|
+
spawnSync("lyt", ["search", userQuery, "--json"]);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The Bash-tool variant: pass the argv array form to the tool's `args` field if the runtime exposes one; if the runtime only accepts a single shell-string, the LLM is responsible for shell-quoting `userQuery` correctly (this is the failure mode argv mode prevents). Precedent: lyt-sync's Phase 3 commits via `spawnSync("git", [..., "-m", message])` for the same reason.
|
|
62
|
+
|
|
63
|
+
Key rules:
|
|
64
|
+
|
|
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 Lock 0.3 stable-key-ordered output the skill parses below; without it, the CLI prints human-readable lines that the skill can't reliably parse.
|
|
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
|
+
- Never combine `--vault` AND `--mesh` — the CLI rejects it with `error: "conflicting-scope-flags"` and exits 1.
|
|
69
|
+
|
|
70
|
+
## Phase 3 — Parse the JSON output
|
|
71
|
+
|
|
72
|
+
The CLI emits Lock 0.3 stable-key-ordered JSON on stdout (exit 0 on success). Expected shape:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"query": "<the query>",
|
|
77
|
+
"scope": "federation" | "mesh" | "vault",
|
|
78
|
+
"scopeTarget": "<name>" | null,
|
|
79
|
+
"limit": 20,
|
|
80
|
+
"results": [
|
|
81
|
+
{
|
|
82
|
+
"confidence": 0.95,
|
|
83
|
+
"tier": 0,
|
|
84
|
+
"vault_name": "<vault>",
|
|
85
|
+
"mesh_name": "<mesh>",
|
|
86
|
+
"figment_path": "<relative/path.md>",
|
|
87
|
+
"snippet": "<≤80-char snippet>"
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
"trace": {
|
|
91
|
+
"tiersRun": [0, 1, 2, 3],
|
|
92
|
+
"perTierHitCount": { "0": 1, "1": 3, "2": 12, "3": 4 },
|
|
93
|
+
"vaultsSearched": ["<vault1>", "<vault2>"]
|
|
94
|
+
},
|
|
95
|
+
"durationMs": 47
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Failure modes (CLI emits to stderr; exit non-zero):
|
|
100
|
+
|
|
101
|
+
- **Empty query** (exit 1) → `{ "error": "empty-query", "message": "..." }`. Surface the message verbatim and ask the user to refine.
|
|
102
|
+
- **Conflicting scope flags** (exit 1) → `{ "error": "conflicting-scope-flags", "flags": [...], "message": "..." }`. Skill-level bug if hit — Phase 1 should have prevented it; surface and stop.
|
|
103
|
+
- **Invalid limit** (exit 1) → `{ "error": "invalid-limit", "value": "<bad>", "message": "..." }`. Re-invoke with the CLI default.
|
|
104
|
+
- **Cascade error** (exit 2) → `{ "error": "cascade-error", "message": "..." }`. Surface verbatim; suggest re-running with narrower scope.
|
|
105
|
+
|
|
106
|
+
## Phase 4 — Format results for the handler
|
|
107
|
+
|
|
108
|
+
Group by mesh, then by vault within mesh. Order results within each vault by descending confidence (the CLI emits them ranked already). One line per result.
|
|
109
|
+
|
|
110
|
+
The CLI emits each result with TWO ranking fields — `confidence` (the float: 0.95/0.90/0.70/0.50) and `tier` (the int: 0/1/2/3, where 0=arcs, 1=lanes, 2=FTS5, 3=edges). The two are isomorphic (one tier-int maps to one canonical confidence), so the handler-facing display shows `confidence` only (it's the more readable signal). The `tier` field stays in the JSON for callers that need to filter by tier source; the skill does not surface it in the one-line format.
|
|
111
|
+
|
|
112
|
+
Format:
|
|
113
|
+
|
|
114
|
+
> **Found N matches for `"<query>"` (scope=federation, <durationMs>ms · tiers: <tier counts>):**
|
|
115
|
+
>
|
|
116
|
+
> **Mesh: `<mesh1>`**
|
|
117
|
+
>
|
|
118
|
+
> - `[0.95]` `<vault1>/notes/2026-05-24-q4-planning.md` — _the auth rewrite is a P0 for Q4..._
|
|
119
|
+
> - `[0.70]` `<vault1>/notes/2026-05-23-auth-decisions.md` — _moving to OAuth, deprecating session tokens..._
|
|
120
|
+
>
|
|
121
|
+
> **Mesh: `<mesh2>`**
|
|
122
|
+
>
|
|
123
|
+
> - `[0.50]` `<vault2>/notes/2026-05-22-stand-up.md` — _...session tokens flagged by legal..._
|
|
124
|
+
|
|
125
|
+
Show each result as `[<confidence>] <vault>/<figment_path> — <snippet>`. Truncate snippets to ~80 characters with an ellipsis. The top-of-output tier-hit summary uses the CLI's `trace.perTierHitCount` map (`{0:N, 1:M, 2:K, 3:L}`) so the handler sees confidence distribution at a glance.
|
|
126
|
+
|
|
127
|
+
On **empty results**: surface _"No matches for `"<query>"` across <scope>."_ and offer scope-widening hints (`--mesh` → federation; `--vault` → `--mesh`).
|
|
128
|
+
|
|
129
|
+
## Rules
|
|
130
|
+
|
|
131
|
+
- **MUST pass the user's query as a single quoted argv argument**, not template-interpolated into a shell command string. Filenames or queries containing shell metacharacters (`` ` ``, `$(...)`, `;`, `&&`) inside the query MUST be safely conveyed as argv.
|
|
132
|
+
- **MUST pass `--json`** on every invocation. Human-readable output is not a contract this skill parses.
|
|
133
|
+
- **MUST resolve mesh/vault names via `lyt vault list --json` or `lyt mesh list --json` before passing `--vault` or `--mesh`.** Do not guess names.
|
|
134
|
+
- **MUST NOT pass `--all` explicitly.** Federation is the default; `--all` is a redundant alias. Use no scope flag instead.
|
|
135
|
+
- **MUST NOT combine `--vault` and `--mesh`.** The CLI exits 1 with `conflicting-scope-flags`.
|
|
136
|
+
- **MUST NOT re-interpret confidence tiers.** The CLI emits them as `0.95 / 0.90 / 0.70 / 0.50` per Tier 0/1/2/3 spec. Display verbatim; do not "smooth" or "round" or invent a derived score.
|
|
137
|
+
- **MUST NOT modify or write any vault file.** This is a read-only skill (`requires_writable_vault: false`). If the user wants results persisted to a Figment, run `/lyt-capture` separately on the formatted output.
|
|
138
|
+
- **MUST NOT widen scope without user signal.** If the user said "in my work vault", do not silently fall back to federation when the named vault is missing — surface the miss and stop.
|
|
139
|
+
|
|
140
|
+
## Companion skills
|
|
141
|
+
|
|
142
|
+
- **`/lyt-recall`** — single-vault keyword grep. Use when the user has only one vault in mind and wants filesystem-level grep semantics rather than the tiered-cascade engine.
|
|
143
|
+
- **`/lyt-sync`** — pull-then-push a vault. Run before `/lyt-search` if the user has unpushed local edits and wants the FTS5 index reflect them (the cascade reads the local vault's libSQL state).
|
|
144
|
+
- **`/lyt-capture`** — write a Figment. Pair with `/lyt-search` if the user wants the recall results persisted.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lyt-sync
|
|
3
|
+
description: >
|
|
4
|
+
Sync a Lyt vault — pull from its GitHub repo, auto-commit any uncommitted local changes (with an inferred commit message or a handler-supplied one), then push back to origin gated on the 6-reason writable verdict from `vault info --json`. Trigger when the user runs /lyt-sync, or says "sync this vault", "pull and push", "sync my notes", "push my changes", or similar phrasing. Wraps `git pull --rebase`, dirty-tree detection, commit, and push under the hood. Read-only / subscriber / orphan / no-remote / gh-offline vaults pull but skip push and surface a reason-specific handler message. Pairs with /lyt-capture.
|
|
5
|
+
visibility: public
|
|
6
|
+
lyt-version: 0.4.0
|
|
7
|
+
capabilities: [read, write]
|
|
8
|
+
runtimes: [claude, codex, agents]
|
|
9
|
+
requires_writable_vault: false
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# /lyt-sync
|
|
13
|
+
|
|
14
|
+
Sync a Lyt vault — pull, detect-and-commit local changes, push (gated on the v1.G.2 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
|
+
|
|
16
|
+
## When to invoke
|
|
17
|
+
|
|
18
|
+
When the user runs `/lyt-sync`, or says something like:
|
|
19
|
+
|
|
20
|
+
- "sync this vault"
|
|
21
|
+
- "sync my notes"
|
|
22
|
+
- "pull and push"
|
|
23
|
+
- "push my changes"
|
|
24
|
+
- "sync `<vault-name>`"
|
|
25
|
+
- "/lyt-sync `<vault-name>`"
|
|
26
|
+
|
|
27
|
+
If the user says "save and sync" or "/lyt-capture then sync", run /lyt-capture first, then /lyt-sync on the destination vault.
|
|
28
|
+
|
|
29
|
+
## Phase 1 — Resolve the target vault
|
|
30
|
+
|
|
31
|
+
Follow this chain, in order, and stop at the first success (mirrors /lyt-capture Phase 1):
|
|
32
|
+
|
|
33
|
+
1. **`--vault <path>` argument** — if the user passed one in the invocation, use it as-is (resolve to absolute path if relative).
|
|
34
|
+
2. **`$LYT_ACTIVE_VAULT` environment variable** — if set, use it.
|
|
35
|
+
3. **`~/lyt/vaults/<handle>/main/`** — the default convention per the unified `{handle}/{repo}` naming (Windows: `%USERPROFILE%\lyt\vaults\<handle>\main`). Resolve `<handle>` from the pod identity (`identity.yon` / `pod.yon`); never hardcode it.
|
|
36
|
+
|
|
37
|
+
Do **not** guess from cwd. If `--vault` / env var / home convention all miss, ask the user which vault to target — fabricating a path from cwd would silently operate on the wrong tree.
|
|
38
|
+
|
|
39
|
+
If the resolved path **does not exist or is not a Lyt vault** (no `.lyt/vault.yon` inside), do **not** attempt git operations. Stop and tell the user:
|
|
40
|
+
|
|
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
|
+
|
|
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 (same family as the G.2 CR-1 gh-flag-injection close). Resolved paths MUST be absolute and MUST start with a drive letter (Windows) or `/` (POSIX) before they enter any `git` argv.
|
|
44
|
+
|
|
45
|
+
## Phase 2 — Pull with rebase
|
|
46
|
+
|
|
47
|
+
Shell out to git directly with the vault path as `cwd`:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
git -C <vault-path> pull --rebase
|
|
51
|
+
```
|
|
52
|
+
|
|
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
|
+
|
|
55
|
+
**On rebase conflict** (`git pull --rebase` exits non-zero with conflict markers): per the ratified default (2026-06-01), do NOT attempt auto-resolution. Surface a structured result to the handler and halt:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"status": "conflict",
|
|
60
|
+
"vault": "<vault-name>",
|
|
61
|
+
"conflicted_files": ["<path1>", "<path2>"],
|
|
62
|
+
"message": "git pull --rebase failed; resolve the listed conflicts manually, then re-invoke /lyt-sync."
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The handler-facing prose to surface: _"Sync halted on rebase conflict in `<vault-name>`. Resolve the conflicts in `<files>`, then run `/lyt-sync` again."_
|
|
67
|
+
|
|
68
|
+
## Phase 3 — Detect + commit local changes
|
|
69
|
+
|
|
70
|
+
Run `git -C <vault-path> status --porcelain`. If the output is empty, skip to Phase 4 with a "no local changes" note for the handler. Otherwise:
|
|
71
|
+
|
|
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
|
+
2. Decide on a commit message. The skill exposes one **caller-options**-style choice:
|
|
74
|
+
|
|
75
|
+
- `options.commit-message: "auto"` _(default — the oversight handler default per the ratified default)_ — call the `inferCommitMessage(diff)` heuristic to summarise the diff:
|
|
76
|
+
- 0 files → `"no changes"` _(defensive; unreached because porcelain was non-empty)_
|
|
77
|
+
- 1 file (non-mesh.yon) → `"sync: <filename>"`
|
|
78
|
+
- 1 file (mesh.yon, at any depth) → `"sync: mesh.yon update"`
|
|
79
|
+
- 2-4 files → `"sync: N files (<comma list>)"`
|
|
80
|
+
- > 4 files → `"sync: N files (<first 3>, +M more)"`
|
|
81
|
+
- `options.commit-message: "prompt-handler"` — pause and ask the handler for a one-line message; do not invent one.
|
|
82
|
+
|
|
83
|
+
The heuristic lives in `packages/lyt-vault/src/util/sync-helpers.ts` as `inferCommitMessage`; the skill prose reproduces the rules above so an agent can run them inline without importing.
|
|
84
|
+
|
|
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
|
+
|
|
87
|
+
```
|
|
88
|
+
# Pseudocode (DO NOT shell-interpolate):
|
|
89
|
+
git -C <vault-path> add -A
|
|
90
|
+
git -C <vault-path> commit -m "<message>"
|
|
91
|
+
|
|
92
|
+
# Actual exec shape (argv array; cross-platform-safe):
|
|
93
|
+
spawnSync("git", ["-C", vaultPath, "add", "-A"]);
|
|
94
|
+
spawnSync("git", ["-C", vaultPath, "commit", "-m", message]);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The matching precedent lives in `packages/lyt-vault/src/flows/clone.ts:87` (`execFileSync("git", ["clone", opts.url, target])`) — the same argv-array shape used everywhere the lyt-vault flow layer shells to git.
|
|
98
|
+
|
|
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
|
+
|
|
101
|
+
## Phase 4 — Push (gated on the 6-reason writable verdict)
|
|
102
|
+
|
|
103
|
+
Invoke `lyt vault info <vault-name> --json` and parse the `vault.writable` and `vault.writableDetermination` fields per the v1.G.2 read-only-awareness contract (see `packages/lyt-vault/src/flows/writability.ts:42-48`). The verdict is tri-state (`true | false | "unknown"`); the determination is one of **6 reasons** the skill must branch on explicitly.
|
|
104
|
+
|
|
105
|
+
The actual reason strings emitted by `vault info --json` (per writability.ts at HEAD `16ccdf6`) are listed in the **emitted name** column. The **semantic name** column gives the human-readable synonym some briefs use; the SKILL.md surface uses the semantic name in handler-facing prose, but the comparison MUST be against the emitted name.
|
|
106
|
+
|
|
107
|
+
| Emitted name (writableDetermination) | Semantic name | writable | Phase 4 behavior |
|
|
108
|
+
| ------------------------------------ | --------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
109
|
+
| `gh-viewerCanPush-true` | **home-pushable-true** | `true` | Push: `git -C <vault-path> push`. Report: _"Synced and pushed N commits to origin."_ |
|
|
110
|
+
| `gh-viewerCanPush-false` | **home-not-pushable-false** | `false` | Skip push. Report: _"Skipped push: you don't have push permission on `<vault.gitUrl>`. Request write access from the owner, or capture into a vault you own."_ |
|
|
111
|
+
| `subscriber-default-false` | (subscriber) | `false` | Skip push. Report: _"Skipped push: this is a subscriber vault. Subscriber vaults pull but don't push. Capture into your home vault instead."_ |
|
|
112
|
+
| `gh-unavailable` | (gh-offline) | `"unknown"` | Skip push. Report: _"Skipped push: gh CLI is unavailable (offline / rate-limited / not authenticated). Re-try when network is available."_ |
|
|
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
|
+
| `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
|
+
|
|
116
|
+
**Note on emitted vs semantic names.** The brief that authored this skill (v1.G.3 handoff) lists `home-pushable-true` and `home-not-pushable-false` as the writable-determination reason strings. The actual strings emitted by `writability.ts` are `gh-viewerCanPush-true` and `gh-viewerCanPush-false`. The semantic names are kept here as a documentation alias so future renames of the underlying enum (e.g. when the gh-probe naming hardens in v1.G.2.1) don't silently break the skill prose. The 4 unchanged reason strings (`subscriber-default-false`, `gh-unavailable`, `no-remote`, `orphan-vault`) match in both surfaces.
|
|
117
|
+
|
|
118
|
+
Final handler-facing result shape:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"status": "ok",
|
|
123
|
+
"vault": "<vault-name>",
|
|
124
|
+
"pulled": true,
|
|
125
|
+
"committed_message": "<message>" | null,
|
|
126
|
+
"pushed": true | false,
|
|
127
|
+
"skipped_push_reason": "<one of the 6 writableDetermination values>" | null,
|
|
128
|
+
"handler_message": "<reason-specific prose from the table above>"
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Rules
|
|
133
|
+
|
|
134
|
+
- **MUST NOT auto-resolve a rebase conflict.** Halt with the structured-output shape in Phase 2 and let the handler resolve manually. Per the ratified default.
|
|
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
|
+
- **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
|
+
- **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.
|
|
138
|
+
- **MUST NOT touch any vault other than the resolved target.** Sync is single-vault. A multi-vault sweep is `mesh clone-all` / a future `lyt sync --mesh` verb, not this skill.
|
|
139
|
+
- **MUST NOT modify `.lyt/vault.yon`, `.lyt/mesh.yon`, ledger YONs, or `@STAMP` blocks.** Those are runner / writer concerns; sync only commits handler-authored content as-is.
|
|
140
|
+
- **MUST NOT silently degrade `writable === "unknown"` to push.** Surface the reason to the handler.
|
|
141
|
+
|
|
142
|
+
## Companion skills
|
|
143
|
+
|
|
144
|
+
- **/lyt-capture** — write a Figment into a vault. /lyt-sync is the natural follow-up when the captured vault has push access.
|
|
145
|
+
- **/lyt-recall** — search the vault. Read-only; no sync interaction.
|