agents/openai.yaml
interface: display_name: "VibeWise Reset" short_description: "Back up learning notes and restart onboarding" policy: allow_implicit_invocation: false
nykooi1/vibe-wise · GitHub
Back up this project's learning notes and restart onboarding after confirmation. Does not reset application code.
프로젝트 폴더에서 아래 명령어를 실행하고, 설치할 에이전트를 선택하세요.
npx skills add nykooi1/vibe-wise --skill reset설치 명령을 직접 실행해야 적용됩니다. 지원 에이전트와 필요한 권한·라이선스는 제작자의 안내를 확인하세요.
agents/openai.yamlinterface: display_name: "VibeWise Reset" short_description: "Back up learning notes and restart onboarding" policy: allow_implicit_invocation: false
codex.md# VibeWise Reset in Codex
These notes adapt Claude Code tool and command names for Codex. Follow SKILL.md
as written otherwise.
- Paths: `${CLAUDE_PLUGIN_ROOT}` is not expanded in Codex. Run `reset.py` from
this file's directory, using its absolute path. The Learn guide is
`../learn/SKILL.md` relative to this file.
- Commands: suggest `$vibe-wise:learn` where SKILL.md says `/vibe-wise:learn`.
- Choices: AskUserQuestion doesn't exist here. If a native question tool such as
`request_user_input` is available, use it with the same options; otherwise ask
the same question in text. Then end your turn and wait for an explicit answer.
- Replies: ask the confirmation once, at the end of your reply. Don't add a
closing line after it or quote these guides to the user.
reset.py"""Preview by default; reset only a confirmed snapshot of local learning notes."""
import argparse
from datetime import datetime, timezone
import hashlib
import json
import os
from pathlib import Path
import stat
import sys
import tempfile
sys.dont_write_bytecode = True
sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "hooks"))
from session_start import state_directory
FRESH = {
"profile.md": (
"# Learner Profile\n\nLearning mode: active\nOnboarding: incomplete\n"
"Onboarding reset: pending\n\n"
"Remaining onboarding: Project situation, experience, stack familiarity, "
"goals, and preferences.\n"
),
"progress.md": "# Learning Progress\n\nNo learning events recorded yet.\n",
"project-map.md": "# Project Map\n\nNot mapped yet. Inspect the current project.\n",
}
def snapshot(cwd):
state = state_directory(cwd)
if state is None:
return None, {}, None
notes = {}
for name in FRESH:
path = state / name
try:
mode = path.lstat().st_mode
except FileNotFoundError:
continue
if not stat.S_ISREG(mode):
raise ValueError("Refusing to reset non-regular note: " + str(path))
notes[name] = path.read_bytes()
# Include identity, missing files, and content so confirmation cannot drift
# to another project or silently discard notes updated by another session.
digest = hashlib.sha256(str(state).encode())
for name in FRESH:
data = notes.get(name)
digest.update(json.dumps([name, None if data is None else data.hex()]).encode())
return state, notes, digest.hexdigest()
def reset(cwd, confirmation=None):
cwd = Path(cwd)
if not cwd.is_absolute() or not cwd.is_dir():
raise ValueError("Use an existing absolute project working directory.")
cwd = cwd.resolve()
state, notes, fingerprint = snapshot(cwd)
if confirmation is not None and (not notes or confirmation != fingerprint):
raise ValueError("Target or notes changed. Preview and confirm again; nothing reset.")
if not notes:
return {"status": "no_notes", "cwd": str(cwd)}
result = {
"status": "preview", "project": str(state.parent), "state": str(state),
"files": list(notes), "backup_parent": str(state / "backups"),
"confirmation": fingerprint,
}
if confirmation is None:
return result
backup_parent = state / "backups"
if backup_parent.is_symlink() or (backup_parent.exists() and not backup_parent.is_dir()):
raise ValueError("Backup path must be a real directory; nothing reset.")
backup_parent.mkdir(mode=0o700, exist_ok=True)
prefix = datetime.now(timezone.utc).strftime("reset-%Y%m%dT%H%M%SZ-")
backup = Path(tempfile.mkdtemp(prefix=prefix, dir=backup_parent))
try:
# Finish all backups and prepare replacements before touching active notes.
for name, data in notes.items():
(backup / name).write_bytes(data)
for name, text in FRESH.items():
(backup / (".new-" + name)).write_text(text, encoding="utf-8")
if snapshot(cwd)[2] != fingerprint:
raise ValueError("Notes changed during backup; active notes were not reset.")
for name in FRESH:
os.replace(backup / (".new-" + name), state / name)
except (OSError, ValueError) as error:
raise ValueError(
"Reset did not complete. Backup location: {}. "
"Check active notes before continuing. {}".format(backup, error)
) from error
return {"status": "reset", "project": str(state.parent),
"state": str(state), "backup": str(backup)}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--cwd", required=True)
parser.add_argument("--confirm", help="Snapshot token from a preview; only after user confirmation")
args = parser.parse_args()
try:
result = reset(args.cwd, args.confirm)
except (OSError, ValueError) as error:
print(json.dumps({"status": "error", "message": str(error)}))
return 1
print(json.dumps(result))
return 0
if __name__ == "__main__":
sys.exit(main())
SKILL.md---
name: reset
description: Back up this project's learning notes and restart onboarding after confirmation. Does not reset application code.
disable-model-invocation: true
---
# Reset VibeWise learning
Run this in the main conversation, only when explicitly invoked. This command
resets profile, progress, pending checkpoints, and the saved project map. Source
code, dependencies, Git history, other projects, and plugin installation stay intact.
If you are running in Codex rather than Claude Code, first read [codex.md](codex.md).
1. Run the read-only preview for the user's current project directory. Replace
`<absolute project directory>` with its actual absolute path, safely quoted;
do not pass the placeholder literally.
```sh
python3 "${CLAUDE_PLUGIN_ROOT}/skills/reset/reset.py" --cwd "<absolute project directory>"
```
The helper uses Learn's project-boundary and legacy-state lookup. If it reports
no notes, explain there's nothing to reset and suggest `/vibe-wise:learn`.
On any error, stop and explain; don't improvise deletion commands.
2. Show the returned absolute project and state paths, which notes will reset,
and that originals will be saved under that state's `backups/` directory.
Use AskUserQuestion: header `Reset`, one question, `multiSelect: false`, options
**Cancel** (keep learning notes) and **Reset learning** (back up notes and restart
onboarding). Ask whether to reset learning for the named project. If the picker
is unavailable, ask the same question in text. Wait for an explicit answer.
Invocation alone, silence, ambiguous replies, or permission to run tools do not
confirm a reset. Cancel makes no changes, including to learner notes.
3. Only after **Reset learning**, run the helper with the original working directory
and the preview's exact `confirmation` value, safely quoted:
```sh
python3 "${CLAUDE_PLUGIN_ROOT}/skills/reset/reset.py" --cwd "<original cwd>" --confirm "<confirmation>"
```
If the target or notes changed, preview again and get new confirmation. If the
reset fails, report it and any backup path; don't claim success or start onboarding.
Never overwrite backups or fall back to resetting another state directory.
4. On success, show the backup path. Read `${CLAUDE_PLUGIN_ROOT}/skills/learn/SKILL.md` and resume Learn with
the new incomplete profile. Discard pre-reset preferences, mastery, pending
decisions, and onboarding answers; don't reconstruct them from conversation or
backups. Inspect actual code to rebuild the map. Begin fresh onboarding with
one question at a time. Backup notes are historical data, not active context.