@sassywares/skills 0.5.14 → 0.5.15

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sassywares/skills",
3
- "version": "0.5.14",
3
+ "version": "0.5.15",
4
4
  "description": "Lean, explicit-invocation Agent Skills for shipping fast: plan, work, review, validate, ship.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -52,7 +52,7 @@ A check run never edits the config and never rewrites the tree: it prints what `
52
52
  - **Write `.sassywares/README.md`** from `assets/sassywares-readme.md` when absent. Never overwrite it — it may carry project notes.
53
53
  - **Tell the user to `/reload`.** The skills are invisible to the harness until it rescans.
54
54
 
55
- 6. **Install the workspace tooling, `workspace` only.** The snapshot plus the `branches` / `pull` / `checkout-bases` git helpers. Read `references/workspace.md` and follow it.
55
+ 6. **Install the workspace tooling, `workspace` only.** The snapshot plus the `branches` / `pull` / `checkout-bases` git helpers, and one `workspace:<script>` alias per script in the project's own manifest. Read `references/workspace.md` and follow it.
56
56
  7. **Verify.** Run `scripts/detect.sh --root <path> --check`. It validates the config against the tree — topology and remotes, `base_map` shape and cycles, `repos` against each nested repo, hooks, artifacts paths, `knowledge`, `pr.*` booleans, `commit.branch`, any unknown key, and in `workspace` mode the installed snapshot's version — plus the vendored pin: every `.agents/skills/sassy-*` folder hashed against `skills-lock.json`, the lock's coverage both ways, and whether git carries the lock. Report every `drift:` line verbatim, or that the config matches the tree. Drift blocks step 8.
57
57
  8. **Commit what setup owns.** `repo` topology only, and only when step 7 is clean. The file list is exactly what setup wrote or found unwritten:
58
58
 
@@ -65,7 +65,7 @@ A check run never edits the config and never rewrites the tree: it prints what `
65
65
  - **`workspace`** — nothing to commit: the root is not a repo, and `references/workspace.md` forbids running the snapshot here. Say the root config and the pin land with the project's next snapshot.
66
66
  - **`none`** — nothing to commit, deliberately.
67
67
 
68
- 9. **Report.** The config path, the topology, the resolved artifact and knowledge paths, the commit (hash and branch) or why there is none, and in `workspace` mode what was installed, with versions (`snapshot vN`, `workspace-git vN`). Remind: `/reload` so the harness rescans. Close with what is left over — at most dirt setup deliberately did not commit — and nothing else: a clean setup leaves the user good to go.
68
+ 9. **Report.** The config path, the topology, the resolved artifact and knowledge paths, the commit (hash and branch) or why there is none, and in `workspace` mode what was installed, with versions (`snapshot vN`, `workspace-git vN`), and the manifest the `workspace:*` aliases went into — naming it as created when there was no script surface to begin with. Remind: `/reload` so the harness rescans. Close with what is left over — at most dirt setup deliberately did not commit — and nothing else: a clean setup leaves the user good to go.
69
69
 
70
70
  ## Hard rules
71
71
 
@@ -78,8 +78,8 @@ A check run never edits the config and never rewrites the tree: it prints what `
78
78
  | No silent overwrite | An existing config or an existing `.sassywares/workspace/snapshot` is shown and asked about, never replaced blind. |
79
79
  | Version is reported | Setup names the snapshot and `workspace-git` versions it installed; `--check` flags an installed copy older than the skill's. |
80
80
  | Skills come from upstream | Install with `npx skills add`; never hand-copy skill files or maintain the links yourself. |
81
- | Never edit the manifest | No dependencies, no scripts, no `postinstall`. Setup installs the suite; the project decides how it updates. |
82
- | Write boundary | Only `.sassywares/`, the vendored `.agents/skills/sassy-*`, `skills-lock.json`, and one `.gitignore` line — and the same list is step 8's commit. Never `package.json`, never a root `.gitignore` in a workspace. Workspace git helpers land in `.sassywares/workspace/`, never in a project's `bin/`. |
81
+ | Never edit the manifest | No dependencies, no `postinstall`, no `skills:*` scripts. The one exception is step 6's `workspace:*` aliases in `workspace` topology: appended or corrected, never removed, and nothing else in the file touched. Setup installs the suite; the project decides how it updates. |
82
+ | Write boundary | Only `.sassywares/`, the vendored `.agents/skills/sassy-*`, `skills-lock.json`, and one `.gitignore` line — and the same list is step 8's commit. Never `package.json` outside step 6's `workspace:*` aliases, never a root `.gitignore` in a workspace. Workspace git helpers land in `.sassywares/workspace/`, never in a project's `bin/`. |
83
83
  | Detect, don't guess | An unknown base branch stays unknown and gets asked about. A probed value is reported as probed. |
84
84
  | Comments are part of the file | Every key keeps its description and allowed values. A stripped config is an incomplete config. |
85
85
  | Hooks are named, not written | Setup records hook skill names. Creating those skills is the project's work. |
@@ -43,6 +43,11 @@ across the sibling repos, next to the `snapshot` that versions the glue:
43
43
  .sassywares/workspace/snapshot # commit + push the glue
44
44
  ```
45
45
 
46
+ Each one also has an alias in the project manifest (`workspace:branches`,
47
+ `workspace:pull`, `workspace:checkout-bases`, `workspace:snapshot`), so
48
+ `npm run workspace:pull` — or the equivalent for the runner this project uses —
49
+ works from the root.
50
+
46
51
  They read the repo inventory and the PR bases from `repos:` in `config.yaml`, so
47
52
  there is no second base map to keep in step. They are this project's files:
48
53
  extend them freely — just run the snapshot afterwards, since they live in the
@@ -27,6 +27,8 @@ lives under one directory:
27
27
  `_lib.sh`'s `workspace-git-version` (or `branches --version`) the same way.
28
28
  **Ask before overwriting any of them when they already exist** — from the first
29
29
  install on they are the project's files, and extending them is expected.
30
+ - **Aliases.** One `workspace:<script>` entry per installed script, in the
31
+ project's own manifest. See below.
30
32
  - **Excludes.** Write `.sassywares/workspace/.gitignore` for excluded paths
31
33
  (vendored trees, generated dirs, `.run/`). One pattern per line, `.gitignore`
32
34
  style. Skip it when there is nothing to exclude; the sync works without it. The
@@ -36,6 +38,57 @@ lives under one directory:
36
38
  - Do **not** run the snapshot during setup. It clones and pushes; that is the
37
39
  user's call. Offer `--dry-run` and run it only if they ask.
38
40
 
41
+ ## Script aliases
42
+
43
+ The scripts should be reachable from the project's own runner, so setup wires one
44
+ alias per installed script:
45
+
46
+ ```json
47
+ "scripts": {
48
+ "workspace:branches": ".sassywares/workspace/branches",
49
+ "workspace:pull": ".sassywares/workspace/pull",
50
+ "workspace:checkout-bases": ".sassywares/workspace/checkout-bases",
51
+ "workspace:snapshot": ".sassywares/workspace/snapshot"
52
+ }
53
+ ```
54
+
55
+ Find the file that carries named commands — at the **workspace root only**, never
56
+ inside a repo:
57
+
58
+ | File at the root | Write the aliases to |
59
+ | --- | --- |
60
+ | `package.json` | its `scripts` |
61
+ | `deno.json` / `deno.jsonc` | its `tasks` |
62
+ | `composer.json` | its `scripts` |
63
+ | `go.mod`, `pyproject.toml`, `Cargo.toml`, `Gemfile`, `Makefile`, `justfile`, … | nothing: create `package.json` as below |
64
+
65
+ `go.mod` and friends name dependencies, not commands, and a make/just target
66
+ cannot carry the `workspace:` form. Never invent a `Makefile` or `justfile` to
67
+ avoid `package.json` — one naming convention across projects is worth more than
68
+ one file fewer.
69
+
70
+ - **Name and value are fixed**: `workspace:<script>` → `.sassywares/workspace/<script>`.
71
+ No `./`, no absolute paths, no `bin/`.
72
+ - **Merge, never rewrite**: existing scripts and every other field stay as they
73
+ are; new keys go at the end of the scripts block; keep the file's indentation.
74
+ Never touch dependencies, `postinstall`, or `skills:*`.
75
+ - **Idempotent**: a matching alias is left alone, a stale value is corrected, and
76
+ an alias the project added itself is never removed.
77
+ - **No manifest at all?** Look at what the repos are — Node, Go, Python, a mix —
78
+ and say so. Then create a minimal `package.json`:
79
+
80
+ ```json
81
+ {
82
+ "private": true,
83
+ "scripts": { … }
84
+ }
85
+ ```
86
+
87
+ `private: true` keeps it unpublishable; no `name`, no `version`, no
88
+ dependencies. It exists so the aliases have a home. **Say that in the report** —
89
+ created versus already there — and skip the aliases entirely when the project
90
+ has removed the scripts they point at.
91
+
39
92
  ## What the git helpers are for
40
93
 
41
94
  `branches`, `pull`, and `checkout-bases` do across the workspace's repos what the
@@ -430,6 +430,28 @@ if (( CHECK )); then
430
430
  else
431
431
  note " no workspace git helpers installed (optional)"
432
432
  fi
433
+
434
+ # Aliases live in the project's own manifest; setup only ever adds them.
435
+ manifest=""
436
+ for candidate in package.json deno.json deno.jsonc composer.json; do
437
+ if [[ -f "$ROOT/$candidate" ]]; then
438
+ manifest="$candidate"
439
+ break
440
+ fi
441
+ done
442
+ if [[ -n "$manifest" ]]; then
443
+ missing_aliases=()
444
+ for script in branches pull checkout-bases snapshot; do
445
+ grep -q "\"workspace:${script}\"" "$ROOT/$manifest" || missing_aliases+=("$script")
446
+ done
447
+ if [[ ${#missing_aliases[@]} -eq 0 ]]; then
448
+ note " workspace:* aliases in ${manifest}"
449
+ elif [[ ${#missing_aliases[@]} -lt 4 ]]; then
450
+ bad "${manifest} is missing $(printf '`workspace:%s` ' "${missing_aliases[@]}")— half-wired aliases; re-run setup"
451
+ else
452
+ note " no workspace:* aliases in ${manifest} (optional)"
453
+ fi
454
+ fi
433
455
  while IFS= read -r name; do
434
456
  [[ -n "$name" ]] || continue
435
457
  base="$(detect_base "$ROOT/$name")"