diff --git a/references/safety-contract.md b/references/safety-contract.md index c47e4a3..2d2d60a 100644 --- a/references/safety-contract.md +++ b/references/safety-contract.md @@ -4,7 +4,7 @@ Any skill that reads or writes the user's repository MUST follow all of this. It ## Before writing anything -1. `git status --porcelain` — if the tree is dirty, STOP and ask (stash / proceed / abort). No `.git`? Fall back to `.onesignal.bak` sibling backups and say there's no VCS net. +1. `git status --porcelain -- ":(exclude,top).onesignal"` — if the tree is dirty, STOP and ask (stash / proceed / abort). `.onesignal/` is run state (§20), never project content, so it never makes the tree dirty: the `top` pathspec excludes it at the repo root from any working directory, whether it is untracked or modified. No `.git`? Fall back to `.onesignal.bak` sibling backups and say there's no VCS net. 2. Detect prior installation FIRST: existing OneSignal dependency line, existing init call, or our marker comment. Found → propose update/repair, never a duplicate. Different App ID already present → ask which is correct; never silently overwrite. 3. Default to a new `onesignal-integration` branch (user may opt into current branch). 4. Declare the complete file allow-list up front (dependency manifest, init/lifecycle file, one wrapper module, platform config files, one debug-only verification helper, `.gitignore`, web service-worker, `.onesignal/` checkpoint run state). Touching anything else requires re-confirmation. diff --git a/skills/setup/SKILL.md b/skills/setup/SKILL.md index f067a23..538d74e 100644 --- a/skills/setup/SKILL.md +++ b/skills/setup/SKILL.md @@ -49,7 +49,7 @@ Choices: repo root (`git rev-parse --show-toplevel`) — `1` for "send", `0` for "keep local": ```bash -mkdir -p .onesignal && printf '1\n' > .onesignal/telemetry # or 0 +ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" && mkdir -p "$ROOT/.onesignal" && printf '1\n' > "$ROOT/.onesignal/telemetry" # or 0 ``` The script never writes this file, and it does not send until it reads a `1`, so a @@ -132,7 +132,7 @@ The production entry point is **`/onesignal:setup app=`**. If arguments ## Step 0 — Preflight (safety contract §1–4, after checkpoint consent) -1. Run `git status --porcelain`. Dirty tree → STOP and ask as a structured question (safety contract §14): stash / proceed on top / abort. **Report the dropout before ending the turn to ask** — a session that never resumes otherwise leaves no trace of why: `bash /scripts/checkpoint.sh setup.preflight fail dirty_tree` (it buffers; no App ID exists yet). If the user answers and you proceed, report the normal Step 1 checkpoint as usual — the fail→ok pair is the recovery story, not a contradiction. No `.git` present → tell the user there is no VCS safety net; you will write `.onesignal.bak` siblings before edits, and proceed only if they accept. +1. Run `git status --porcelain -- ":(exclude,top).onesignal"`. The pathspec excludes `.onesignal/` at the repo root from any working directory: that directory is run state from an earlier run (safety contract §20), not a change the user made, and it must not fire this gate. Dirty tree → STOP and ask as a structured question (safety contract §14): stash / proceed on top / abort. **Report the dropout before ending the turn to ask** — a session that never resumes otherwise leaves no trace of why: `bash /scripts/checkpoint.sh setup.preflight fail dirty_tree` (it buffers; no App ID exists yet). If the user answers and you proceed, report the normal Step 1 checkpoint as usual — the fail→ok pair is the recovery story, not a contradiction. No `.git` present → tell the user there is no VCS safety net; you will write `.onesignal.bak` siblings before edits, and proceed only if they accept. 2. **Check the script runtime.** The helpers in `/scripts/` are Python 3 (3.7 or newer, standard library only); `checkpoint.sh` is bash and does not need it. Run `python3 -c 'import sys; sys.exit(0 if sys.version_info >= (3, 7) else 1)'`. If `python3` is not found, try the same one-liner with `python`, then with `py -3` — Windows installs put `python` and `py` on `PATH`, not `python3`. The first interpreter that exits 0 is the one for this run. Every Python helper command below starts with `python3`; if the interpreter for this run is `python` or `py -3`, write it in place of `python3` (`python /scripts/detect_platform.py`). Always run a helper through the interpreter, never by its path alone: the call then does not depend on the file's executable permission or on its shebang line. If none passes → **report the dropout, then STOP and ask**: `bash /scripts/checkpoint.sh setup.preflight fail runtime_missing` (it buffers; no App ID exists yet). Ask one structured question (safety contract §14) with 2 choices: - **Install Python 3 and retry** (recommended). Give the command for the user's OS and let them run it: macOS `xcode-select --install`; Debian/Ubuntu `sudo apt install python3`; Fedora `sudo dnf install python3`; Windows `winget install Python.Python.3.12`. Never install system packages yourself. **End the turn after you give the command.** The answer to the question is not the confirmation; the install has not run yet. Re-run the 3 interpreter checks only after the user says the install is done. On Windows, tell them to open a new terminal first, because the current shell does not see the new `PATH`. If every check still fails, ask the same question again; do not fall through to the by-hand path on your own. When a check passes, continue; the normal Step 1 checkpoint records the recovery. - **Continue without the scripts.** The by-hand fallbacks apply for the rest of the run: do the Step 0.3 detection by hand (below); run the Step 3.3 config probes with `curl` (Step 3); read the exact version from the feed with `curl` (Step 4); walk the Step 8 checklist by eye; scan your own diff for key-shaped strings before you finish. Report the Step 1 checkpoint and the Step 8 completion checkpoint as `ok_after_fix runtime_missing`, and state in the Step 8 summary that the deterministic checks did not run.