# Safe Code

> Use when asked to run a full repo hygiene pass, full cleanup, or to maintain a repo in one go — and whenever the user invokes /safe-code or any wrapper of it (/skill:safe-code, /skills safe-code, $safe-code, @safe-code, or bare safe-code), including --continue to resume saved work and --save to finalize docs and commit. Also use for first-time project setup, restoring project context or session memory, dead-code audits, or agent-config trust checks.

- Skill: `afu-it/safe-code` (Agent Skill, multi-file: 12 files)
- Install (CLI): `npx skillmds@latest add afu-it/safe-code`
- Raw SKILL.md: https://api.skillmd.com/api/skills/afu-it/safe-code/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: afu-it (https://skillmd.com/u/afu-it)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/afu-it/safe-code

---


# Safe Code

Run a complete repo hygiene pass autonomously. Think before acting. Make decisions independently. Only ask the user when a decision cannot be reversed or when intent is genuinely unclear.

Apply `$senior-dev` discipline throughout the run: task list first, measure twice cut once, adversarial strategy critique, clean repo policy, small reversible slices, and verification before completion.

## Scope Rule (Read This First)

**Everything operates inside the current project root only.**

- Never read from or write to paths outside the current project root
- Never use `~/`, `~/.safe-code/`, or any home directory path
- All paths are relative to the project root
- The project root is the directory where the agent was invoked
- Graph MCP bootstrap may create or update `<project-root>/.mcp.json` only. Do not auto-edit global agent MCP config.
- **One exception, user-declared:** the Save Bridge (`--save`) may *append* to the single absolute file the user recorded as `diary_path` in `user-preferences.md`. Append-only, existence check only, never read, never committed, never created. No `diary_path` -> no exception.

```
CORRECT: <project-root>/.safe-code/ACTIVE.md
WRONG:   ~/.safe-code/ACTIVE.md
```

---

## Safety Invariants (every command, every mode)

- **Never push.** Every save is a local commit only; remote detection never triggers a push.
- **Never copy secrets, raw logs, stack traces, private URLs, or `current-issues.md` content into any committed file.** A sanitized one-line summary in `LOG.md` is the committed history.
- **Never overwrite an existing file** when scaffolding, migrating, or writing bridges: create missing files, append clearly-marked blocks, or report the conflict.
- **Never read or write outside the project root** (Scope Rule above; the user-declared Save Bridge is the one append-only exception).
- **Gitignore work artifacts at creation, not at audit.** Any directory a run generates for itself (captures, mirrors, scratch, logs, unpacked bundles) gets a `.gitignore` entry the moment it is created — such folders routinely hold live session tokens and cookies, and "audit before commit" has already failed once too often.
- **Redact before you show.** Debug loops, smoke runs, and captured artifacts (HAR files, request dumps) print commands and outputs: every secret becomes `<REDACTED>` before it reaches the transcript, loops are built against env vars so the credential stays in the environment, and artifacts are quoted only on the lines that carry the signal. If the redacted output is not enough to diagnose, say so and ask.
- **Inspect secret-bearing files by shape, never by value.** For `.env*`, auth/session stores, token caches, keychains: report key names, byte length, and mtime only (`cut -d= -f1`, `wc -c`, `stat`); never `cat` them, never print a value or an expiry payload into the transcript. A transcript leak is a leak.

---

## Doc Structure

```
<project-root>/
├── AGENTS.md                      <- canonical entry point + Read First order (source of truth)
├── CLAUDE.md                      <- ┐
├── GEMINI.md                      <- │ provider bridges: thin pointers to AGENTS.md so each
├── .github/copilot-instructions.md<- │ host auto-loads the same brain (no state, just redirect)
├── .cursor/rules/safe-code.mdc    <- ┘
└── .safe-code/                    <- the project brain + all session state (continuity)
    ├── ACTIVE.md                  <- saved resume point; written on /safe-code --save
    ├── SESSION.md                 <- working memory + draft doc/context updates
    ├── LOG.md                     <- append-only safe diary; no raw secrets/log dumps
    ├── BACKLOG.md                 <- operational task queue
    ├── MEMORY.md                  <- temporary audit/refactor architecture notes
    ├── safe-refactor-code.md      <- refactor rules and flagged candidates
    ├── CHANGELOG.md               <- release history (update on release only)
    └── context/                   <- project brain; canonical long-term context
        ├── project-overview.md    <- what, who, goals, scope, success criteria
        ├── architecture.md        <- stack, boundaries, storage, invariants
        ├── user-preferences.md    <- user-approved preferences and hard dislikes
        ├── code-standards.md      <- implementation conventions
        ├── ai-workflow-rules.md   <- agent workflow and scoping rules
        ├── ui-context.md          <- UI/design conventions (read only for UI work)
        ├── progress-tracker.md    <- phase, current goal, decisions, safe session notes
        ├── current-issues.md      <- issue tracker: user + AI-appended; local-only, gitignored
        └── feature-specs/         <- AI-written specs w/ status field; suggestions + active units
            └── 00-template.md
```

`/safe-code` keeps all continuity in **one** place — `AGENTS.md` + the `.safe-code/` folder are the single source of truth, shared by every agent (Codex, Claude, Cursor, Windsurf, Copilot, Gemini): continuity belongs to the project, not the tool. A thin **provider-bridge pointer** redirects the current host to that same brain; bridges hold no state, and their mechanics are defined once in the Provider Bridge section (Step 1). Never store session/context docs in `.codex/`, `.claude/`, `.cursor/`, `.windsurf/`, or `.agents/` — those are legacy layouts that get migrated into `.safe-code/` and removed (bridge pointers are not session state and are preserved).

The six session files (`ACTIVE.md`, `SESSION.md`, `LOG.md`, `BACKLOG.md`, `MEMORY.md`, `safe-refactor-code.md`) sit directly inside `.safe-code/`. `.safe-code/context/` is canonical project context; the six session files are operational session state.

---

## Loading Layers

### Layer 1 — Entry (every session)

```
AGENTS.md                         — root instructions and Read First order
.safe-code/context/project-overview.md       — product/project definition
.safe-code/context/architecture.md           — system boundaries and invariants
.safe-code/context/user-preferences.md       — user-approved preferences and hard dislikes
.safe-code/context/code-standards.md         — coding conventions
.safe-code/context/ai-workflow-rules.md      — workflow rules
.safe-code/context/ui-context.md             — only for UI/design work
.safe-code/context/progress-tracker.md       — Current Phase, Current Goal, Next Up, Open Questions only
ACTIVE.md                         — Before/Current/Next blocks only, if present
SESSION.md                        — Carry Forward + draft updates only, if present
LOG.md                            — last 3 typed entries only, if present
```

Do not read `.safe-code/context/current-issues.md` during normal work. Read **and append to** it when the user reports an issue — trigger phrases like "fix this", "failed", "got error", "bug", "crash", "tak jalan", "rosak", or a pasted stack trace — or when the user references that file. See the Issue Tracking Rule.

After loading, start the session's **first** reply with a one-line brain-status banner: `[safe-code: brain loaded @ <last_synced_commit | unsynced>]`; when context is missing, `[safe-code: no project brain — run /safe-code]`, or `[safe-code: no project brain — initializing now]` if the current invocation already IS `/safe-code`. Once per session only.

### Layer 2 — Resume (`/safe-code --continue` or auto-continue)

```
.safe-code/context/progress-tracker.md       — full content
ACTIVE.md                         — full content
SESSION.md                        — full content
LOG.md                            — full content if Last Session.status = saved
```

`/safe-code` must auto-use Layer 2 when saved unfinished state exists, even if the user forgot `--continue`.

### Layer 3 — Detail (triggered only)

```
.safe-code/context/feature-specs/<active>.md — feature/refactor work contract
.safe-code/context/architecture.md           — audit/refactor/debug impact checks
MEMORY.md                         — old/migrated architecture notes or audit detail
safe-refactor-code.md             — cleanup/refactor candidates and guardrails
BACKLOG.md                        — operational queue sync
.safe-code/CHANGELOG.md                      — releasable changes only
```

Do not load detail files unless the trigger condition is met.

---

## Project Context vs Session State

| | `.safe-code/context/` | `.safe-code/` |
|---|---|---|
| Purpose | Long-term project brain | Runtime/session memory |
| Updated | Draft during work, finalize on `/safe-code --save` | `SESSION.md` during work; others on save |
| Canonical for | Product, architecture, standards, workflow, progress | Resume point, logs, cleanup/refactor notes |
| Secrets/raw logs | Never | Avoid; keep summaries only |

`.safe-code/context/current-issues.md` is special: safe-code creates the template and gitignores it. Both the user and the agent write it — the user pastes raw context, and the agent appends/updates issue entries on error triggers (see the Issue Tracking Rule). It may contain raw errors, URLs, or secrets, so the Safety Invariants apply.

`.safe-code/context/user-preferences.md` captures explicit, durable user preferences from conversation. Add only when the user clearly says they want/avoid something, or repeats a preference. Draft changes in `SESSION.md` and apply on `/safe-code --save`.

### Source-of-Truth Ownership

Avoid duplicate truth: each fact has exactly one canonical home — root rules -> `AGENTS.md`; product/goals -> `project-overview.md`; stack/invariants -> `architecture.md`; preferences -> `user-preferences.md`; conventions -> `code-standards.md`; workflow -> `ai-workflow-rules.md`; UI -> `ui-context.md`; phase + safe decisions -> `progress-tracker.md`; feature scope + idea history -> `feature-specs/<nn-name>.md` (with `status:` field); releases -> `.safe-code/CHANGELOG.md`; issues -> `current-issues.md` (local-only); resume point -> `ACTIVE.md`; live tasks/drafts -> `SESSION.md` (wiped on save); refactor candidates -> `safe-refactor-code.md`.

When two files disagree, prefer executable repo evidence first, then canonical home, then session notes. Record mismatch in `SESSION.md` and fix canonical home on `/safe-code --save`.

> **Layer 3 Trigger:** When unsure where a fact belongs, or what may appear in non-canonical locations, read `references/source-of-truth.md` (Ownership Table).

### Evidence Tags

Load-bearing technical claims written into `.safe-code/context/*.md` (paths, commands, invariants, architecture facts) should carry an evidence tag:

- `[extracted: <path|command>]` — read directly from the repo; the tag names where, so a later agent can re-verify by running the pointer instead of trusting prose.
- `[inferred: <basis>]` — a deduction; the tag names what it is deduced from.

Untagged prose is fine for narrative, but a technical claim that cannot be tagged `[extracted: …]` is a candidate Open Question, not a fact. The Context Self-Test treats answers resting only on `[inferred]` claims as weak evidence (see `references/first-run.md`). Tags make the brain self-auditing — the written context carries the same EXTRACTED/INFERRED honesty as repo evidence itself.

---

## Command Recognition (Read Before Parsing Any Command)

Hosts wrap invocation differently — `/safe-code`, `/skill:safe-code`, `/skills safe-code`, `/skill safe-code`, `$safe-code`, `@safe-code`, bare `safe-code`, and `run safe-code` are all the same invocation. Strip the wrapper and the name; map whatever argument remains to a mode:

- empty -> `/safe-code` (setup / auto-resume / fresh pass)
- `--continue` | `continue` | `-c` | `resume` -> continue mode
- `--save` | `save` | `-s` | `finish` | `end` -> save mode
- `--explain` | `explain` | `explain my project` | `what does my app do` | `apa projek` -> explain mode (read-only briefing)
- `--graphify` | `graphify` | `graph` -> graphify build mode; `--graphify "<question>"` (any trailing text after the flag, quoted or not) -> graphify query mode (read-only)
- `fresh pass` | `fresh setup` | `ignore saved state` -> force a fresh pass
- unrecognized -> default to plain `/safe-code` and note which form you received. Never refuse a run just because the host used a different prefix.

**Flag-only shorthand:** when the project contains `.safe-code/` and the user's message is just a bare flag — `--save`, `--continue`, `--explain`, `--graphify` (optionally with a trailing question) — treat it as the matching `/safe-code` mode; the flag syntax is unambiguous even without the name. Bare *words* (`save`, `continue`) without the flag or the safe-code name are NOT claimed — they may belong to another assistant's save/memory system on the user's machine; act on them as safe-code only when the context makes that clearly the intent.

The canonical forms are `/safe-code`, `/safe-code --continue`, `/safe-code --save`, `/safe-code --explain`, `/safe-code --graphify` — use them in your own output, but accept any wrapper the host produced.

---

## Command: `/safe-code`

Run setup, auto-resume, or a fresh hygiene pass.

Behavior:

1. Locate project root and the single `.safe-code/` folder.
2. If saved unfinished safe-code state exists, automatically behave like `/safe-code --continue` and print: `Saved safe-code session found; resuming automatically. Say "fresh pass" to ignore saved state.`
3. If no saved state exists, initialize/reconcile doc structure.
4. If any legacy layout exists (`.codex/agents/`, `.claude/agents/`, `.cursor/agents/`, `.windsurf/agents/`, v3 `.agents/`, or safe-code-managed root `context/`), run Legacy Layout Migration: move content into `.safe-code/`, patch old config to the new paths, remove the emptied legacy folders.
5. Explore repo facts and select the safest profile: Orientation, Audit, or Cleanup.

Start a truly fresh pass only when no saved state exists or user explicitly says `fresh pass`, `fresh setup`, or `ignore saved state`.

## Command: `/safe-code --continue`

Resume an existing safe-code session with full context loading. Use this in a new chat, new day, or after `/safe-code --save`. `/safe-code` auto-enters this mode when saved state exists.

First, detect old setup config (legacy folders, old `.gitignore` entry, old `AGENTS.md` paths). If found, run Legacy Layout Migration before loading anything — saved state may still live in the old location.

Before doing work, read: `AGENTS.md`, then Layer 2 in full (`progress-tracker.md`, `ACTIVE.md`, `SESSION.md`, `LOG.md`), plus the active `feature-specs/<file>.md` when resuming a feature, and `MEMORY.md`/`safe-refactor-code.md` only for audit/refactor/debug resumes.

Do not guess previous context. If saved state contradicts repo evidence, trust executable repo evidence and record the mismatch in `SESSION.md`.

## Command: `/safe-code --save`

End the session safely.

Save does these things:

```
0. Detect old setup config (legacy folders, old .gitignore entry, old AGENTS.md
   paths) — if found, run Legacy Layout Migration first so the save lands in
   .safe-code/ on the new version
1. Review SESSION.md draft updates
2. Apply approved context/doc updates
3. Update .safe-code/context/progress-tracker.md with safe summary only; set
   last_synced_commit to current HEAD and context_synced_at to today (Context Freshness Check)
4. Update ALL SIX session files (Six-File Save Rule below):
   - ACTIVE.md            -> Last Session block + next_action
   - SESSION.md           -> wipe to clean carry-forward template
   - LOG.md               -> append safe typed summary + a `plain:` one-line recap
                            a non-coder can read (then apply trim rule)
   - BACKLOG.md           -> sync queue from SESSION.md drafts
   - MEMORY.md            -> apply drafted audit/refactor notes
   - safe-refactor-code.md -> apply flagged candidates and guardrail changes
5. Update .safe-code/CHANGELOG.md only for releasable changes
6. Ensure local git repo exists when allowed by current repo state
7. Split the session into atomic commits (Atomic Commit Split Rule below)
8. Retro: scan the run for environment improvements (Retro Rule below); write
   findings to BACKLOG.md as `retro:` items — nothing found, nothing written
9. Save Bridge: if user-preferences.md has `diary_path:` and that file exists,
   append one dated block (project, `plain:` recap, commit hashes) to it —
   append-only, outside the repo, never committed, never created (Save Bridge Rule below)
10. Report commit hashes + types + local-only status + next action
```

Do not push.

### Atomic Commit Split Rule

`/safe-code --save` turns the session's **one** save into **several atomic commits**: code/behavior tasks first in task order (conventional `type: subject` from each task's annotation), root scaffold artifacts this run created (`.mcp.json`, bridges, `.gitignore`) as their own `chore:`/`docs:` group, then ONE final bookkeeping commit for `.safe-code/` + `context/` updates (`docs: sync .safe-code session files`) — always last, never mixed with code. The gate is unchanged: only at `--save`, **local-only, never pushes**, never `--no-verify`; no re-verification between commits (each task was verified per-slice during the run — the split is staging over already-good changes).

Fallback: overlapping hunks, thin/unannotated task list, or unseparable changes -> ONE local commit + `LOG.md` note (`atomic split skipped: <reason>`). The save **never fails or blocks** because of splitting.

> **Layer 3 Trigger:** On `--save`, read `references/save-procedure.md` for the split procedure, the commit-type mapping, Last Session block shapes, the LOG.md Trim Rule procedure, and the per-file sync table.

### Retro Rule (improve the agent's environment, not the code)

At `--save`, look back over the run for things that made *the agent* slower or wronger, in seven categories ordered by severity: **navigation** (a file was hard to find -> add a Navigation-map pointer in `architecture.md`); **automated checks** (a lint/type/test could have caught this mistake -> propose it); **coding standards** (the reviewer needs a new rule in `code-standards.md`); **AGENTS.md bloat** (steering that belongs in standards or checks); **tool economy** (expensive or token-wasteful tool calls); **no-ops** (steering lines that changed no behaviour); **information access** (a fact the agent could not reach). Each finding becomes one `retro: <category> — <one line>` item in `BACKLOG.md`; a clean run writes nothing. Principle: the review step enforces standards, because the implementing agent carries all the context pressure.

### Save Bridge Rule

Users who keep a personal journal or a second memory system outside the repo (a topic diary, a notes vault) otherwise copy every save by hand. If `user-preferences.md` carries a `## Save Bridge` block with `diary_path: <absolute path>`, `--save` appends **one** block to that file after the commits land:

```
## <YYYY-MM-DD HH:MM> — <project name> — safe-code save
- plain: <the LOG.md plain: recap, verbatim>
- commits: <hash type: subject>, …
- next: <ACTIVE.md next_action>
```

Constraints: no `diary_path` (or `-`) -> print nothing; append only; the file must already exist (`diary_path` set but file absent -> `Save bridge: skipped (file not found)`, never create it); never read its content; never include secrets, `current-issues.md` content, or raw output; the bridge file is never committed and never part of the Six-File rule. This is the only write outside the project root safe-code ever makes, and only because the user declared the path (Scope Rule exception).

### Six-File Save Rule

Every `/safe-code --save` MUST update all six session files in `.safe-code/` — no exceptions, no "nothing changed" skips:

| File | Always written on save |
|---|---|
| `ACTIVE.md` | Last Session block, pending list, `next_action` |
| `SESSION.md` | Wiped to clean carry-forward template with fresh date stamp |
| `LOG.md` | One new typed entry added newest-at-top (even a short `verify`/`decision` entry), each carrying a `plain:` one-line recap a non-coder can read |
| `BACKLOG.md` | Drafted items applied; otherwise refresh the `_<DATE>_` stamp |
| `MEMORY.md` | Drafted notes applied; otherwise refresh the `_<DATE>_` stamp |
| `safe-refactor-code.md` | Flagged candidates + Graveyard entries (with real commit hashes) applied; otherwise refresh the `_<DATE>_` stamp |

If a file has no new content this session, still refresh its date stamp so all six files provably reflect the last save — but a stamp never covers an unfilled template placeholder (fill, delete, or convert to an Open Question first; see First-Run Population). A save that leaves any of the six files untouched is an incomplete save — verify all six are in the commit diff before reporting done.

### Draft-Until-Save Rule

During normal work, draft updates to `.safe-code/context/*.md`, `AGENTS.md`, `.safe-code/CHANGELOG.md`, and continuity docs in `SESSION.md`. Apply final persistent doc/context updates on `/safe-code --save`.

Exceptions:

- Create missing scaffold files/folders needed for safe operation.
- Add `/.safe-code/context/current-issues.md` and `/.safe-code/backups/` to `.gitignore` during setup.
- **First-Run Population** (see Step 1): on the first `/safe-code` run, populate empty scaffold `AGENTS.md` + evidence-derivable context files immediately, so agents have real context without waiting for `--save`.
- Append/update issue entries in `.safe-code/context/current-issues.md` on error triggers (see the Issue Tracking Rule). This file is local-only/gitignored, so it is never part of a commit.
- Write a feature spec (including a `status: suggested` idea) before implementation, or whenever a new feature is proposed (see the Feature Suggestion Rule).
- Update code files as required by the user task.

---

## Command: `/safe-code --explain`

Read the project brain back to the user in plain language. **Read-only: make no edits, no commits, no save, and run no hygiene pass.** This is for a non-technical user who wants to remember what their own project does.

Behavior:

1. If `.safe-code/context/` is missing or empty -> say there is no project brain yet and suggest running `/safe-code` first, then stop.
2. Otherwise load `project-overview.md`, `architecture.md`, and `progress-tracker.md`, and brief the user in plain language — no jargon dumps, no raw file contents:

```
What it does:   <one or two sentences, and who it's for>
Built with:     <stack in plain terms>
Where it's at:  <current phase / what works now>
In progress:    <current goal / next up>
Open questions: <unknowns from progress-tracker, if any>
```

3. If the brain conflicts with executable repo evidence, trust the repo and say so briefly.

Do not load Layer 3, run helpers, audit, or touch git. `--explain` answers a question; it never changes the repo.

---

## Command: `/safe-code --graphify`

Build or query a project knowledge graph via the external graphify pipeline (Graphify-Labs/graphify). It is an **optional accelerator** — every path must degrade to "unavailable, continue without"; never a hard dependency, never a silent install.

- **Build mode** (`--graphify`, no argument): run the pipeline on the project root, then harvest results into the brain (draft-until-save): god nodes + communities -> `architecture.md` Navigation map refresh; surprising connections + suggested questions -> `progress-tracker.md` Open Questions candidates; graph stats -> the Step 8 `Graph:` line; god-node list -> Context Self-Test seed questions.
- **Query mode** (`--graphify "<question>"`): read-only like `--explain` — run the query, relay the answer in plain language, change nothing, commit nothing. The agent may use graphify's `path`/`explain` subcommands internally; the user surface stays this one form. No graph built yet -> say so and offer build mode.

Detection order (first hit wins): `$graphify` skill available on host (verify its description matches the knowledge-graph purpose, not just the name) -> dispatch it as a helper · `graphify` CLI on PATH -> health-check it once per session (detect the OS, count copies on PATH, read the version, compare with PyPI when online; report one `Graphify:` line and print an OS- and installer-matched upgrade/cleanup command for the user — never install, upgrade, or uninstall anything yourself), then drive the CLI · `uv` available -> ask ONCE before installing (a PyPI package is a supply-chain decision; record accept/decline in `user-preferences.md`; cannot ask this session -> treat as declined for this run only, record nothing) · none -> record `Graphify: unavailable`, suggest `uv tool install graphifyy`, continue.

Safety: `graphify-out/` lives inside the project root, gitignored via its own `.gitignore` (same pattern as `.code-review-graph/`), never committed by `--save`. Exclude `.safe-code/context/current-issues.md` from the corpus (may hold secrets). Neither mode pushes or commits.

**Auto-refresh (once a graph exists):** the first build is always the user's explicit call, but after `graphify-out/graph.json` exists, every `/safe-code` and `--continue` run keeps it fresh automatically — when the Context Freshness Check detects drift, run the incremental refresh (`graphify update .` on the CLI path; the `$graphify` skill's update mode otherwise). It is deterministic and LLM-free, so it costs seconds; failure -> record `Graphify: stale (refresh failed)` and continue — auto-refresh never blocks a run and never triggers an install.

> **Layer 3 Trigger:** On any `--graphify` invocation, read `references/graph-integration.md` (Graphify Pipeline) for the CLI call sequence, harvest mapping, and gitignore block.

---

## Measure Twice, Cut Once Policy

Before every action, reason explicitly. Do not guess. Do not skip this. Every run must maintain a visible task checklist in `SESSION.md` — the checklist is the working plan and progress tracker.

HARD RULE: every file the run leaves behind is one a task claims and a later agent needs — the codebase stays clean and organised at all times.

Rules:

- Create or refresh `SESSION.md ## Task List` before Step 3.
- Every meaningful task starts as `[ ]`.
- Mark a task `[~]` while actively working on it.
- Mark a task `[x]` only after the action and its verification are complete.
- Add newly discovered work as a new task instead of doing it invisibly.
- Draft unrelated or deferred tasks for `BACKLOG.md` in `SESSION.md`; do not hide them in prose.
- On `/safe-code --save`, migrate unfinished checklist items into `ACTIVE.md Last Session.pending` and `next_action`.
- Do not claim completion unless the checklist, verification output, and final summary agree.
- If verification fails, keep the task `[~]` or `[ ]`, add the failure note, and route to `$debug-issue` when appropriate.
- When marking a task `[x]`, annotate it with the paths it touched and its commit type, so `/safe-code --save` can map each task to one atomic commit (Atomic Commit Split Rule). Record paths while the info is fresh; never reconstruct at save time. A missing annotation is a thin task list — the split falls back to a single commit.

- Every meaningful task carries its closing check **before** the work starts: `check: <command> · expect: <success-only token>`. It passes only when the command exits 0 **and** the token appears; a nonzero exit never passes because its error text happens to contain the token. No runnable check -> `check: manual · evidence: <the artifact, path, line, or measurement that will prove it>` — a description of work done is not evidence, and ambiguous evidence keeps the task `[~]`. Review manual tasks by consequence, not visibility: the riskiest item in a run is often the one nothing can check.
- A check is weak when it names an activity ("run the tests") instead of an outcome ("suite X green, N tests"); when its `expect:` token also appears in failure output (`error`, `done`, `finished`); when it asserts a number the command was handed instead of one it computed; or when it cannot fail for any state of the repo. Rewrite the annotation before starting the task.
- **Abandon, never drop.** A task that turns out impossible or out of reach stays in the list as `- [!] <task> · abandoned: <reason + who must decide>`. Abandonment is an honest ending, not completion: the Step 8 banner carries an `Abandoned:` line, `--save` copies each one into `ACTIVE.md pending`, and a run with an abandoned task is never reported as complete or clean.

Task annotation format:

```md
- [ ] remove unused dateUtil  · check: rg -n "dateUtil" src · expect: 0 matches (control: rg "formatDate" -> hits)
- [x] remove unused dateUtil  · type: refactor · files: src/utils/dateUtil.ts · closed by: observed (rg 0 matches, control hit)
- [!] migrate legacy auth     · abandoned: needs the user's decision on session store (Redis vs DB)
```

Default checklist:

```md
## Task List
- [ ] Locate project root and `.safe-code/` folder
- [ ] Initialize or reconcile AGENTS.md, context, and session docs
- [ ] Detect saved state or legacy layout migration need
- [ ] Load required context for this command
- [ ] Check context freshness (drift vs last_synced_commit)
- [ ] Draft or update active feature spec if needed
- [ ] Check git state and rollback safety
- [ ] Identity + account guard (Step 3e)
- [ ] Check or bootstrap graph support when useful
- [ ] Explore repo facts before context backfill
- [ ] Run context self-test after backfill (verify brain is sufficient)
- [ ] Audit dead code and stale files only when in scope
- [ ] Audit agent config trust artifacts when in scope
- [ ] Decide run profile and execution mode
- [ ] Execute scoped code changes if requested
- [ ] Review changes and test coverage
- [ ] Debug verification failures, if any
- [ ] Draft docs/context updates in SESSION.md
- [ ] Save final docs/context updates on /safe-code --save
```

### Decision Framework

1. What are the 2-3 options?
2. What does each risk or preserve?
3. Which is safest given what I know?
4. Can this be undone?
5. What am I assuming? → verify from codebase first; ask only if cannot verify

If assumption is about user intent (not a technical fact) → verify from codebase first.
If assumption cannot be verified from codebase → stop and ask.

If (4) = no → stop, show options to user before acting.
If (4) = yes → proceed with safest option, log reasoning.

### Act Autonomously When
- Action is reversible (git tracked)
- Confidence is High (zero references, no dynamic risk)
- Decision is technical, not about user intent
- Answer is discoverable from the codebase

### Stop and Ask When
- Action is irreversible (no git, no backup)
- Confidence is Low
- Unexpected scope change (blast radius > 10 files)

**Never ask about Medium confidence candidates** — apply auto-promotion rule instead.

### Reasoning Format

```
Reasoning:
  Options: <list>
  Risk: <list>
  Decision: <chosen>
  Why: <one sentence>
  Reversible: yes/no
  Assumptions: <list — or "none">
```

Steps 3–5 emit this same block with step-specific fields (listed at each step); do not invent a new shape. Full block vs one-liner is governed by the Proportional Ceremony Rule below.

### Proportional Ceremony Rule

Ceremony must scale to run size — a routine resume in a small repo must not read like an audit report. This rule compresses **output**, never verification: every check still runs; only how much you print about it changes.

- **Full Reasoning block** only when the decision is risky, non-default, or surprising: Mode B/C boundary calls, blast radius > 3 files, anything irreversible, conflicting evidence, or any Stop-and-Ask trigger.
- **One-liner otherwise**: `Reasoning: <decision> — <why> (reversible: yes)`. Steps 3c, 3e, 3f, 4b, and 5 accept this compact form; their step-specific fields are the menu of what to *consider*, not mandatory output.
- **Final summary (Step 8)**: on Orientation and routine-resume runs, omit banner lines whose value is `none`, `skipped: not in scope`, or `not needed`. Always keep the header, mode/profile, git/save/commits lines, and the task-list line.
- **Task annotations** stay mandatory when code changed (the Atomic Commit Split depends on them); on runs that touch no file outside `.safe-code/` a bare `[x]` is fine — the split has nothing else to map. (A run that wrote `.mcp.json`, a bridge, or `.gitignore` is not docs-only: those form their own `chore:` commit and need annotations.)

---

## Step 0: Locate Project Root

Session state lives in a single agent-agnostic folder at the project root:

```
safe-code folder = <project-root>/.safe-code/
```

No agent detection is needed. Codex, Claude, Cursor, and Windsurf all share the same `.safe-code/` folder so continuity belongs to the project, not the tool. Create `<project-root>/.safe-code/` if it does not exist.

HARD RULE: never create `.codex/`, `.claude/`, `.cursor/`, `.windsurf/`, or `.agents/` folders **for session state**. If any of them exist with safe-code docs inside, run Legacy Layout Migration (Step 1) — migrate their content into `.safe-code/` and remove them. Exception: the Provider Bridge (Step 1) may write a thin read-pointer in a host's native config location (e.g. `.cursor/rules/safe-code.mdc`, `.github/copilot-instructions.md`); these hold no state, only a redirect to `AGENTS.md`/`.safe-code/`, and are never treated as legacy.

---

## Step 1: Initialize Doc Structure

Create only the scaffold needed for safe operation before reading the codebase. Do not populate long-term context with guesses.

Create missing folders/files:

```
AGENTS.md
<current host's bridge only — CLAUDE.md | GEMINI.md | .github/copilot-instructions.md
 | .cursor/rules/safe-code.mdc — see Provider Bridge below; pointer, not state>
.safe-code/CHANGELOG.md
.safe-code/context/
.safe-code/context/project-overview.md
.safe-code/context/architecture.md
.safe-code/context/user-preferences.md
.safe-code/context/code-standards.md
.safe-code/context/ai-workflow-rules.md
.safe-code/context/ui-context.md
.safe-code/context/progress-tracker.md
.safe-code/context/current-issues.md
.safe-code/context/feature-specs/
.safe-code/context/feature-specs/00-template.md
.safe-code/ACTIVE.md
.safe-code/SESSION.md
.safe-code/LOG.md
.safe-code/BACKLOG.md
.safe-code/MEMORY.md
.safe-code/safe-refactor-code.md
```

Rules:

- Create missing files with templates only (Safety Invariants).
- Add `/.safe-code/context/current-issues.md` to `.gitignore` if absent; the agent only appends issue entries there on error triggers (Issue Tracking Rule).
- For project facts, inspect repo evidence first.
- On the **first run** (empty scaffold), populate evidence-derivable context files immediately (First-Run Population below). On later runs, draft updates in `SESSION.md` and apply on `/safe-code --save` unless a scaffold file or active feature spec is required now.

### Existing Project Backfill

If the repo already has code, docs, manifests, routes, schemas, tests, or configs: treat the repo as source of truth; backfill `.safe-code/context/*.md` from evidence only; put unverifiable facts into `progress-tracker.md` Open Questions; generate feature specs for upcoming work, active bugs, refactors, or missing documentation units (new ideas as `status: suggested`, Feature Suggestion Rule); never create fake historical specs for completed features unless the user asks.

### First-Run Population

The whole point of the first run is that any agent can read real context afterward and not hallucinate. So on the **first** `/safe-code` run — while the target file is still an empty scaffold — write evidence-derivable context immediately instead of waiting for `--save`: `AGENTS.md`, `project-overview.md`, `architecture.md` (incl. the Navigation map), `code-standards.md`, and `progress-tracker.md` (Current Phase + Open Questions). Conversation-derived files (`user-preferences.md`), `ui-context.md`, and `current-issues.md` stay template. The exception applies only while a file is an empty scaffold — once it holds real content, edits revert to Draft-Until-Save. Never invent facts: anything not provable from repo evidence is an Open Question, not a populated claim. **No placeholder survives a `--save`**: an unfilled scaffold section (`<!-- Example -->`, `[Will learn…]`, `<TBD>`) is either populated from evidence, deleted, or converted into an Open Question in `progress-tracker.md` — a date-stamp refresh over an unfilled placeholder is not a save, it is placeholder rot with a fresh coat of paint. After populating, run the **Context Self-Test**; fill or flag any gaps it finds.

> **Layer 3 Trigger:** On a first run (or whenever the Context Self-Test triggers), read `references/first-run.md` for the per-file population table and the self-test procedure.

### Provider Bridge

`AGENTS.md` + `.safe-code/` are the source of truth, but not every host auto-reads `AGENTS.md`, so safe-code writes a thin **pointer** file in the host's native config location (Claude Code `CLAUDE.md`, Cline, Gemini CLI, GitHub Copilot, Cursor; most other hosts read `AGENTS.md` natively). Write only the bridge for the host you are running in — others accrue lazily; host undetectable -> write the CLAUDE.md/GEMINI.md/Copilot/Cursor four. Bridges are pointers, not state (never duplicate project facts), are scaffold files (write immediately, preserve during Legacy Layout Migration), and are appended as a `<!-- safe-code:bridge -->` block when a host file already exists (Safety Invariants).

> **Layer 3 Trigger:** Read `references/doc-templates.md` (Provider Bridge Files) for the host table, the bridge shapes, and the full host-coverage list.

### Save-Reminder Hook Offer (opt-in, Claude Code only)

On a first run under Claude Code, when project-local `.claude/settings.json` has no safe-code Stop hook, offer ONCE: install a reminder hook that prints a nudge whenever a session ends with unsaved `.safe-code/` work. It only reminds — never commits, saves, or blocks. If accepted, merge the Stop block (shape in `references/doc-templates.md`, Save-Reminder Hook) into project-local `.claude/settings.json`, preserving existing hooks; if a clean merge is not possible, print the block for the user to paste. If declined, draft the decline into `user-preferences.md` and never re-offer. If no answer can be obtained this session (autonomous/non-interactive run), defer the offer without recording a decline — it may be offered again later. Never touch `~/.claude/` (Scope Rule).

### Legacy Layout Migration

Older versions used pre-v3 per-tool `agents/`+`memory/` folders (`.codex/`, `.claude/`, `.cursor/`, `.windsurf/`) and the v3 `.agents/` + root `context/` + root `CHANGELOG.md`. Detect on **every** command and migrate immediately (a scaffold operation, not draft-until-save): move every safe-code `*.md` into `.safe-code/` (`git mv` when tracked), patch old config paths (`.gitignore`, `AGENTS.md` Read First, other safe-code-written docs), remove each legacy folder once empty, log it all as ONE typed `decision` entry in `LOG.md`. Hard rules: Safety Invariants on destination files (keep the legacy file, report the conflict); never remove a folder still holding unmigrated or non-safe-code files; content rewrites are drafted in `SESSION.md` and applied on `--save`, uncertain facts marked as Open Questions.

> **Layer 3 Trigger:** When any legacy layout is detected, read `references/legacy-migration.md` for the full detection list, per-location steps, config patch targets, and content mapping.

### Doc + Session Templates (loaded on demand)

Do not inline template bodies here. When creating or reconciling scaffold files in Step 1, read the fallback shapes from the skill's `references/` folder and apply them only to missing files:

- `references/agents-md-authoring.md` — `AGENTS.md` template **and** the canonical AGENTS.md authoring rules. This is the single source of truth for how to write `AGENTS.md`; helper skills defer to it when run under safe-code.
- `references/doc-t

…(truncated)
