@ericrisco/rsc 3.7.0 → 3.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/manifest.json +25 -2
- package/package.json +1 -1
- package/scripts/lib/default-skill-floor.js +5 -1
- package/scripts/lib/domains.js +1 -1
- package/scripts/lib/onboarding.js +12 -2
- package/skills/tidy/SKILL.md +150 -0
- package/skills/tidy/evals/README.md +23 -0
- package/skills/tidy/evals/cases.yaml +53 -0
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/@ericrisco/rsc)
|
|
10
10
|
[](https://www.npmjs.com/package/@ericrisco/rsc)
|
|
11
|
-
[](#the-catalog)
|
|
12
12
|
[](LICENSE)
|
|
13
13
|
[](https://github.com/ericrisco/rsc-harness/stargazers)
|
|
14
14
|
|
|
@@ -71,7 +71,7 @@ The decisions your agent needs should have a place to live outside the chat.
|
|
|
71
71
|
| --- | --- |
|
|
72
72
|
| **Knowledge** | A local `02-DOCS/` wiki for project context, decisions and evidence. |
|
|
73
73
|
| **Tools** | A `01-TOOLS/` convention for documenting real connections and their checks. |
|
|
74
|
-
| **Skills** | A selection from
|
|
74
|
+
| **Skills** | A selection from 274 available skills, loaded progressively when relevant. |
|
|
75
75
|
| **Controls** | Working rules and provider-specific hooks, with explicit support limits. |
|
|
76
76
|
|
|
77
77
|
The mechanism is practical: keep the decision, make it discoverable, and have the next task consult it.
|
|
@@ -501,7 +501,7 @@ price, customer testimonial, deadline or guarantee is needed to explain a useful
|
|
|
501
501
|
|
|
502
502
|
## The catalog
|
|
503
503
|
|
|
504
|
-
|
|
504
|
+
274 skills, grouped by what you are trying to do. Click any skill to read its `SKILL.md`. It fires on
|
|
505
505
|
its own when a task matches.
|
|
506
506
|
|
|
507
507
|
### 🧭 Core & control plane
|
|
@@ -513,7 +513,7 @@ its own when a task matches.
|
|
|
513
513
|
Two lanes for change: `ftd` for ordinary work, and the ten-phase chain when durable artifacts would
|
|
514
514
|
settle a real ambiguity. `idea-refinement` runs inside `specify`; `decision-challenge` is on demand.
|
|
515
515
|
|
|
516
|
-
[ftd](skills/ftd/) · [sdd](skills/sdd/) · [constitution](skills/constitution/) · [idea-refinement](skills/idea-refinement/) · [specify](skills/specify/) · [clarify](skills/clarify/) · [plan](skills/plan/) · [tasks](skills/tasks/) · [analyze](skills/analyze/) · [decision-challenge](skills/decision-challenge/) · [implement](skills/implement/) · [source-grounded-development](skills/source-grounded-development/) · [verify](skills/verify/) · [review](skills/review/) · [simplify-code](skills/simplify-code/) · [ship](skills/ship/) · [debug](skills/debug/) · [worktrees](skills/worktrees/) · [parallel](skills/parallel/)
|
|
516
|
+
[ftd](skills/ftd/) · [sdd](skills/sdd/) · [constitution](skills/constitution/) · [idea-refinement](skills/idea-refinement/) · [specify](skills/specify/) · [clarify](skills/clarify/) · [plan](skills/plan/) · [tasks](skills/tasks/) · [analyze](skills/analyze/) · [decision-challenge](skills/decision-challenge/) · [implement](skills/implement/) · [source-grounded-development](skills/source-grounded-development/) · [verify](skills/verify/) · [review](skills/review/) · [simplify-code](skills/simplify-code/) · [ship](skills/ship/) · [debug](skills/debug/) · [worktrees](skills/worktrees/) · [parallel](skills/parallel/) · [tidy](skills/tidy/)
|
|
517
517
|
|
|
518
518
|
### 💼 Run a business
|
|
519
519
|
|
package/manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.7.
|
|
2
|
+
"version": "3.7.2",
|
|
3
3
|
"counts": {
|
|
4
|
-
"skills":
|
|
4
|
+
"skills": 274,
|
|
5
5
|
"agents": 34,
|
|
6
6
|
"commands": 53,
|
|
7
7
|
"fixedCommands": 20
|
|
@@ -5056,6 +5056,29 @@
|
|
|
5056
5056
|
],
|
|
5057
5057
|
"profiles": []
|
|
5058
5058
|
},
|
|
5059
|
+
{
|
|
5060
|
+
"id": "tidy",
|
|
5061
|
+
"description": "Use when every repository in the workspace must end synced and clean: each one on its default branch, everything pushed, everything pulled, no leftover branches or worktrees. Covers the root repo and every nested repo (child projects). Fires on 'limpia el harness', 'actualiza todo', 'sincroniza todo', 'déjalo todo en main', 'sube y baja todo', 'tidy up the repos', 'sync everything'. NOT upgrading the rsc version (that is `npx @ericrisco/rsc upgrade`), NOT opening isolation for new work (that is `worktrees`), NOT landing one finished branch (that is `ship`).",
|
|
5062
|
+
"tags": [
|
|
5063
|
+
"git",
|
|
5064
|
+
"sync",
|
|
5065
|
+
"cleanup",
|
|
5066
|
+
"branches",
|
|
5067
|
+
"worktrees",
|
|
5068
|
+
"limpieza",
|
|
5069
|
+
"sincronizar",
|
|
5070
|
+
"main"
|
|
5071
|
+
],
|
|
5072
|
+
"recommends": [
|
|
5073
|
+
"worktrees",
|
|
5074
|
+
"ship"
|
|
5075
|
+
],
|
|
5076
|
+
"profiles": [
|
|
5077
|
+
"minimal",
|
|
5078
|
+
"core",
|
|
5079
|
+
"full"
|
|
5080
|
+
]
|
|
5081
|
+
},
|
|
5059
5082
|
{
|
|
5060
5083
|
"id": "tiktok-api",
|
|
5061
5084
|
"description": "Use when connecting a real TikTok account to code via the Content Posting, Display and Business Account APIs — OAuth, chunked video publish with status polling, and pulling views, watch time and impression sources, then logging that performance into the wiki as a dated feedback record. Covers short-lived tokens breaking a cron, unverified pull-from-URL ownership, and rate limits. NOT what to post or how to package it (that is `shortform-strategy` and `shortform-packaging`).",
|
package/package.json
CHANGED
|
@@ -22,7 +22,11 @@
|
|
|
22
22
|
// `ux` joined in 3.4.0: `design` decides how a screen looks, `ux` decides whether people can use it —
|
|
23
23
|
// the whole flow, every state, the browser walk. It replaced `ui-engineering`, which was core-only.
|
|
24
24
|
// Only its description is paid for on other turns; the upstream references load on demand.
|
|
25
|
-
|
|
25
|
+
//
|
|
26
|
+
// `tidy` joined in 3.8.0: "limpia el harness" / "actualiza todo" — every repo on its default branch,
|
|
27
|
+
// pushed, pulled, no landed branch or worktree left. Leftovers pile up in every workspace, not only in
|
|
28
|
+
// the ones that picked a profile with git skills, and the person asks for it in their own words.
|
|
29
|
+
export const DEFAULT_SKILL_FLOOR = Object.freeze(['orient', 'suggest', 'unslop', 'ftd', 'connect-tool', 'design', 'ux', 'tidy']);
|
|
26
30
|
|
|
27
31
|
export function withDefaultSkillFloor(skillIds = []) {
|
|
28
32
|
return [...new Set([...DEFAULT_SKILL_FLOOR, ...skillIds])];
|
package/scripts/lib/domains.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
export const DOMAINS = [
|
|
7
7
|
{ title: 'Core & control plane', ids: ['init', 'harness', 'orient', 'suggest', 'unslop', 'author-skill', 'sdd-init'] },
|
|
8
|
-
{ title: 'Spec-Driven Development', ids: ['ftd', 'sdd', 'constitution', 'idea-refinement', 'specify', 'clarify', 'plan', 'tasks', 'analyze', 'decision-challenge', 'implement', 'source-grounded-development', 'verify', 'review', 'simplify-code', 'ship', 'debug', 'worktrees', 'parallel'] },
|
|
8
|
+
{ title: 'Spec-Driven Development', ids: ['ftd', 'sdd', 'constitution', 'idea-refinement', 'specify', 'clarify', 'plan', 'tasks', 'analyze', 'decision-challenge', 'implement', 'source-grounded-development', 'verify', 'review', 'simplify-code', 'ship', 'debug', 'worktrees', 'parallel', 'tidy'] },
|
|
9
9
|
{ title: 'Run a business', ids: ['finance-ops', 'invoicing', 'bookkeeping', 'pricing', 'sales-pipeline', 'lead-gen', 'cold-outreach', 'proposals', 'contracts', 'customer-support', 'client-onboarding', 'retention', 'hiring', 'people-ops', 'inventory', 'logistics-ops', 'procurement', 'meeting-notes', 'sop-builder', 'project-ops'] },
|
|
10
10
|
{ title: 'Raise & model money', ids: ['pitch-deck', 'investor-materials', 'financial-model', 'fundraising', 'unit-economics', 'grants'] },
|
|
11
11
|
{ title: 'Legal, privacy & compliance', ids: ['gdpr-privacy', 'terms-conditions', 'compliance', 'data-policy', 'ip-trademark'] },
|
|
@@ -18,11 +18,13 @@ export const ONBOARDING_VALUES = Object.freeze({
|
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
const ignored = new Set([
|
|
21
|
-
|
|
21
|
+
// `vendor` is Composer's (and Go's/Bundler's) `node_modules`: third-party code, not the project. A
|
|
22
|
+
// Laravel app was read as Python because one vendored package shipped a `docs/requirements.txt` (#325).
|
|
23
|
+
'.git', '.rsc', 'node_modules', 'vendor', '.venv', '.next', 'dist', 'build', 'coverage', '__pycache__', '.dart_tool',
|
|
22
24
|
'.claude', '.codex', '.cursor', '.opencode', '.amp', '.jules', '.zed', '.gemini', '.antigravity',
|
|
23
25
|
'.windsurf', '.clinerules', '.roo', '.continue', '.junie', '.kiro', '.aider',
|
|
24
26
|
]);
|
|
25
|
-
const manifests = new Set(['package.json', 'pyproject.toml', 'go.mod', 'Cargo.toml', 'pubspec.yaml', 'requirements.txt']);
|
|
27
|
+
const manifests = new Set(['package.json', 'pyproject.toml', 'go.mod', 'Cargo.toml', 'pubspec.yaml', 'requirements.txt', 'composer.json']);
|
|
26
28
|
const sourceExt = new Set(['.js', '.jsx', '.ts', '.tsx', '.py', '.go', '.rs', '.dart', '.java', '.kt', '.swift', '.php', '.rb']);
|
|
27
29
|
|
|
28
30
|
const clean = (value) => String(value ?? '').trim();
|
|
@@ -152,6 +154,14 @@ export function scanProject(root = process.cwd()) {
|
|
|
152
154
|
} catch { stacks.add('node'); }
|
|
153
155
|
}
|
|
154
156
|
if (entry.name === 'pyproject.toml' || entry.name === 'requirements.txt') stacks.add('python');
|
|
157
|
+
if (entry.name === 'composer.json') {
|
|
158
|
+
stacks.add('php');
|
|
159
|
+
try {
|
|
160
|
+
const composer = JSON.parse(readFileSync(path, 'utf8'));
|
|
161
|
+
const deps = { ...(composer.require || {}), ...(composer['require-dev'] || {}) };
|
|
162
|
+
if (deps['laravel/framework']) stacks.add('laravel');
|
|
163
|
+
} catch { /* an unreadable composer.json is still PHP */ }
|
|
164
|
+
}
|
|
155
165
|
if (entry.name === 'go.mod') stacks.add('go');
|
|
156
166
|
if (entry.name === 'Cargo.toml') stacks.add('rust');
|
|
157
167
|
if (entry.name === 'pubspec.yaml') stacks.add('flutter');
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tidy
|
|
3
|
+
description: "Use when every repository in the workspace must end synced and clean: each one on its default branch, everything pushed, everything pulled, no leftover branches or worktrees. Covers the root repo and every nested repo (child projects). Fires on 'limpia el harness', 'actualiza todo', 'sincroniza todo', 'déjalo todo en main', 'sube y baja todo', 'tidy up the repos', 'sync everything'. NOT upgrading the rsc version (that is `npx @ericrisco/rsc upgrade`), NOT opening isolation for new work (that is `worktrees`), NOT landing one finished branch (that is `ship`)."
|
|
4
|
+
tags: [git, sync, cleanup, branches, worktrees, limpieza, sincronizar, main]
|
|
5
|
+
recommends: [worktrees, ship]
|
|
6
|
+
profiles: [minimal, core, full]
|
|
7
|
+
origin: risco
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# tidy — every repo on main, pushed, pulled, nothing left over
|
|
11
|
+
|
|
12
|
+
One request, every repository in the workspace. When it ends, each repo shows the same picture:
|
|
13
|
+
|
|
14
|
+
- the main checkout is on the **default branch**, up to date with the remote;
|
|
15
|
+
- **nothing local is missing from the remote** — no unpushed commit, on any branch;
|
|
16
|
+
- **no worktree and no branch whose work has already landed**, locally or on the remote.
|
|
17
|
+
|
|
18
|
+
The job is cleanup, and cleanup is where work gets lost. So the rule under every step: **delete only
|
|
19
|
+
what is proven to be in the default branch already.** Anything else is pushed, kept and reported —
|
|
20
|
+
never thrown away to make the picture look clean.
|
|
21
|
+
|
|
22
|
+
## 1. Find the repositories
|
|
23
|
+
|
|
24
|
+
The workspace root, plus every nested git repository below it (child projects keep their own git):
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git rev-parse --show-toplevel # the root repo, if any
|
|
28
|
+
find . -name .git -maxdepth 4 -not -path '*/node_modules/*' -not -path '*/.worktrees/*'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
A `.git` that is a *file* is a linked worktree or a submodule, not a repo of its own: skip it here,
|
|
32
|
+
it is handled from its parent in step 4. Name the list in one line before touching anything.
|
|
33
|
+
|
|
34
|
+
**Never change the working directory into a child repo.** Use `git -C <repo>` and absolute paths.
|
|
35
|
+
Session hooks take the cwd as the project, and a `cd` plants state inside the child.
|
|
36
|
+
|
|
37
|
+
## 2. Read everything before changing anything
|
|
38
|
+
|
|
39
|
+
Per repo, one pass, no writes except the fetch:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git -C <repo> fetch --all --prune --quiet
|
|
43
|
+
git -C <repo> symbolic-ref --short refs/remotes/origin/HEAD # the default branch (origin/main)
|
|
44
|
+
git -C <repo> status --short --branch # current branch, ahead/behind, dirty
|
|
45
|
+
git -C <repo> for-each-ref --format='%(refname:short) %(upstream:short) %(upstream:track)' refs/heads
|
|
46
|
+
git -C <repo> worktree list --porcelain
|
|
47
|
+
git -C <repo> stash list
|
|
48
|
+
gh pr list --state open --json number,headRefName 2>/dev/null # open PRs, when gh is there
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
No remote at all → the repo cannot be "pushed"; report it and only tidy what is local.
|
|
52
|
+
|
|
53
|
+
## 3. Classify every item
|
|
54
|
+
|
|
55
|
+
Each branch, worktree and remote branch lands in exactly one row. Decide by the commands, not by
|
|
56
|
+
reading names.
|
|
57
|
+
|
|
58
|
+
| Item | Proof | Action |
|
|
59
|
+
| --- | --- | --- |
|
|
60
|
+
| Worktree whose work landed | `npx @ericrisco/rsc worktrees` calls it safe | `npx @ericrisco/rsc worktrees reap` |
|
|
61
|
+
| Worktree whose directory is gone | `prunable` in the porcelain list | `git -C <repo> worktree prune` |
|
|
62
|
+
| Worktree with live or unsaved work | anything the reaper refuses | keep; report the reaper's reason |
|
|
63
|
+
| Local branch merged into the default | `merge-base --is-ancestor <b> origin/<default>` | `git branch -d <b>` |
|
|
64
|
+
| Local branch squash-merged | its content is in the default (below) | `git branch -D <b>`, tip SHA in the report |
|
|
65
|
+
| Local branch with unlanded commits | neither of the two above | push it (`git push -u origin <b>`), keep it |
|
|
66
|
+
| Remote branch whose content landed | same content check, against `origin/<b>` | delete it, after one confirmation (step 6) |
|
|
67
|
+
| Remote branch with an open PR | `gh pr list` | keep; it is live |
|
|
68
|
+
| Remote branch unlanded, no PR | not in the default, no PR | keep; report it as an open question |
|
|
69
|
+
| Stash | any | keep; report it. Never `stash drop` without a yes |
|
|
70
|
+
|
|
71
|
+
**The content check** (what makes a squash merge count as landed): merge the branch into the default
|
|
72
|
+
in memory and see whether anything changes.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git -C <repo> merge-tree --write-tree origin/<default> <branch> | head -1 # resulting tree
|
|
76
|
+
git -C <repo> rev-parse origin/<default>^{tree} # default's tree
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Same tree → the branch adds nothing; it has landed. A conflict, a different tree, or a git older
|
|
80
|
+
than 2.38 (no `--write-tree`) → **not proven**, so it is kept. A branch that never carried a commit
|
|
81
|
+
of its own is a live workspace someone just opened, not leftovers: keep it.
|
|
82
|
+
|
|
83
|
+
Never delete the default branch, the current branch of another checkout, or `rsc/knowledge`.
|
|
84
|
+
|
|
85
|
+
## 4. Act, in this order
|
|
86
|
+
|
|
87
|
+
1. **Uncommitted changes stop that repo.** Show the files and ask once: commit them, stash them, or
|
|
88
|
+
leave the repo as is. Never commit or discard someone's work in progress on your own. Another
|
|
89
|
+
session working in that checkout (the isolation notice says so) → do not touch its branch or its
|
|
90
|
+
files at all; report it.
|
|
91
|
+
2. **Push what is only local.** Every branch with unlanded commits goes to the remote. The default
|
|
92
|
+
branch ahead of `origin`: push it if the default branch is open here; if it is protected
|
|
93
|
+
(branches and PRs), move those commits to a branch and open a PR — ask first.
|
|
94
|
+
3. **Retire what landed.** `npx @ericrisco/rsc worktrees reap` for worktrees (it refuses anything
|
|
95
|
+
that would lose a file, and its refusal stands), `worktree prune`, then the branches from step 3.
|
|
96
|
+
Without rsc in that repo, follow the manual path in `../worktrees/SKILL.md`.
|
|
97
|
+
4. **Back to the default and pull.** Clean checkout on another branch whose work is pushed →
|
|
98
|
+
`git -C <repo> switch <default>`. Then `git -C <repo> pull --ff-only`. A pull that cannot
|
|
99
|
+
fast-forward means the local default diverged: stop and report, never `reset --hard`.
|
|
100
|
+
|
|
101
|
+
## 5. What is never done
|
|
102
|
+
|
|
103
|
+
- `reset --hard`, `clean -fdx`, `push --force`, `worktree remove --force`, `stash drop` or `clear` —
|
|
104
|
+
not to make the picture tidy, not on a "probably fine".
|
|
105
|
+
- Deleting a branch or worktree because its name looks old. Only the proofs in step 3 count.
|
|
106
|
+
- Committing straight to a protected default branch.
|
|
107
|
+
|
|
108
|
+
## 6. Remote branches: one confirmation, for all of them
|
|
109
|
+
|
|
110
|
+
Deleting a remote branch reaches everyone who clones the repo. Collect every remote branch whose
|
|
111
|
+
content landed, across all repos, and ask **once** with the full list:
|
|
112
|
+
|
|
113
|
+
> Remote branches already in main, to delete: `rsc-harness: feat/x, fix/y` · `rsc-brain: feat/z`.
|
|
114
|
+
> ¿Las borro? (sí/no)
|
|
115
|
+
|
|
116
|
+
On yes: `git -C <repo> push origin --delete <b> ...`. On no: keep them and say so in the report.
|
|
117
|
+
|
|
118
|
+
## 7. The report
|
|
119
|
+
|
|
120
|
+
One table, one row per repo, then the open questions. Only facts you observed in this run.
|
|
121
|
+
|
|
122
|
+
| Repo | Branch | ↑ / ↓ | Worktrees | Local branches | Remote branches | Pending |
|
|
123
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
124
|
+
| rsc-harness | main | 0 / 0 | 0 | 0 | 2 deleted | — |
|
|
125
|
+
| rsc-brain | main | 0 / 0 | 1 kept | 1 pushed | — | `feat/z`: live, no PR |
|
|
126
|
+
|
|
127
|
+
Under it: every deleted squash-merged branch with its tip SHA (it can be brought back with
|
|
128
|
+
`git branch <name> <sha>`), and every item kept with the one action that would close it. A repo that
|
|
129
|
+
is not fully clean is reported as not clean, with the reason; a tidy-looking summary that hides one
|
|
130
|
+
kept item is the failure this skill exists to prevent.
|
|
131
|
+
|
|
132
|
+
## Anti-patterns → STOP
|
|
133
|
+
|
|
134
|
+
| Rationalization | Reality / Fix |
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| "It's an old branch, nobody uses it" | Age proves nothing. Ancestor or same tree, or it stays. |
|
|
137
|
+
| "Squash-merged, so `-D` is fine without checking" | Check the tree first. A branch with one extra commit after the PR looks identical by name. |
|
|
138
|
+
| "The tree is dirty, I'll stash it to switch to main" | That is someone's work. Ask first; a stash is easy to forget for ever. |
|
|
139
|
+
| "Pull failed, I'll `reset --hard origin/main`" | That throws away local commits. Report the divergence instead. |
|
|
140
|
+
| "I'll `cd` into each child to run git" | `git -C <repo>`. A `cd` plants session state inside the child. |
|
|
141
|
+
| "I'll delete the remote branches as I go" | One list, one confirmation, at the end. |
|
|
142
|
+
| "Report says clean; the kept worktree is a detail" | Say what was kept and why. The report is the deliverable. |
|
|
143
|
+
|
|
144
|
+
**Next:** after a clean report there is nothing to hand over. Neighbours: `../worktrees/SKILL.md`
|
|
145
|
+
opens isolation for new work; `../ship/SKILL.md` lands one finished branch; `npx @ericrisco/rsc
|
|
146
|
+
upgrade` updates the harness itself, which is a different "actualiza".
|
|
147
|
+
|
|
148
|
+
## Orientación (siempre)
|
|
149
|
+
|
|
150
|
+
Habla con la voz de `orient`: frases cortas, una idea por frase, y cada respuesta se entiende sola. Registro técnico o con analogías según `technical_level` en `02-DOCS/wiki/harness/user-profile.md`. Cierra cada turno con el **bloque-brújula** (📍 dónde estás · ➡️ siguiente, terminando en pregunta; ✅ y 🧭 cuando hay algo hecho o decidido). **Nunca termines en seco.** Protocolo completo: skill `orient` → `skills/orient/references/orientation-contract.md`. (Defiere a `suggest` el "¿instalo la skill que falta?".)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Evals — tidy
|
|
2
|
+
|
|
3
|
+
The claim under test is the boundary with three neighbours that also say "update" or "clean":
|
|
4
|
+
`rsc upgrade` (the harness version), `worktrees` (opening isolation) and `ship` (landing one
|
|
5
|
+
branch). The negatives prove the split.
|
|
6
|
+
|
|
7
|
+
## Triggering
|
|
8
|
+
|
|
9
|
+
Load only `tidy` and run every prompt in 3–5 fresh sessions. A positive passes when `tidy` loads in
|
|
10
|
+
a majority of trials; a negative passes when it stays quiet. Require at least 90% accuracy, and treat
|
|
11
|
+
a trigger on "actualiza rsc a la última versión" as blocking: that one is the same verb, a
|
|
12
|
+
different job.
|
|
13
|
+
|
|
14
|
+
## Capability
|
|
15
|
+
|
|
16
|
+
Fixture: a workspace with a root repo and two child repos holding, between them, a merge-landed
|
|
17
|
+
branch, a squash-landed branch whose remote is gone, a branch with one unpushed commit, a landed
|
|
18
|
+
worktree, a worktree with an untracked `.env`, and a child checkout left on a feature branch.
|
|
19
|
+
|
|
20
|
+
Pass when, after the run: both landed branches are gone (the squash one with its SHA reported); the
|
|
21
|
+
unpushed branch exists on the remote and locally; the landed worktree is gone; the `.env` worktree is
|
|
22
|
+
still there and reported; every checkout is on `main`, 0 ahead and 0 behind; and no remote branch was
|
|
23
|
+
deleted before the single confirmation. Any lost commit or file fails the run outright.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
skill: tidy
|
|
2
|
+
|
|
3
|
+
# `tidy` owns the end-of-day sweep across every repo in the workspace: each on its default
|
|
4
|
+
# branch, pushed, pulled, no landed branch or worktree left. Upgrading rsc itself, opening
|
|
5
|
+
# isolation for new work and landing one branch belong to neighbours.
|
|
6
|
+
should_trigger:
|
|
7
|
+
- prompt: "Limpia el harness."
|
|
8
|
+
why: "The owner's own phrase for the whole sweep."
|
|
9
|
+
|
|
10
|
+
- prompt: "Actualiza todo a main en estos proyectos, que esté todo subido y sin ramas."
|
|
11
|
+
why: "Default branch, pushed, no branches: the contract in one sentence."
|
|
12
|
+
|
|
13
|
+
- prompt: "Sube y baja todo y quita los worktrees que sobren."
|
|
14
|
+
why: "Push, pull and retire leftovers across the workspace."
|
|
15
|
+
|
|
16
|
+
- prompt: "Tidy up the repos, I have branches and worktrees everywhere."
|
|
17
|
+
why: "Leftover branches and worktrees across repos, in English."
|
|
18
|
+
|
|
19
|
+
- prompt: "Déjalo todo en main y limpio antes de irme."
|
|
20
|
+
why: "End-of-session state for every repo."
|
|
21
|
+
|
|
22
|
+
- prompt: "Sync everything with GitHub and delete the merged branches."
|
|
23
|
+
why: "Push/pull plus landed-branch cleanup is this skill's whole job."
|
|
24
|
+
|
|
25
|
+
should_not_trigger:
|
|
26
|
+
- prompt: "Actualiza rsc a la última versión."
|
|
27
|
+
route_to: "suggest"
|
|
28
|
+
why: "Upgrading the harness itself is `rsc upgrade`, not a git sweep."
|
|
29
|
+
|
|
30
|
+
- prompt: "Abre un worktree para empezar la feature de pagos."
|
|
31
|
+
route_to: "worktrees"
|
|
32
|
+
why: "Opening isolation for new work is the opposite move."
|
|
33
|
+
|
|
34
|
+
- prompt: "Esta rama ya pasó review, fusiónala."
|
|
35
|
+
route_to: "ship"
|
|
36
|
+
why: "Landing one verified branch is ship."
|
|
37
|
+
|
|
38
|
+
- prompt: "Borra los ficheros temporales y el node_modules del proyecto."
|
|
39
|
+
route_to: "bash-scripting"
|
|
40
|
+
why: "Disk cleanup inside a project is not branch and remote hygiene."
|
|
41
|
+
|
|
42
|
+
capability:
|
|
43
|
+
- scenario: "User says: 'Limpia el harness.' The workspace has a root repo and two child repos. Between them: a branch merged into main, a squash-merged branch whose remote is gone, a branch with one unpushed commit, a worktree whose work landed, a worktree holding an untracked `.env`, and one child checkout left on a clean, pushed feature branch. Another child has an uncommitted edit to README.md."
|
|
44
|
+
must_include:
|
|
45
|
+
- "Lists the repos it found (root plus every nested repo) before changing anything, and runs git with `git -C <repo>` instead of changing directory into a child"
|
|
46
|
+
- "Fetches with prune and reads branches, worktrees, stashes and status for every repo before the first write"
|
|
47
|
+
- "Deletes the merged branch with `git branch -d`, and the squash-merged one only after the content check (merge-tree tree equals the default's tree), reporting its tip SHA"
|
|
48
|
+
- "Pushes the branch with the unpushed commit and keeps it, instead of deleting it"
|
|
49
|
+
- "Retires the landed worktree through `npx @ericrisco/rsc worktrees reap` and keeps the `.env` worktree, reporting the reaper's reason"
|
|
50
|
+
- "Stops on the uncommitted README.md edit and asks (commit, stash or leave) instead of stashing or discarding it on its own"
|
|
51
|
+
- "Switches the clean child checkout back to main and pulls with `--ff-only`"
|
|
52
|
+
- "Asks once, with the full list, before deleting any remote branch"
|
|
53
|
+
- "Ends with one table per repo plus the kept items and the action that would close each, and never uses reset --hard, push --force, clean -fdx or stash drop"
|