@sassywares/skills 0.5.2 → 0.5.3
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 +14 -8
- package/package.json +1 -1
- package/skills/sassy-babysit/SKILL.md +5 -3
- package/skills/sassy-commit-push-pr/SKILL.md +4 -2
- package/skills/sassy-setup/assets/sassywares-readme.md +1 -1
- package/skills/sassy-setup/references/config.md +9 -5
- package/skills/sassy-setup/scripts/detect.sh +6 -1
- package/skills/sassy-ship/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -133,8 +133,11 @@ knowledge:
|
|
|
133
133
|
write: true # false = this project takes no learnings
|
|
134
134
|
git:
|
|
135
135
|
repo: origin # a remote name | workspace (repos below, none here) | none (no git)
|
|
136
|
-
#
|
|
137
|
-
|
|
136
|
+
base_map: # head branch -> the base it targets
|
|
137
|
+
"*": staging # ordinary work branches from and targets staging
|
|
138
|
+
staging: main # staging releases to main
|
|
139
|
+
# remote: owner/backup # workspace only: the snapshot mirror
|
|
140
|
+
# mirror_branch: main # workspace only: the mirror's branch
|
|
138
141
|
repos: # workspace only: each nested repo -> the base its PRs target
|
|
139
142
|
fe: dev
|
|
140
143
|
commit:
|
|
@@ -143,17 +146,20 @@ pr:
|
|
|
143
146
|
babysit: true
|
|
144
147
|
merge: false # true authorizes merging every babysat PR here
|
|
145
148
|
delete_branch: false
|
|
146
|
-
hooks:
|
|
149
|
+
hooks:
|
|
147
150
|
pr:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
"*": # keyed by the PR's HEAD branch
|
|
152
|
+
before_create: [tap2-version mode:auto] # after the commit, before the PR opens
|
|
153
|
+
after_create: [] # the moment the PR exists
|
|
154
|
+
before_merge: [] # this run is about to merge
|
|
155
|
+
after_merge: [] # this run observed the merge
|
|
156
|
+
staging: # a per-point override for one head
|
|
157
|
+
before_create: []
|
|
152
158
|
```
|
|
153
159
|
|
|
154
160
|
### Extending the pipeline
|
|
155
161
|
|
|
156
|
-
A project adds its own steps by naming a skill that lives in its own `.agents/skills/`. Nothing declared means nothing runs.
|
|
162
|
+
A project adds its own steps by naming a skill that lives in its own `.agents/skills/`. Nothing declared means nothing runs. Keys are the **head** branch — the one a PR comes from — and every point can be overridden per head; entries may carry args (`<skill> <args…>`).
|
|
157
163
|
|
|
158
164
|
| Hook | Runs | Typical use |
|
|
159
165
|
|---|---|---|
|
package/package.json
CHANGED
|
@@ -21,7 +21,9 @@ Keep an open PR moving toward merge by reacting to three streams as each arrives
|
|
|
21
21
|
|
|
22
22
|
An explicit token always beats the config.
|
|
23
23
|
|
|
24
|
-
**Config.** Resolve `.sassywares/config.yaml` (nearest, walking up) per the `sassy-setup` skill's `references/config.md`. Precedence: explicit token > session instruction > config > skill default. `pr.*` seeds `merge` and `delete_branch`;
|
|
24
|
+
**Config.** Resolve `.sassywares/config.yaml` (nearest, walking up) per the `sassy-setup` skill's `references/config.md`. Precedence: explicit token > session instruction > config > skill default. `pr.*` seeds `merge` and `delete_branch`; merge hooks come from `hooks.pr` for this run's head.
|
|
25
|
+
|
|
26
|
+
**Keys are the head branch.** Resolve per head: the exact head, then the longest matching family (`release/*`), then `"*"`. Each point overrides independently. An entry is `<skill> <args…>` — split on the first whitespace and pass the args verbatim.
|
|
25
27
|
|
|
26
28
|
**One PR per run.** This skill watches the PR resolved from the argument or the current branch. A workspace fan-out is N runs, one per PR, and `pr.merge` never merges a fan-out — that needs an explicit say-so per PR.
|
|
27
29
|
|
|
@@ -35,7 +37,7 @@ An explicit token always beats the config.
|
|
|
35
37
|
|
|
36
38
|
Snapshot the PR state first, then act in this order:
|
|
37
39
|
|
|
38
|
-
1. **Terminal** — `MERGED`/`CLOSED` → if it is `MERGED` and `
|
|
40
|
+
1. **Terminal** — `MERGED`/`CLOSED` → if it is `MERGED` and `after_merge` resolves for this PR's head, run those hooks once (see Step 3) before stopping.
|
|
39
41
|
2. **Capture the head SHA** — a later push invalidates this snapshot's CI.
|
|
40
42
|
3. **Feedback before CI** — fetch open review threads (`gh pr view --json reviewThreads,comments`). Address each actionable thread: reply, then fix. Use `sassy-debug` for a real defect. Never wait for a reviewer who is "still reviewing" before acting on feedback already posted.
|
|
41
43
|
4. **Stale-SHA cancellation** — if the head moved since step 2, skip the CI work for this snapshot.
|
|
@@ -50,7 +52,7 @@ Stop when any holds:
|
|
|
50
52
|
- **Terminal** — merged or closed.
|
|
51
53
|
- **Looks ready** — `MERGEABLE`, `CLEAN`, all checks terminal, no open review threads, no currency blocker, zero `needs-human` items. With `merge:on`, run the merge (and `delete-branch:on` branch deletion if set) before treating this as a stop; the merge turns it into the **Terminal** stop.
|
|
52
54
|
|
|
53
|
-
**Merge hooks.** Immediately before merging,
|
|
55
|
+
**Merge hooks.** Immediately before merging, resolve `before_merge` for this PR's head and run each entry in declared order — one `worker` per hook, with the same brief every hook gets: plan path, changed files, artifact paths, base, branch, commit hash, and the PR URL plus head SHA. These run before the merge, so they must leave the tree clean. A missing skill or a `blocked` result means **do not merge**: report it and stop at Blocked. After a successful merge, resolve `after_merge` for this PR's head and run each entry the same way; these follow the merge, so they must leave the tree clean. In a workspace fan-out, everything is per PR.
|
|
54
56
|
|
|
55
57
|
**Which merge hook fires.** `before_merge` needs a merge this run will perform. `after_merge` fires whenever this run observes the PR merged, including one that was already merged when the run started — so it must be idempotent.
|
|
56
58
|
|
|
@@ -16,7 +16,9 @@ disable-model-invocation: true
|
|
|
16
16
|
|
|
17
17
|
**Options.** `branch:new|current` selects the branch policy below. `babysit:on|off` (default `on`) controls the closing babysit. `checkpoint` bounds that babysit to a single tick. `merge:on|off` and `delete-branch:on|off` (both default `off`) are forwarded unchanged to `sassy-babysit`.
|
|
18
18
|
|
|
19
|
-
**Config.** Resolve `.sassywares/config.yaml` (nearest, walking up) per the `sassy-setup` skill's `references/config.md`. Precedence: explicit token > session instruction > config > skill default. `commit.branch` seeds the branch policy, `pr.*` seeds the babysit options, and `hooks.pr
|
|
19
|
+
**Config.** Resolve `.sassywares/config.yaml` (nearest, walking up) per the `sassy-setup` skill's `references/config.md`. Precedence: explicit token > session instruction > config > skill default. `commit.branch` seeds the branch policy, `pr.*` seeds the babysit options, and `hooks.pr` supplies the `before_create` / `after_create` steps for this run's head.
|
|
20
|
+
|
|
21
|
+
**Keys are the head branch.** Resolve per head: the exact head, then the longest matching family (`release/*`), then `"*"`. Each point overrides independently. An entry is `<skill> <args…>` — split on the first whitespace and pass the args verbatim.
|
|
20
22
|
|
|
21
23
|
## Context
|
|
22
24
|
|
|
@@ -44,7 +46,7 @@ Only an exit-0 empty list means "no open PR". A non-zero exit means **unknown**
|
|
|
44
46
|
## Steps
|
|
45
47
|
|
|
46
48
|
1. **Commit** — follow `sassy-commit` with the branch choice from the policy above (named files only, outcome-stating message). Honor an `exclude:<paths>` token if present.
|
|
47
|
-
2. **`before_create` hooks.**
|
|
49
|
+
2. **`before_create` hooks.** Resolve `before_create` for the head branch (`base_map` decides the base, the head is the branch you are on); empty means skip. Split each entry on the first whitespace — the first token is the skill, the rest are its args. Run each name in declared order, one `worker` per hook, whose task is *read `<repo>/.agents/skills/<name>/SKILL.md` and follow it* plus a brief: plan path, changed files, artifact paths, base, branch, and the commit hash. This point runs **after** the commit, so a hook may write and commit its own artifacts — push whatever ends up on the branch. A missing skill or a `blocked` result stops the run and names the hook; a `needs-decision` result comes back to you to present.
|
|
48
50
|
3. **Pre-push gate** — resolve any pre-push or review-ready requirement from the project's active instructions. Only evidence valid for the exact commit being sent satisfies it; otherwise stop and report what is missing. If none, proceed.
|
|
49
51
|
4. **Push** — `git push -u origin <branch>` for a new branch, else `git push`. Re-verify branch and remote first, and re-check that the branch is ahead of origin after any hook commits.
|
|
50
52
|
5. **Compose the PR title and body**
|
|
@@ -31,4 +31,4 @@ If a skill tells you another skill is missing, run `skills:sync` and restart. Su
|
|
|
31
31
|
|
|
32
32
|
## Hooks
|
|
33
33
|
|
|
34
|
-
`hooks.pr
|
|
34
|
+
`hooks.pr` names project skills that run inside the PR pipeline, keyed by the PR's **head** branch: `"*"` for every PR, an exact branch, or a family such as `release/*`, overriding per point (`before_create`, `after_create`, `before_merge`, `after_merge`). An entry is `<skill> <args…>`; the args mean whatever that skill says they mean — `mode:auto` pre-authorizes the step. Hooks are ordinary skills in `.agents/skills/`, which makes them **code**: review them like code, and never point a hook at a copy of a suite skill.
|
|
@@ -157,8 +157,9 @@ feature/x --base_map["*"]--> staging --base_map[staging]--> main
|
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
1. `base_map[<head>]` — the exact rung
|
|
160
|
-
2. `
|
|
161
|
-
3.
|
|
160
|
+
2. the longest matching family key (`release/*`) — a nested rung
|
|
161
|
+
3. `base_map["*"]` — ordinary work
|
|
162
|
+
4. stop and ask; never guess
|
|
162
163
|
|
|
163
164
|
A rung is a release edge: standing on `staging`, a PR targets `main` without
|
|
164
165
|
anyone passing `base:main`. Add a rung for any branch that releases elsewhere; a
|
|
@@ -169,6 +170,9 @@ The probed remote default is only useful as a hint for `"*"`: it tells you where
|
|
|
169
170
|
the repository considers work to land, not what every branch targets. Confirm it
|
|
170
171
|
before writing.
|
|
171
172
|
|
|
173
|
+
`--head <branch>` prints the resolution for one head: the base (repo topology)
|
|
174
|
+
and all four hook points. Use it instead of merging maps by hand.
|
|
175
|
+
|
|
172
176
|
In a `workspace`, `base_map` does not apply — there are no branches at the
|
|
173
177
|
workspace level. Nested repos carry their own bases in `repos`, and a nested repo
|
|
174
178
|
that needs a ladder gets its own `.sassywares/config.yaml` rather than a nested
|
|
@@ -230,9 +234,9 @@ Per point, independently:
|
|
|
230
234
|
3. `"*"`
|
|
231
235
|
|
|
232
236
|
The first rule that declares a value for that point wins and the rest are not
|
|
233
|
-
merged
|
|
234
|
-
`after_merge` from `"*"`.
|
|
235
|
-
|
|
237
|
+
merged, so a `staging` entry that sets only `before_create` still inherits
|
|
238
|
+
`after_merge` from `"*"`. When two families match one head, the longer prefix
|
|
239
|
+
wins — `release/v2/*` beats `release/*`.
|
|
236
240
|
|
|
237
241
|
### Entries carry arguments
|
|
238
242
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#
|
|
7
7
|
# Usage:
|
|
8
8
|
# detect.sh [--root DIR] print a proposed config to stdout
|
|
9
|
+
# detect.sh [--head BRANCH] resolve the base and hooks for one head
|
|
9
10
|
# detect.sh [--root DIR] --check compare the existing config to reality
|
|
10
11
|
set -euo pipefail
|
|
11
12
|
|
|
@@ -290,6 +291,9 @@ if (( CHECK )); then
|
|
|
290
291
|
fi
|
|
291
292
|
|
|
292
293
|
if [[ "$TOPOLOGY" == "repo" ]]; then
|
|
294
|
+
if [[ -n "$(yflat "git${US}remote")" ]]; then
|
|
295
|
+
bad "git.remote is workspace-only — a repo config names its remote in git.repo"
|
|
296
|
+
fi
|
|
293
297
|
if [[ -z "$(yflat "git${US}base_map${US}*")" ]]; then
|
|
294
298
|
bad "git.base_map has no \"*\" entry — it is the base for ordinary work"
|
|
295
299
|
else
|
|
@@ -454,7 +458,8 @@ EOF
|
|
|
454
458
|
else
|
|
455
459
|
printf ' "*": %s # base for ordinary work; never guessed\n' "<confirm by hand>"
|
|
456
460
|
fi
|
|
457
|
-
printf ' # staging: main
|
|
461
|
+
printf ' # staging: main # uncomment when a branch releases somewhere else\n'
|
|
462
|
+
printf ' # release/*: main # a family of heads, longest prefix wins\n'
|
|
458
463
|
cat <<'EOF'
|
|
459
464
|
|
|
460
465
|
# workspace only: each nested repo folder -> the base its PRs target
|
|
@@ -22,7 +22,7 @@ disable-model-invocation: true
|
|
|
22
22
|
|
|
23
23
|
## Steps (in order)
|
|
24
24
|
|
|
25
|
-
1. **Review gate.** In `mode:manual` only: present a compact shipping summary — the plan or topic, the changes from the cycle results, the docs the close-out expects to write, the branch/PR target, the babysit options, and **the hooks this run
|
|
25
|
+
1. **Review gate.** In `mode:manual` only: present a compact shipping summary — the plan or topic, the changes from the cycle results, the docs the close-out expects to write, the branch/PR target, the babysit options, and **the hooks resolved for this run's head — point, skill, and args — or that none are declared** — and wait. In `mode:auto`, skip this gate.
|
|
26
26
|
2. **Compound (conditional).** If the work produced a qualifying learning, dispatch a `worker` whose task is: *load the `sassy-compound` skill and follow it with `mode:auto`* — with a compact learnings brief (the solved problems, root causes, and solutions taken from the cycle results, not from re-reading the tree). It always gets `mode:auto` because ship's own gate already covered the approval. Skip cleanly when nothing qualifies, and skip entirely when `knowledge.write` is `false`.
|
|
27
27
|
3. **Handbook (conditional).** If the feature is self-contained and independent enough that a teammate would benefit from a handover, dispatch a `worker` whose task is: *load the `sassy-handbook` skill and follow it* — with the plan path and topic. The worker reads the tree itself. Skip for small or tightly-coupled changes.
|
|
28
28
|
4. **Commit or snapshot.** After the review gate — never before it — the docs and any remaining code become durable.
|