@sassywares/skills 0.5.3 → 0.5.4
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/package.json
CHANGED
|
@@ -30,7 +30,7 @@ Treat the reads as a snapshot; re-read branch and staged set right before commit
|
|
|
30
30
|
|
|
31
31
|
**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` supplies the default.
|
|
32
32
|
|
|
33
|
-
**Branch option.** `branch:current|new [<name>]`. `current` commits on the checked-out branch. `new` cuts a branch from `origin/<base>` — `<base>` is `
|
|
33
|
+
**Branch option.** `branch:current|new [<name>]`. `current` commits on the checked-out branch. `new` cuts a branch from `origin/<base>` — `<base>` is `base_map` from the repo's own config when it has one, else `repos[<dir>]` from the workspace config, else the probed base **confirmed with the user** — named `<name>` when given, else from the change. `sassy-commit-push-pr` forwards its own `branch` choice here.
|
|
34
34
|
|
|
35
35
|
**Not in a workspace root, not outside git.** With `git.repo: workspace` there is no local commit to make: refuse in one line and name the snapshot instead. With `git.repo: none`, refuse and say the project is deliberately outside git. Inside a nested repo, a normal commit is correct — the nearest work tree is the repo.
|
|
36
36
|
|
|
@@ -39,7 +39,7 @@ Only an exit-0 empty list means "no open PR". A non-zero exit means **unknown**
|
|
|
39
39
|
|
|
40
40
|
**Branch policy.** Default: if on the base branch or detached HEAD, create a feature branch named from the work and say so. `branch:current` or a plain request keeps the checked-out branch (that run pushes and skips the PR). Never ask whether to branch. Forward the resolved choice to `sassy-commit`: `branch:new <name>` when this run creates a branch, else `branch:current`.
|
|
41
41
|
|
|
42
|
-
**Base branch.** `<base>` is `
|
|
42
|
+
**Base branch.** `<base>` is `base_map[<current head>]` from the nearest config — a nested repo's own config wins over the workspace's `repos[<dir>]` — falling back to `base_map["*"]`, else the probed remote HEAD **confirmed with the user before use**. The map is the reason a release PR targets `main` while the work sits on `staging`, with no token passed. An explicit `base:<branch>` token wins over all of them — use it when this PR targets something other than the day-to-day base, such as a release PR aimed at `main` while work lands on `staging`. **Never use `defaultBranchRef` as the PR base when the config names one.** Pass it explicitly: `gh pr create --base <base>`.
|
|
43
43
|
|
|
44
44
|
**Refused topologies.** From a `workspace` root there is no single PR to open — refuse in one line and point at `sassy-ship`, which owns the per-repo fan-out. With `git.repo: none`, refuse and say why. Neither ever pushes directly to a base branch.
|
|
45
45
|
|
|
@@ -174,9 +174,17 @@ before writing.
|
|
|
174
174
|
and all four hook points. Use it instead of merging maps by hand.
|
|
175
175
|
|
|
176
176
|
In a `workspace`, `base_map` does not apply — there are no branches at the
|
|
177
|
-
workspace level.
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
workspace level. A nested repo's base resolves in this order:
|
|
178
|
+
|
|
179
|
+
1. that repo's own `.sassywares/config.yaml` → `base_map` — **authoritative**
|
|
180
|
+
2. `repos[<dir>]` in the workspace config — the inventory, and the fallback for a
|
|
181
|
+
repo that carries no config
|
|
182
|
+
3. stop and ask
|
|
183
|
+
|
|
184
|
+
`repos` exists because a workspace can hold repos you do not own and cannot add a
|
|
185
|
+
config to. When a repo has both, the nested config wins and `--check` reports
|
|
186
|
+
the disagreement rather than picking silently. A nested config needs no ladder
|
|
187
|
+
of its own unless its PRs target more than one branch.
|
|
180
188
|
|
|
181
189
|
**Branch name**, one per run. Derived once from the plan slug or topic before the
|
|
182
190
|
first commit, then passed to every repo. Multi-repo runs pass
|
|
@@ -131,10 +131,13 @@ yaml_flat() {
|
|
|
131
131
|
path = ""
|
|
132
132
|
for (i = 1; i <= sp; i++) if (sd[i] < d) path = path (path == "" ? "" : us) sk[i]
|
|
133
133
|
print path (path == "" ? "" : us) key "\t" val
|
|
134
|
-
}' "$CONFIG"
|
|
134
|
+
}' "${1:-$CONFIG}"
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
yflat() { yaml_flat | awk -F'\t' -v p="$1" '$1 == p { print $2; exit }'; }
|
|
137
|
+
yflat() { yaml_flat "$CONFIG" | awk -F'\t' -v p="$1" '$1 == p { print $2; exit }'; }
|
|
138
|
+
|
|
139
|
+
# yflat_in FILE PATH — the same reader against another config file.
|
|
140
|
+
yflat_in() { yaml_flat "$1" | awk -F'\t' -v p="$2" '$1 == p { print $2; exit }'; }
|
|
138
141
|
|
|
139
142
|
list_items() {
|
|
140
143
|
printf '%s' "$1" | sed -e 's/^\[//' -e 's/\]$//' | tr ',' '\n' \
|
|
@@ -155,7 +158,7 @@ map_match() {
|
|
|
155
158
|
if [[ "$head" == "$stem"* ]] && (( ${#stem} > bestlen )); then
|
|
156
159
|
best="$pat"; bestlen=${#stem}
|
|
157
160
|
fi
|
|
158
|
-
done < <(yaml_flat | awk -F'\t' -v us="$US" -v sec="$section" \
|
|
161
|
+
done < <(yaml_flat "$CONFIG" | awk -F'\t' -v us="$US" -v sec="$section" \
|
|
159
162
|
'{n=split($1,a,us); if (n==3 && a[1]=="git" && a[2]==sec) print a[3]}' | sort -u)
|
|
160
163
|
if [[ -n "$best" ]]; then
|
|
161
164
|
v="$(yflat "git${US}${section}${US}${best}")"
|
|
@@ -303,7 +306,7 @@ if (( CHECK )); then
|
|
|
303
306
|
"*") ;;
|
|
304
307
|
*"*") [[ "${pat%\*}" != *"*" ]] || bad "base_map key '$pat': only one trailing * is allowed" ;;
|
|
305
308
|
esac
|
|
306
|
-
done < <(yaml_flat | awk -F'\t' -v us="$US" '{n=split($1,a,us); if (n==3 && a[1]=="git" && a[2]=="base_map") print a[3]}' | sort -u)
|
|
309
|
+
done < <(yaml_flat "$CONFIG" | awk -F'\t' -v us="$US" '{n=split($1,a,us); if (n==3 && a[1]=="git" && a[2]=="base_map") print a[3]}' | sort -u)
|
|
307
310
|
head_ref="${HEAD_ARG:-$(git -C "$ROOT" branch --show-current 2>/dev/null || true)}"
|
|
308
311
|
if [[ -n "$head_ref" ]]; then
|
|
309
312
|
# the --head readout below prints this line; avoid printing it twice
|
|
@@ -343,8 +346,22 @@ if (( CHECK )); then
|
|
|
343
346
|
[[ -n "$name" ]] || continue
|
|
344
347
|
base="$(detect_base "$ROOT/$name")"
|
|
345
348
|
listed="$(block_value repos "$name" || true)"
|
|
346
|
-
|
|
347
|
-
|
|
349
|
+
# A nested repo's own config is authoritative; `repos` is the inventory and
|
|
350
|
+
# the fallback for repos that have none.
|
|
351
|
+
nested="$ROOT/$name/.sassywares/config.yaml"
|
|
352
|
+
nested_base=""
|
|
353
|
+
[[ -f "$nested" ]] && nested_base="$(yflat_in "$nested" "git${US}base_map${US}*")"
|
|
354
|
+
|
|
355
|
+
if [[ -n "$nested_base" ]]; then
|
|
356
|
+
if [[ -n "$listed" && "$listed" != "$nested_base" ]]; then
|
|
357
|
+
bad "repos.$name is '$listed' but $name/.sassywares/config.yaml maps \"*\" to '$nested_base' — the nested config wins; fix or drop the repos entry"
|
|
358
|
+
elif [[ -z "$listed" ]]; then
|
|
359
|
+
note " $name: base '$nested_base' from its own config (no repos entry needed)"
|
|
360
|
+
else
|
|
361
|
+
note " $name: base '$nested_base' (agrees with its own config)"
|
|
362
|
+
fi
|
|
363
|
+
elif [[ -z "$listed" ]]; then
|
|
364
|
+
bad "repos has no entry for '$name' and $name carries no config (remote default: ${base:-unknown})"
|
|
348
365
|
elif [[ -n "$base" && "$listed" != "$base" ]]; then
|
|
349
366
|
note " repos.$name '$listed' overrides the remote default '$base' — expected for an integration branch"
|
|
350
367
|
fi
|
|
@@ -29,7 +29,7 @@ disable-model-invocation: true
|
|
|
29
29
|
- **`git.repo` is a remote.** Dispatch a `worker`: *load the `sassy-commit` skill and follow it*, naming that the commit must include the plan, any new solutions docs, the concepts file, `AGENTS.md`, and any handbook just written — resolved from `artifacts.*`, never hardcoded. Use `branch:current` when already on a feature branch, so the docs land with the phase commits. When the checked-out branch is the base branch, use `branch:new <name>` so the branch is created from `origin/<base>` and carries every phase commit; a workspace run passes the run's shared branch name. Never push directly to the base branch. It returns the hash and subject.
|
|
30
30
|
- **`git.repo: workspace`.** Commit code inside each affected repo on the run's shared branch (cut once on the run's first commit, `branch:current` after), then run `.sassywares/workspace/snapshot`. The snapshot is the workspace's commit and it runs every time, right after approval. A missing or outdated `.sassywares/workspace/snapshot` is a blocker: report it and say to run `sassy-setup`.
|
|
31
31
|
- **`git.repo: none`.** No commit exists here. Report that the work is not persisted and stop.
|
|
32
|
-
5. **PR.** In a `remote` repo, dispatch a `worker`: *load the `sassy-commit-push-pr` skill and follow it with `branch:current` and `babysit:off`, forwarding `base:<branch>` when the caller supplied one* (step 6 owns the babysit). It returns the PR URL. In a `workspace`, open one PR per affected repo — the same branch name in each, `--base` from that repo's `repos` entry — and return a table. A touched repo missing from `repos`, or a base that cannot be resolved, is a stop-and-ask, never a guess. `none` opens nothing.
|
|
32
|
+
5. **PR.** In a `remote` repo, dispatch a `worker`: *load the `sassy-commit-push-pr` skill and follow it with `branch:current` and `babysit:off`, forwarding `base:<branch>` when the caller supplied one* (step 6 owns the babysit). It returns the PR URL. In a `workspace`, open one PR per affected repo — the same branch name in each, `--base` from that repo's own `base_map` when it carries a `.sassywares/config.yaml`, else its `repos` entry — and return a table. A touched repo missing from `repos`, or a base that cannot be resolved, is a stop-and-ask, never a guess. `none` opens nothing.
|
|
33
33
|
|
|
34
34
|
**The PR step owns the PR hooks.** `before_create` and `after_create` run inside `sassy-commit-push-pr`, once per PR; ship neither runs nor repeats them.
|
|
35
35
|
6. **Babysit.** With `pr.babysit` (default `true`), dispatch a `worker`: *load the `sassy-babysit` skill and follow it for the PR just created, one checkpoint*, forwarding any `merge:on|off` and `delete-branch:on|off` the caller supplied, else `pr.merge` and `pr.delete_branch`. It reports looks-ready or blocked. For a continuous watch, tell the user to run `sassy-babysit` in-session.
|