From d2610d6550b268ca7e65efefb11bbd18ecbeaa2a Mon Sep 17 00:00:00 2001 From: mant1st Date: Sat, 11 Jul 2026 19:19:31 +1000 Subject: [PATCH] feat(context-restore): show Universal Save receipt health --- context-restore/SKILL.md | 69 ++++++++++++++++++++++------ context-restore/SKILL.md.tmpl | 69 ++++++++++++++++++++++------ gstack/llms.txt | 2 +- scripts/proactive-suggestions.json | 4 +- test/context-restore-receipt.test.ts | 26 +++++++++++ 5 files changed, 137 insertions(+), 33 deletions(-) create mode 100644 test/context-restore-receipt.test.ts diff --git a/context-restore/SKILL.md b/context-restore/SKILL.md index f71fbf147..63ba32719 100644 --- a/context-restore/SKILL.md +++ b/context-restore/SKILL.md @@ -2,7 +2,7 @@ name: context-restore preamble-tier: 2 version: 1.0.0 -description: Restore working context saved earlier by /context-save. (gstack) +description: Restore working context saved earlier by /save or legacy /context-save. (gstack) allowed-tools: - Bash - Read @@ -26,7 +26,7 @@ Loads the most recent saved state (across all branches by default) so you can pick up where you left off — even across Conductor workspace handoffs. Use when asked to "resume", "restore context", "where was I", or -"pick up where I left off". Pair with /context-save. +"pick up where I left off". Pair with /save. Formerly /checkpoint resume — renamed because Claude Code treats /checkpoint as a native rewind alias in current environments. @@ -808,8 +808,8 @@ Parse the user's input: - `/context-restore` → load the most recent saved context (any branch) - `/context-restore ` → load a specific saved context -- `/context-restore list` → tell the user "Use `/context-save list` — listing - lives on the save side" and exit. No mode detection here. +- `/context-restore list` → display the same cross-branch candidate list from + Step 1 and exit without loading a file. --- @@ -853,23 +853,60 @@ enables Conductor workspace handoff. Read the chosen file and present a summary: +Then inspect the sibling Universal Save receipt without writing anything: + +```bash +# Set CHOSEN_FILE to the exact checkpoint selected above. +RECEIPT_FILE="${CHOSEN_FILE%.md}.receipt.json" +if [ -f "$RECEIPT_FILE" ]; then + echo "RECEIPT_FILE=$RECEIPT_FILE" +else + echo "LEGACY_CHECKPOINT_NO_RECEIPT" +fi ``` -RESUMING CONTEXT + +If `RECEIPT_FILE` exists, read it and include: + +- `receipt_schema_version` (`missing` means supported legacy v0; versions above + `1` are unsupported and must produce a warning rather than a green claim); +- `verification.layers` statuses for working checkpoint, Codex Brain, Obsidian + bridge and QMD; +- exact `receipt_path` and `restore.command`; +- the first item under `### Что осталось` / `### Remaining Work` as the next + action. + +If any layer is absent or not `ok`, start the result with +`ВОССТАНОВЛЕНИЕ С ПРЕДУПРЕЖДЕНИЕМ` and name the exact layer. Do not run save, +resume, QMD update/embed or any write from this read-only skill. A legacy +checkpoint without a receipt remains restorable, but label its four-layer status +as `не подтверждён`. + +Present the human-facing result in Russian: + +``` +ВОССТАНОВЛЕНИЕ КОНТЕКСТА ════════════════════════════════════════ -Title: {title} -Branch: {branch from frontmatter} -Saved: {timestamp, human-readable} -Duration: Last session was {formatted duration} (if available) -Status: {status} +Название: {title} +Ветка: {branch from frontmatter} +Сохранено: {timestamp, human-readable} +Длительность:{formatted duration, if available} +Статус: {status} +Квитанция: {receipt path or legacy} ════════════════════════════════════════ -### Summary +### Кратко {summary from saved file} -### Remaining Work +### Состояние четырёх слоёв +Checkpoint: {status} +Codex Brain: {status} +Obsidian: {status} +QMD: {status} + +### Что осталось {remaining work items} -### Notes +### Примечания {notes} ``` @@ -893,14 +930,16 @@ If A, summarize the first remaining work item and suggest starting there. If Step 1 printed `NO_CHECKPOINTS`, tell the user: -"No saved contexts yet. Run `/context-save` first to save your current working -state, then `/context-restore` will find it." +"Сохранённых контекстов пока нет. Запустите `/save`, затем +`/context-restore` найдёт сохранение." --- ## Important Rules - **Never modify code.** This skill only reads saved files and presents them. +- **Never mutate a receipt.** Receipt inspection and four-layer verification + display are read-only; repair belongs to `/save` resume flow. - **Always search across all branches by default.** Cross-branch resume is the whole point. Only filter by branch if the user explicitly asks via a title-fragment match that happens to be branch-specific. diff --git a/context-restore/SKILL.md.tmpl b/context-restore/SKILL.md.tmpl index 55889f6e0..3b141208f 100644 --- a/context-restore/SKILL.md.tmpl +++ b/context-restore/SKILL.md.tmpl @@ -3,11 +3,11 @@ name: context-restore preamble-tier: 2 version: 1.0.0 description: | - Restore working context saved earlier by /context-save. Loads the most recent + Restore working context saved earlier by /save or legacy /context-save. Loads the most recent saved state (across all branches by default) so you can pick up where you left off — even across Conductor workspace handoffs. Use when asked to "resume", "restore context", "where was I", or - "pick up where I left off". Pair with /context-save. + "pick up where I left off". Pair with /save. Formerly /checkpoint resume — renamed because Claude Code treats /checkpoint as a native rewind alias in current environments. (gstack) allowed-tools: @@ -51,8 +51,8 @@ Parse the user's input: - `/context-restore` → load the most recent saved context (any branch) - `/context-restore ` → load a specific saved context -- `/context-restore list` → tell the user "Use `/context-save list` — listing - lives on the save side" and exit. No mode detection here. +- `/context-restore list` → display the same cross-branch candidate list from + Step 1 and exit without loading a file. --- @@ -96,23 +96,60 @@ enables Conductor workspace handoff. Read the chosen file and present a summary: +Then inspect the sibling Universal Save receipt without writing anything: + +```bash +# Set CHOSEN_FILE to the exact checkpoint selected above. +RECEIPT_FILE="${CHOSEN_FILE%.md}.receipt.json" +if [ -f "$RECEIPT_FILE" ]; then + echo "RECEIPT_FILE=$RECEIPT_FILE" +else + echo "LEGACY_CHECKPOINT_NO_RECEIPT" +fi ``` -RESUMING CONTEXT + +If `RECEIPT_FILE` exists, read it and include: + +- `receipt_schema_version` (`missing` means supported legacy v0; versions above + `1` are unsupported and must produce a warning rather than a green claim); +- `verification.layers` statuses for working checkpoint, Codex Brain, Obsidian + bridge and QMD; +- exact `receipt_path` and `restore.command`; +- the first item under `### Что осталось` / `### Remaining Work` as the next + action. + +If any layer is absent or not `ok`, start the result with +`ВОССТАНОВЛЕНИЕ С ПРЕДУПРЕЖДЕНИЕМ` and name the exact layer. Do not run save, +resume, QMD update/embed or any write from this read-only skill. A legacy +checkpoint without a receipt remains restorable, but label its four-layer status +as `не подтверждён`. + +Present the human-facing result in Russian: + +``` +ВОССТАНОВЛЕНИЕ КОНТЕКСТА ════════════════════════════════════════ -Title: {title} -Branch: {branch from frontmatter} -Saved: {timestamp, human-readable} -Duration: Last session was {formatted duration} (if available) -Status: {status} +Название: {title} +Ветка: {branch from frontmatter} +Сохранено: {timestamp, human-readable} +Длительность:{formatted duration, if available} +Статус: {status} +Квитанция: {receipt path or legacy} ════════════════════════════════════════ -### Summary +### Кратко {summary from saved file} -### Remaining Work +### Состояние четырёх слоёв +Checkpoint: {status} +Codex Brain: {status} +Obsidian: {status} +QMD: {status} + +### Что осталось {remaining work items} -### Notes +### Примечания {notes} ``` @@ -136,14 +173,16 @@ If A, summarize the first remaining work item and suggest starting there. If Step 1 printed `NO_CHECKPOINTS`, tell the user: -"No saved contexts yet. Run `/context-save` first to save your current working -state, then `/context-restore` will find it." +"Сохранённых контекстов пока нет. Запустите `/save`, затем +`/context-restore` найдёт сохранение." --- ## Important Rules - **Never modify code.** This skill only reads saved files and presents them. +- **Never mutate a receipt.** Receipt inspection and four-layer verification + display are read-only; repair belongs to `/save` resume flow. - **Always search across all branches by default.** Cross-branch resume is the whole point. Only filter by branch if the user explicitly asks via a title-fragment match that happens to be branch-specific. diff --git a/gstack/llms.txt b/gstack/llms.txt index efe522f90..579b4be2a 100644 --- a/gstack/llms.txt +++ b/gstack/llms.txt @@ -18,7 +18,7 @@ Conventions: - [/careful](careful/SKILL.md): Safety guardrails for destructive commands. - [/claude](claude/SKILL.md): Claude Code CLI wrapper for non-Claude hosts - three modes. - [/codex](codex/SKILL.md): OpenAI Codex CLI wrapper — three modes. -- [/context-restore](context-restore/SKILL.md): Restore working context saved earlier by /context-save. +- [/context-restore](context-restore/SKILL.md): Restore working context saved earlier by /save or legacy /context-save. - [/context-save](context-save/SKILL.md): Save working context. - [/cso](cso/SKILL.md): Chief Security Officer mode. - [/design-consultation](design-consultation/SKILL.md): Design consultation: understands your product, researches the landscape, proposes a complete design system (aesthetic, typography, color, layout, spacing, motion), and generates font+color preview pages. diff --git a/scripts/proactive-suggestions.json b/scripts/proactive-suggestions.json index d08c60853..8a12780a8 100644 --- a/scripts/proactive-suggestions.json +++ b/scripts/proactive-suggestions.json @@ -39,8 +39,8 @@ "voice_line": "Voice triggers (speech-to-text aliases): \"code x\", \"code ex\", \"get another opinion\"." }, "context-restore": { - "lead": "Restore working context saved earlier by /context-save.", - "routing": "Loads the most recent\nsaved state (across all branches by default) so you can pick up where you\nleft off — even across Conductor workspace handoffs.\nUse when asked to \"resume\", \"restore context\", \"where was I\", or\n\"pick up where I left off\". Pair with /context-save.\nFormerly /checkpoint resume — renamed because Claude Code treats /checkpoint\nas a native rewind alias in current environments.", + "lead": "Restore working context saved earlier by /save or legacy /context-save.", + "routing": "Loads the most recent\nsaved state (across all branches by default) so you can pick up where you\nleft off — even across Conductor workspace handoffs.\nUse when asked to \"resume\", \"restore context\", \"where was I\", or\n\"pick up where I left off\". Pair with /save.\nFormerly /checkpoint resume — renamed because Claude Code treats /checkpoint\nas a native rewind alias in current environments.", "voice_line": null }, "context-save": { diff --git a/test/context-restore-receipt.test.ts b/test/context-restore-receipt.test.ts new file mode 100644 index 000000000..a025e6ba6 --- /dev/null +++ b/test/context-restore-receipt.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, test } from 'bun:test'; +import * as fs from 'fs'; +import * as path from 'path'; + +const ROOT = path.resolve(import.meta.dir, '..'); + +describe('context-restore Universal Save receipt contract', () => { + const sources = [ + 'context-restore/SKILL.md.tmpl', + 'context-restore/SKILL.md', + '.agents/skills/gstack-context-restore/SKILL.md', + ]; + + for (const relative of sources) { + test(`${relative} reads four-layer receipts without mutation`, () => { + const content = fs.readFileSync(path.join(ROOT, relative), 'utf-8'); + expect(content).toContain('RECEIPT_FILE="${CHOSEN_FILE%.md}.receipt.json"'); + expect(content).toContain('receipt_schema_version'); + expect(content).toContain('Codex Brain'); + expect(content).toContain('Obsidian'); + expect(content).toContain('QMD'); + expect(content).toContain('Never mutate a receipt'); + expect(content).toContain('ВОССТАНОВЛЕНИЕ КОНТЕКСТА'); + }); + } +});