--- name: isurus-conventions description: Use when working in the Isurus repository (or any repo identified as Isurus by the presence of `Isurus` in `README.md` or `cmd/isurus/`). Encodes Isurus-specific Mercurial conventions: non-publishing repo, bookmarks-as-PRs, commit message style, pre-PR Makefile checklist, opening PRs in the Isurus web UI. --- # Isurus conventions (Mercurial overlay) ## When this applies Use when working in the Isurus repository. Detect Isurus by: - Repo root contains `cmd/isurus/`, or - Top-level `README.md` contains the word `Isurus`, or - Repo is cloned from `ssh://hg@hg.leafscale.com/leafscale/isurus`. This skill is **purely additive**. The procedures live in `mercurial-basics`, `mercurial-bookmarks-and-prs`, `mercurial-sync-and-merge`, `mercurial-history-rewriting`, and `mercurial-finishing-a-branch`. This file supplies Isurus-specific values those procedures plug into. ## Repository facts | Fact | Value | |---|---| | VCS | Mercurial 7.x (never git) | | Clone URL | `ssh://hg@hg.leafscale.com/leafscale/isurus` | | Long-lived branches | `default`, `stable` | | Phase model | **Non-publishing** — pushed changesets stay `draft` until merged | | Feature/PR mechanism | **Bookmarks** (push with `-B `) | | Forge | Isurus (web UI at `https://hg.leafscale.com/`) | ## Commit messages in this repo - Imperative summary, **under 72 characters**. - Prefix with a category: `feat:`, `fix:`, `chore:`, `docs:`, `test:`, `refactor:`, `scripts:`, `hgignore:`. Match what `hg log` shows for recent commits if uncertain. - Body (optional) explains *why*; the diff shows *what*. - One blank line between summary and body. - **Never pass `-u`** to `hg commit` — identity is in `~/.hgrc`. ## Pre-PR check sequence Run from the repo root, in this order: ```sh make fmt # gofmt — leaves no diff if all files are formatted make vet # go vet — catches suspicious constructs make check # full test suite against PostgreSQL test DB ``` `make check` requires the `isurus-test` database on localhost: - DB name: `isurus-test` - User: `isurus-test` - Password: `isurus-test` Override with `ISURUS_TEST_DSN`. See `make test-setup` for one-time DB creation. Optional but recommended (skip if not installed): ```sh make lint # golangci-lint ``` The PR checklist from `CONTRIBUTING.md` (must all be true before opening PR): - `make check` passes - `go vet ./...` is clean - Code is formatted (`make fmt`) - New public functions have short godoc comments where non-obvious - No new `TODO`/`FIXME` markers (fix or file an issue instead) - Documentation updated if behavior or configuration changed - Commit messages explain *why* ## Pull request flow 1. `hg push -B ` to the canonical remote. 2. Open a PR in the Isurus web UI (`https://hg.leafscale.com//`). 3. Title: same as the commit message summary. 4. Description: *why* + link to related issues. 5. Reviewer feedback → `hg amend` → `hg push -B -f`. The non-publishing repo makes `-f` after amend the **expected** workflow, not a sign of trouble. ## What this overlay does NOT cover - General Mercurial commands → `mercurial-basics`. - Bookmark mechanics → `mercurial-bookmarks-and-prs`. - Pull / merge / conflicts → `mercurial-sync-and-merge`. - Amend / uncommit / phase rules → `mercurial-history-rewriting`. - The end-to-end "finish a branch" sequence → `mercurial-finishing-a-branch`. This file only changes the *values* those skills use (URLs, branch names, check commands). The procedures stay the same. --- name: mercurial-basics description: Use when working in any Mercurial repository for inspection or local commits — `hg status`, `diff`, `log`, `add`, `commit`, `parents`, `heads`, `branches`, `bookmarks`, `phase`. Triggers on any `hg ...` command or when `.hg/` is in the working directory. --- # Mercurial basics ## When this applies Use when: - The working directory contains `.hg/` (or any ancestor does). - About to run any `hg` command. - About to perform an operation that has both git and hg equivalents and the repo is hg. Do not use for: - Pulling, merging, conflict resolution → see `mercurial-sync-and-merge`. - Bookmarks and the PR workflow → see `mercurial-bookmarks-and-prs`. - Amending or rewriting history → see `mercurial-history-rewriting`. ## Identity comes from ~/.hgrc **Never pass `-u` to `hg commit`.** Identity is configured globally in `~/.hgrc`: ```ini [ui] username = Name ``` `hg commit -u "..."` is for impersonation and will create commits with the wrong author. Always: ```sh hg commit -m "your message" ``` ## Inspection commands | Need | Command | |---|---| | What changed in working dir | `hg status` | | Diff of unstaged changes | `hg diff` | | Recent commits | `hg log` (or `hg log -l 10` for limit) | | Working dir parent revision | `hg parents` | | All current heads | `hg heads` | | Named branches | `hg branches` | | Bookmarks (≈ feature branches) | `hg bookmarks` | | Phase of a revision | `hg phase -r ` | | Who wrote each line | `hg annotate ` (git users: `blame`) | ## Reading `hg log` output Default format shows changeset hash, branch (if not `default`), tag, user, date, and summary: ``` changeset: 42:a1b2c3d4e5f6 branch: myfeature tag: tip bookmark: work-in-progress user: Alice date: Mon May 02 09:00:00 2026 -0500 summary: feat: add the thing ``` For terser output: `hg log --template '{node|short} {bookmarks} {branch} {desc|firstline}\n'` ## Commit messages The Isurus convention (and a generally good rule) is: - **First line:** imperative summary, **under 72 characters**. Examples: `feat: add language stats to repo sidebar`, `fix: handle nil reviewer in PR template`, `chore: bump dependency X to v2`. - **Body (optional):** explain *why* the change is being made. The diff already shows *what*. One blank line between summary and body. - **Category prefix** (`feat:`, `fix:`, `docs:`, `chore:`, `test:`, `refactor:`) is convention in this codebase — match what `hg log` shows. Keep each commit focused. If a single change touches unrelated areas, split into separate commits. ## Adding files ```sh hg add path/to/file # explicit hg add # add all untracked files (use carefully) ``` Mercurial does not have a staging area. Files are tracked or not; commits include all changes to tracked files. To commit only some changes, use `hg commit path/to/file1 path/to/file2`. ## .hgignore syntax `.hgignore` lives at the repo root. Default syntax is `glob`: ``` syntax: glob # Build artifacts dist/ *.o # Switch syntax for a section syntax: rootglob binary-at-root-only # Switch back syntax: glob **/*.swp ``` `syntax: rootglob` matches only at the repo root (useful for binary names that must not match files in subdirectories). ## Phase awareness Every changeset has a phase: `draft`, `public`, or `secret`. The phase governs what's safe to rewrite: - **draft** — local or pushed-but-not-merged. Safe to amend, uncommit, rewrite. - **public** — published and considered immutable. - **secret** — never pushed. In a non-publishing repo (like Isurus), pushed changesets stay draft until merged into the canonical branch. This is what makes `hg amend` safe during code review. See `mercurial-history-rewriting` for the rewriting rules. To check: `hg phase -r `. To see your tip: `hg phase -r tip`. ## Common workflow examples Inspect what's changed and commit: ```sh hg status hg diff hg add new-file.go hg commit -m "feat: add new thing" ``` See recent history on a bookmark: ```sh hg log -l 5 -B my-feature ``` Diff between two revisions: ```sh hg diff -r REV1 -r REV2 ``` --- name: mercurial-bookmarks-and-prs description: Use when starting feature work, switching between in-progress work, or pushing a feature for review in a Mercurial repo. Bookmarks are the unit of feature work and the unit of pull requests in this workflow. --- # Mercurial bookmarks and pull requests ## When this applies Use when: - Starting a new feature or fix that will become a pull request. - Switching between multiple in-progress features. - About to push work for review. - A bookmark is in the wrong place and needs fixing. Do not use for: - Long-lived branches like `default`, `stable` — those are named branches, see "Bookmark vs named branch" below for the distinction. - Pulling/merging upstream changes → see `mercurial-sync-and-merge`. - Amending commits before push → see `mercurial-history-rewriting`. ## Bookmark vs named branch | | Bookmark | Named branch | |---|---|---| | Purpose | Feature/PR pointer | Long-lived line of development | | Lifetime | Days to weeks; deleted after merge | Months to years | | Examples | `add-language-stats`, `fix-nil-reviewer` | `default`, `stable`, `release-2.0` | | Moves on commit? | Yes (the active one moves) | The new commit stays on the branch | | Can be deleted? | Yes (`hg bookmark -d`) | Effectively no | **Rule of thumb:** if you'd open a PR for it, it's a bookmark. If it's a maintained release line, it's a named branch. ### When the user says "branch" Most users come to Mercurial from Git, where "branch" means a lightweight pointer that can be deleted. In Mercurial that concept is a **bookmark**, not a named branch. Map their words accordingly: - **"create a feature branch", "start a branch", "switch branches", "branch off X"** → bookmark, every time. - **"create a release branch", "branch for v2.0"** → named branch (long-lived release line). - **Ambiguous** → ask, but default to bookmark for anything PR-shaped. **Override repo precedent.** If you find existing named branches that look like feature work (e.g. an `add-language-stats` named branch alongside `default`), do *not* infer that the convention is to use named branches. That precedent is almost always a previous mistake (often by an LLM that didn't load this skill). Use a bookmark for the new work and surface the inconsistency: > "Heads up: this repo has named branches (`add-language-stats`, `fix-nil-reviewer`) that look like feature work, which is unusual — feature work in Mercurial is typically a bookmark. I'm using a bookmark for the new feature; let me know if you'd prefer to match the existing pattern." The only time existing named branches *should* steer you toward a named branch is when they are clearly long-lived release lines (`stable`, `release-1.0`, `release-2.0`). ## Starting a feature ```sh hg pull -u # sync to latest default hg bookmark my-feature # create bookmark at current rev # ... edit files ... hg add new-file.go hg commit -m "feat: add new thing" hg push -B my-feature # push the bookmark to the remote ``` After `hg commit`, the bookmark `my-feature` advances to the new changeset automatically (it's the active bookmark). ## Listing bookmarks ```sh hg bookmarks ``` Output marks the active bookmark with `*`: ``` add-language-stats 42:a1b2c3d4e5f6 * my-feature 47:b9c8d7e6f5a4 work-in-progress 39:c5d4e3f2a1b0 ``` ## Switching bookmarks ```sh hg update my-feature # switch to the bookmark and make it active ``` `hg update` checks out the changeset the bookmark points to AND activates the bookmark (so future commits move it forward). If you only want to look at a revision without activating any bookmark there: ```sh hg update -r ``` ## Pushing for review The Isurus convention (non-publishing repo + bookmarks = PRs): ```sh hg push -B my-feature ``` `-B my-feature` pushes the bookmark by name. Without `-B`, `hg push` pushes the current head's changesets but does not push the bookmark itself, which means the remote won't know to associate them with a PR. After pushing, open the PR in the Isurus web UI (or the equivalent forge UI). See `isurus-conventions` for Isurus specifics. ## Updating a PR after review feedback In a non-publishing repo, pushed changesets stay `draft` until the PR is merged. That means amending after a push is **safe**: ```sh # ... make the requested changes ... hg amend # rewrites the tip changeset in place hg push -B my-feature -f # -f because the rewrite changed the hash ``` The `-f` is required because the new amended changeset has a different hash than what's on the remote; without `-f` the push is rejected. This is the *intended* workflow — not a sign you're doing something dangerous, because the changesets are still draft. ## Deleting a bookmark after merge Once the PR is merged into `default`: ```sh hg pull -u # pull in the merged changes hg bookmark -d my-feature # delete locally hg push --delete my-feature # delete on the remote (if not already gone) ``` ## Recovering a misplaced bookmark If the bookmark is on the wrong changeset (e.g., you forgot it was active and committed something unrelated): ```sh hg bookmarks # see where it is hg bookmark my-feature -r # move it ``` The `-r` flag moves an existing bookmark to a specific revision without checking out anything. ## Common pitfalls - **Forgetting `-B` on push:** the changesets land but no bookmark = no PR association. Re-push with `hg push -B `. - **Forgetting `-f` after amend:** push is rejected with "remote has changesets you don't have." Verify it's your own amended changeset (not a real upstream change), then `-f`. - **Active bookmark surprise:** `hg update -r ` *without* a bookmark name leaves no bookmark active; subsequent commits create anonymous heads. Always activate a bookmark you intend to commit to. --- name: mercurial-finishing-a-branch description: Use when an implementation is complete and ready to be proposed as a pull request — runs the pre-PR checklist (build, vet, format, test) and walks through pushing the bookmark and opening a PR. The Mercurial counterpart to superpowers' `finishing-a-development-branch`. --- # Mercurial: finishing a development branch ## When this applies Use when: - Implementation is complete and the user is ready to propose a PR. - The user says "let's ship this" / "this is done" / "let's open a PR" in an hg repo. Do not use for: - Mid-development commits → see `mercurial-basics`. - Recovering from a bad commit → see `mercurial-history-rewriting`. ## The flow Six steps. Do them in order; do not skip. ### 1. Verify the working directory is clean ```sh hg status ``` Expected: empty output. If anything is shown: - New files you intended to include → `hg add` and amend the tip commit. - New files you didn't mean to track → add to `.hgignore` and commit that change separately. - Modified files → either amend or commit them as a separate change. Do not push with uncommitted changes lingering. ### 2. Verify you're on the right bookmark ```sh hg bookmarks ``` The active bookmark is marked with `*`. Confirm it's the feature bookmark, not e.g. an accidental commit on no bookmark. If a feature bookmark exists but isn't active: ```sh hg update ``` If commits were made without an active bookmark (anonymous head): ```sh hg bookmark -r . ``` (See `mercurial-bookmarks-and-prs` for the bookmark mechanics.) ### 3. Verify history is clean ```sh hg log -l 10 --template '{node|short} {phase} {desc|firstline}\n' ``` Look for: - All commits should be `draft` (in non-publishing repos like Isurus). - Commit messages follow the convention (imperative summary, <72 chars, "category: summary" prefix where the project uses one). - No "wip", "fix typo", "address review" debris — squash via `hg amend` / `hg uncommit`. If cleanup is needed → see `mercurial-history-rewriting`. The non-publishing repo means amend is safe even on already-pushed changesets. ### 4. Run the project's pre-PR checks Detect the project's check command: ```sh ls Makefile 2>/dev/null && grep -E '^(check|test|fmt|vet|lint):' Makefile ``` Common patterns: - **Has `Makefile` with `check` target:** `make check` (full test suite). Then run `make fmt` and `make vet` if those exist. - **Go project, no Makefile:** `go test ./...`, `go vet ./...`, `gofmt -l .` (anything output = unformatted). - **Other languages:** match the project's documented test/lint commands. For the Isurus repository specifically, see `isurus-conventions` — it documents the exact `make` targets used. If checks fail, **fix or surface** before continuing. Do not push code that fails the project's own gate. ### 5. Push the bookmark ```sh hg push -B ``` The `-B ` is critical — without it the changesets push but the remote doesn't know to associate them with a bookmark/PR. If the push is rejected because the bookmark was previously pushed and has since been amended: ```sh hg push -B -f ``` `-f` is the expected workflow in non-publishing repos after `hg amend`. See `mercurial-bookmarks-and-prs` for context. ### 6. Open the pull request In the forge web UI: 1. Navigate to the repository. 2. The forge typically shows a banner offering to open a PR for the just-pushed bookmark — click it. 3. Title the PR using the same format as the commit message summary. 4. PR description: explain *why*, link any related issues. The diff shows *what*; don't repeat it in the description. For Isurus-specific URL patterns and PR conventions → see `isurus-conventions`. ## After the PR is open When reviewer feedback comes in: - Make the requested changes locally. - `hg amend` to fold the fix into the existing changeset (in non-publishing repos). - `hg push -B -f`. - Reply to the review comments confirming the fix is pushed. When the PR is merged: - `hg pull -u` to bring the merged changes locally. - `hg bookmark -d ` to delete the local bookmark. - Optionally `hg push --delete ` if the forge doesn't auto-delete on merge. --- name: mercurial-history-rewriting description: Use when rewriting Mercurial history — amending commits, uncommitting, splitting commits, or recovering from a mistake. Critical: only safe on draft changesets, never on public ones. --- # Mercurial history rewriting ## When this applies Use when: - About to amend a commit (fix typo, add forgotten file, edit the message). - Need to uncommit / split a changeset. - Recovering from a mistaken commit. Do not use for: - Routine commits → see `mercurial-basics`. - Bookmark/PR push flow → see `mercurial-bookmarks-and-prs`. - Conflicts after merging → see `mercurial-sync-and-merge`. ## The fundamental rule: draft only **Only rewrite changesets in `draft` phase. Never rewrite `public` ones.** Check before rewriting: ```sh hg phase -r tip # or any specific revision ``` If the phase is `public`, **stop and surface the situation to the user.** Rewriting public history breaks every other clone of the repo. Mercurial will refuse by default with: `cannot amend public changesets`. In Isurus the repo is non-publishing, so pushed changesets stay `draft` until merged into the canonical branch. That makes `hg amend` safe during code review. After merge, the changesets become `public` and are off-limits. ## `hg amend` — fix the tip changeset in place The most common rewrite. Edit files, then: ```sh hg amend # fold working-dir changes into tip; keeps message hg amend -m "new message" # also rewrite the message hg amend file1 file2 # only fold those files ``` After amend, the new changeset has a different hash. If it was already pushed, you'll need `-f` next push: ```sh hg push -B my-feature -f ``` This is normal in a non-publishing repo. See `mercurial-bookmarks-and-prs` for the post-amend push pattern. ## `hg uncommit` — undo a commit, keeping changes in working dir ```sh hg uncommit # the entire tip changeset hg uncommit file1 file2 # only those files (rest stay committed) ``` Use cases: - The commit message is wrong and you want to redo it from scratch. - You committed too much and want to split. After uncommit, the files are back in the working dir as uncommitted changes. Re-commit selectively. ## Splitting a commit Goal: turn one commit into two (or more) more focused ones. ```sh hg uncommit # uncommit everything hg commit path/to/group-1 -m "feat: part 1" hg commit path/to/group-2 -m "feat: part 2" ``` If groups overlap by line within a single file, you may need to use a partial-add tool — that's beyond v1 scope. Manually patch and recommit, or use `hg commit -i` (interactive) if available. ## Recovering from a mistake ### "I committed too soon / wrong message" ```sh hg amend -m "the right message" ``` ### "I committed to the wrong bookmark" ```sh hg bookmarks # see what's where hg bookmark wrong-name -r .~1 # move the wrong bookmark back one hg bookmark right-name -r . # put the right bookmark on tip ``` ### "I committed something I shouldn't have" If only the most recent commit is wrong and changes haven't been pushed: ```sh hg uncommit # changes return to working dir # discard them (CAREFUL — destructive): hg revert --all --no-backup # discard all working-dir changes ``` ### "I want to undo the last several local commits" This is harder in vanilla Mercurial without `evolve`. Options: 1. `hg strip ` — removes a changeset and all descendants. Requires the `strip` extension (`[extensions] strip = ` in `~/.hgrc`). Destructive; backups are saved in `.hg/strip-backup/` by default. 2. Re-clone from the remote, lose local changes. In Isurus today, prefer option 1 with the strip extension. For complex multi-commit rewrites, this is exactly the case where `evolve` + `topics` would help (deferred to phase 2). ## What `hg rollback` is and isn't `hg rollback` undoes the most recent transaction (commit, pull, push). It's mostly deprecated because it operates on the *transaction*, not the changeset, and quietly loses information. **Prefer `hg amend` / `hg uncommit` / `hg strip` instead.** The repo's `[ui] rollback = false` is recommended (and is the default in modern Mercurial). ## Public-changeset attempts If an `hg amend` returns: ``` abort: cannot amend public changesets: ``` Do not use `--force` to override. Stop and surface the situation: someone (or the workflow) has marked this changeset public, which means it's been integrated. The right answer is a *new* commit on top, not a rewrite. ## A note on evolve / topics Modern Mercurial (with the `evolve` extension and `topics`) supports rich history rewriting workflows: stable obsolescence markers, topic branches, automatic descendant rebasing. Isurus does not enable these today; if it does in a future version, this skill will grow a sibling (`mercurial-evolve`) or be expanded. --- name: mercurial-sync-and-merge description: Use when pulling changes from a remote, updating to a different revision, dealing with multiple heads, or resolving merge conflicts in a Mercurial repo. --- # Mercurial sync and merge ## When this applies Use when: - Pulling changes from a remote. - Updating the working directory to a different revision. - The repo has multiple heads on the same branch. - Resolving merge conflicts. Do not use for: - Local commit hygiene → see `mercurial-basics`. - Moving or deleting bookmarks → see `mercurial-bookmarks-and-prs`. - Amending after a merge → see `mercurial-history-rewriting`. ## Pull then update ```sh hg pull # fetch new changesets, do not touch the working dir hg update # update working dir to tip of the active branch/bookmark ``` Combined: ```sh hg pull -u # pull then update in one step (most common) ``` If a pull brings in changesets that create a new head on the same branch (someone else committed in parallel), `hg update` will move to the new tip *only if* the working dir is at the previous tip. Otherwise it warns about multiple heads. ## Multiple heads A "head" is a changeset with no children on the same branch. Normal repos have one head per branch. Two parallel commits → two heads. See them: ```sh hg heads # all heads hg heads default # heads on the default branch ``` Resolution options: 1. **Merge them** — combine the two lines: ```sh hg update -r hg merge # resolve any conflicts (see below) hg commit -m "merge: combine parallel work" ``` 2. **Rebase your work onto the other head** (preferred for personal feature work): ```sh # If your work is the new head and the other is upstream: hg update -r # then for each of your local commits, replay using rebase or amend ``` Note: vanilla Mercurial without the `rebase` extension can't `hg rebase` directly. Either enable `rebase` in `~/.hgrc` (`[extensions] rebase = `) or fall back to merge. For Isurus today: merge is the safe default; rebase is not part of the v1 workflow. ## Merging two heads ```sh hg update -r # check out the changeset to merge INTO hg merge -r --tool internal:merge # bring source into the working dir # files with conflicts are listed in the output ``` **Always pass `--tool internal:merge`** when running `hg merge` from a Claude Code session. The user's `~/.hgrc` may default to `vimdiff`, `kdiff3`, or another interactive tool, none of which work in a non-TTY context — the merge will hang or error. `internal:merge` writes conflict markers (`<<<<<<<` / `=======` / `>>>>>>>`) into the file and returns control immediately, which is exactly what the resolution flow below assumes. ## Conflict resolution After `hg merge`, files in conflict are marked. Inspect them: ```sh hg resolve --list # 'U' = unresolved, 'R' = resolved ``` Edit each unresolved file. Conflict markers look like: ``` <<<<<<< local your version ======= their version >>>>>>> other ``` Remove the markers, keep the correct content, save. Then mark resolved: ```sh hg resolve --mark path/to/file ``` Or after editing all of them: ```sh hg resolve --mark --all ``` Verify nothing remains: ```sh hg resolve --list # should print nothing ``` Re-run a merge tool on a specific file (e.g., to retry): ```sh hg resolve --tool internal:merge3 path/to/file ``` ### Shortcuts when one side wins If the user explicitly picks one side ("keep ours", "take theirs") rather than wanting a hand-merge, use the appropriate `internal:` resolver — it both resolves and marks in one step, no manual editing needed: ```sh hg resolve --tool internal:local path/to/file # keep working-dir version hg resolve --tool internal:other path/to/file # take incoming version ``` Then verify with `hg resolve --list` and proceed to commit. Once all files are resolved: ```sh hg commit -m "merge: combine X and Y" ``` A merge commit has two parents. `hg log --graph` (or `hg log -G`) shows the merge visually. ## Aborting a merge If you started a merge and want to back out: ```sh hg update -C -r ``` `-C` means clean — discard the in-progress merge state. Verify the working dir is clean afterward with `hg status`. ## Common pitfalls - **`hg pull` without `-u`:** changesets are in the repo but the working dir is unchanged. You're working against stale code without realizing. - **Two parents after merge with no commit:** if you `hg merge` and then run other commands, the working dir has two parents until you `hg commit`. Until then, `hg parents` shows both. - **Conflict markers committed:** if you `hg commit` without removing all `<<<<<<<`/`=======`/`>>>>>>>` markers, you commit broken files. Always grep before commit: ```sh grep -r '<<<<<<<' . ```