@sassywares/agents 0.0.0-stage → 0.1.1

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/CONCEPTS.md ADDED
@@ -0,0 +1,45 @@
1
+ # Sassy Agents — Concepts
2
+
3
+ ## Source of truth
4
+
5
+ Each harness directory is the only copy of that harness's roster. `scripts/install.sh <harness>` symlinks each file into the harness's user agent directory (`~/.pi/agent/agents/`, `~/.claude/agents/`), so the running agents are the working tree.
6
+
7
+ ## Agent
8
+
9
+ A Markdown file with `name` and `description` frontmatter, plus optional `tools`, `model`, `thinking`, and `profiles`. The body is the system prompt. One file, one role. See the [pi agent format](https://github.com/earendil-works/pi).
10
+
11
+ ## Harness
12
+
13
+ A directory at the repo root named after the tool that consumes it: `pi/` for pi, `claude/` for Claude Code. Every harness directory holds the full roster. Harnesses differ in frontmatter and discovery only: an agent's body — what it does — is identical in every harness, and CI fails when it drifts.
14
+
15
+ ## Roster
16
+
17
+ The four agents shipped here — `scout`, `worker`, `reviewer`, `validator` — and the contract that they cover a unit of work end to end: ground it, implement it, review it, validate it against intent.
18
+
19
+ ## Profile
20
+
21
+ A named model choice inside an agent's `profiles:` list, such as `deepseek` or `anthropic`. A dispatch selects a profile; the agent's entry supplies the model and thinking level for that provider. Profiles are how one roster runs on several providers without a branch or a second copy.
22
+
23
+ ## Profile selection
24
+
25
+ The precedence that resolves which profile a dispatch runs: the tool call's `profile` parameter, then `PI_SASSY_PROFILE`, then `sassy.profile` in project settings, then user settings, then the default `deepseek`. A missing profile is an error naming the available ones — never a silent fallback.
26
+
27
+ ## Scope
28
+
29
+ Where an agent is discovered from. `user` is `~/.pi/agent/agents/`, the target of `scripts/install.sh`. `project` is the nearest project `.pi/agents/`, which overrides a user agent of the same name. The `subagent` tool takes `user`, `project`, or `both`; the default is `both`.
30
+
31
+ ## Grounding brief
32
+
33
+ One file per repo or worktree, in a per-user temp directory, written by `scout` and read by every other agent in the run. It carries project evidence with `file:line` citations so consumers do not repeat discovery. Location, freshness, and wait rules are in [GROUNDING.md](GROUNDING.md).
34
+
35
+ ## Subagent
36
+
37
+ The tool from `@sassywares/pi-extensions` that spawns one pi process per task and returns compact output. Modes are single, parallel, and chain. This repo supplies the agents it dispatches; it does not implement the tool.
38
+
39
+ ## Orchestrator
40
+
41
+ A skill from `sassy-skills` that coordinates: it decides which agents to dispatch, writes the brief, and keeps the main context small. Orchestrators live in the skills repo, not here.
42
+
43
+ ## Upstream derivation
44
+
45
+ The roster is a modified version of pi's MIT-licensed examples and documentation. `NOTICE` records the attribution; `LICENSE` covers this repository.
package/GROUNDING.md ADDED
@@ -0,0 +1,60 @@
1
+ # Grounding brief
2
+
3
+ Every subagent in a run reads one shared grounding brief instead of exploring the repo for itself. `scout` writes it; `reviewer`, `validator`, and `worker` consume it.
4
+
5
+ ## Location
6
+
7
+ A per-user temp directory, keyed by the absolute repo or worktree root:
8
+
9
+ ```bash
10
+ ROOT="/tmp/pi-grounding-$(id -u)"
11
+ [ -L "$ROOT" ] && { echo "unsafe symlink: $ROOT" >&2; exit 1; }
12
+ [ -d "$ROOT" ] || { umask 077; mkdir -p "$ROOT"; }
13
+ chmod 700 "$ROOT" 2>/dev/null
14
+ ROOT_ABS=$(cd "$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")" && pwd -P)
15
+ KEY=$(printf '%s' "$ROOT_ABS" | shasum -a 256 | cut -d' ' -f1)
16
+ BRIEF="$ROOT/$KEY.md"
17
+ ```
18
+
19
+ For example, `tap2-workspace` resolves to `/tmp/pi-grounding-501/<sha>.md`. The directory is `0700` and owned by the current user; a symlinked or foreign-owned root aborts rather than being followed, because the brief is read as trusted-ish context by later agents.
20
+
21
+ Keying on the worktree root means:
22
+
23
+ - Two repos, or two worktrees of one repo, never share a brief.
24
+ - A non-git folder still gets a stable location (hash of `$PWD`), so a scout and a consumer launched from the same directory agree.
25
+ - Nothing is written into the repo, so there is no `.gitignore` entry and nothing to commit.
26
+ - `/tmp` is cleared on reboot, which is the desired lifetime for a brief describing a working tree.
27
+
28
+ ## Freshness
29
+
30
+ A brief is usable when all four hold:
31
+
32
+ 1. `repo` matches the current `ROOT_ABS`.
33
+ 2. `head` matches `git rev-parse HEAD`.
34
+ 3. `dirty` matches the current digest of `git status --porcelain`, `git diff`, and `git diff --cached` combined.
35
+ 4. `scope` covers what the consumer is about to ask.
36
+
37
+ The digest covers statuses and diffs, not statuses alone: `git status --porcelain` reports ` M path` no matter what changed inside the file, so a status-only digest leaves a brief "fresh" after further edits to an already-dirty file. Including the diffs closes that. Any commit, edit, staged change, or new untracked file changes the digest and invalidates the brief; for a non-git folder the digest is empty, so freshness there rests on `scope` and `written` alone.
38
+
39
+ ## Waiting
40
+
41
+ Consumers wait for a stale brief to be rewritten, never for one that does not exist. Waiting is token-free:
42
+
43
+ ```bash
44
+ if [ -f "$BRIEF" ]; then
45
+ for _ in $(seq 1 30); do
46
+ { grep -qx "head: $HEAD" "$BRIEF" && grep -qx "dirty: $DIRTY" "$BRIEF"; } && break
47
+ sleep 2
48
+ done
49
+ fi
50
+ ```
51
+
52
+ Sixty seconds is the ceiling. A missing brief reports `grounding: missing`; a brief that never refreshes reports `grounding: stale`. Either way the consumer does **at most 5 bounded reads** to fill the gap and says so in its output. It never runs a broad discovery pass and never becomes a second scout.
53
+
54
+ ## Sequencing
55
+
56
+ The orchestrator dispatches `scout` first and awaits it, then dispatches the rest. Agents dispatched without the path still resolve the default location themselves, so a brief written by any earlier agent is reused.
57
+
58
+ ## What the brief is not
59
+
60
+ It is not a cache across commits and not a substitute for judging evidence. A stale or thin brief is a finding the consumer reports, not something it silently papers over.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sassywares
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,9 @@
1
+ # Notice
2
+
3
+ The agent definitions under `pi/` and `claude/` are derived from the examples and
4
+ documentation of [pi](https://github.com/earendil-works/pi), Copyright (c) Mario
5
+ Zechner and contributors, licensed under the MIT License.
6
+
7
+ They have been modified for the Sassywares workflow: the Sassy roster, profile
8
+ selection, and the shared grounding brief. See `LICENSE` for the license
9
+ covering this repository.
package/README.md CHANGED
@@ -1,3 +1,239 @@
1
- # Temporary Holding Version
1
+ # Sassy Agents
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **The Sassy subagent roster — one directory per harness, one behavior in every harness, one roster on every provider.**
4
+
5
+ Sassy Agents is the source of truth for the subagents the Sassywares workflow dispatches: a grounding scout, an implementation worker, a reviewer, and a validator. Each agent is a Markdown file with frontmatter; each declares a `profiles:` list, so the same roster runs on DeepSeek by default and on Anthropic when a project opts in.
6
+
7
+ The repo is `sassy-agents`. The npm mirror is `@sassywares/agents`.
8
+
9
+ ## Table of contents
10
+
11
+ - [Why this roster](#why-this-roster)
12
+ - [Quick start](#quick-start)
13
+ - [Agents](#agents)
14
+ - [How agents are found](#how-agents-are-found)
15
+ - [Model profiles](#model-profiles)
16
+ - [Grounding brief](#grounding-brief)
17
+ - [Harness layout](#harness-layout)
18
+ - [Adding or editing an agent](#adding-or-editing-an-agent)
19
+ - [Repository layout](#repository-layout)
20
+ - [Development](#development)
21
+ - [Repository maintenance](#repository-maintenance)
22
+ - [Provenance](#provenance)
23
+
24
+ ## Why this roster
25
+
26
+ - **One job per agent.** Scout grounds, worker implements, reviewer judges quality, validator judges intent. None of them re-does another's work.
27
+ - **Isolated context.** Each is dispatched by the `subagent` tool from [`sassy-pi-extensions`](https://github.com/sassywares/sassy-pi-extensions), so each gets its own context window and returns a compact result.
28
+ - **Provider-agnostic.** Model choice lives in frontmatter `profiles:`, not in a branch or a separate roster. Swapping providers is a settings change.
29
+ - **Read-only by default.** Reviewer and validator get `read, grep, find, ls, bash`; only scout and worker can write.
30
+ - **Shared grounding.** Every agent reads one brief written by `scout` instead of re-exploring the repo. See [GROUNDING.md](GROUNDING.md).
31
+ - **Composable with [`sassy-skills`](https://github.com/sassywares/sassy-skills).** The skills dispatch these agents by name — `scout`, `worker`, `reviewer`, `validator`.
32
+
33
+ ## Quick start
34
+
35
+ Clone the repo next to your work and link the roster for your harness:
36
+
37
+ ```bash
38
+ git clone https://github.com/sassywares/sassy-agents.git
39
+ ./sassy-agents/scripts/install.sh # pi → ~/.pi/agent/agents/
40
+ ./sassy-agents/scripts/install.sh claude # Claude Code → ~/.claude/agents/
41
+ ```
42
+
43
+ `sassy-setup` (in `sassy-skills`) checks for the roster and offers this link, or a per-project copy into `.pi/agents/` / `.claude/agents/`.
44
+
45
+ `install.sh` symlinks `pi/*.md` into `~/.pi/agent/agents/`. Editing this repo changes the running agents on the next subagent invocation — there is no copy to keep in sync.
46
+
47
+ Then install the extensions that dispatch them, if you have not already:
48
+
49
+ ```bash
50
+ pi install npm:@sassywares/pi-extensions
51
+ ```
52
+
53
+ Reload pi (`/reload`) and confirm the `subagent` tool lists the Sassy agents.
54
+
55
+ A package-only install of `@sassywares/agents` works too when you would rather pin a version than link a checkout:
56
+
57
+ ```bash
58
+ npm install --save-dev @sassywares/agents@0.1.0
59
+ ./node_modules/@sassywares/agents/scripts/install.sh
60
+ ```
61
+
62
+ Pi does not load agents from packages on its own; the link step is what makes them visible.
63
+
64
+ ## Agents
65
+
66
+ | Agent | Role | pi `deepseek` profile | pi `anthropic` profile | Claude Code `model` |
67
+ |---|---|---|---|---|
68
+ | `scout` | Grounding scout: writes the shared grounding brief other agents read, including matching prior learnings from the project's `.sassywares/config.yaml` knowledge paths. | `deepseek/deepseek-flash` | `anthropic/claude-haiku-4-5` | `haiku` |
69
+ | `worker` | General-purpose implementation in an isolated context. | `deepseek/deepseek-flash` | `anthropic/claude-sonnet-4-5` | `sonnet` |
70
+ | `reviewer` | Quality, correctness, security, project-rule, and design-system review, diff-scoped. | `deepseek/deepseek-flash` | `anthropic/claude-opus-4-5` | `opus` |
71
+ | `validator` | Checks that the diff matches the plan, independent of review. | `deepseek/deepseek-flash` | `anthropic/claude-sonnet-4-5` | `sonnet` |
72
+
73
+ Each file's body is the system prompt. Keep it to the role, hard rules, scope, and return shape — the orchestrating skill supplies the task. The body is identical in every harness directory; only the frontmatter is harness-specific, and CI fails on drift.
74
+
75
+ ## How agents are found
76
+
77
+ Claude Code discovers agents from `~/.claude/agents/` (user) and the project's `.claude/agents/` (project, which wins on a name clash).
78
+
79
+ In pi, the `subagent` extension discovers agents from:
80
+
81
+ - `~/.pi/agent/agents/` — user scope, where `scripts/install.sh` links this roster.
82
+ - The nearest project `.pi/agents/` — project scope, which overrides a user agent with the same name.
83
+
84
+ `PI_AGENTS_DIR` overrides the user target when linking, which is useful in a container or a test harness. The extension's `agentScope` parameter (`user`, `project`, `both`) decides which of the two a dispatch sees; the default is `both`.
85
+
86
+ ## Model profiles
87
+
88
+ A dispatch picks a profile — a named model choice — and the child process starts on that profile's model.
89
+
90
+ Pick a profile three ways, highest precedence first:
91
+
92
+ 1. The tool call: `{ agent: "worker", task: "…", profile: "anthropic" }`. Individual `tasks[]` and `chain[]` entries accept `profile` too.
93
+ 2. An environment variable: `PI_SASSY_PROFILE=anthropic`.
94
+ 3. A project setting in `.pi/settings.json`, which is where a project opts in once for everyone:
95
+
96
+ ```json
97
+ { "sassy": { "profile": "anthropic" } }
98
+ ```
99
+
100
+ Project settings override `~/.pi/agent/settings.json`; with neither set, the default profile is `deepseek`.
101
+
102
+ A profile an agent does not define is an error naming the ones it does — it never falls back to the default provider. The run footer shows the model and, in parentheses, the profile it came from.
103
+
104
+ Every agent must define every profile a project may select. Adding a profile is a frontmatter edit in each file you want it to apply to:
105
+
106
+ ```yaml
107
+ profiles:
108
+ - name: deepseek
109
+ model: deepseek/deepseek-flash
110
+ thinking: low
111
+ - name: anthropic
112
+ model: anthropic/claude-sonnet-4-5
113
+ thinking: low
114
+ ```
115
+
116
+ Rules:
117
+
118
+ - Profile names are lowercase letters, digits, and dashes, and must be unique within an agent.
119
+ - `model` is always `provider/id`; `thinking` is one of `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`.
120
+ - `profiles:` and `model:` are mutually exclusive — pinning a model and offering profiles at once is a parse error.
121
+ - A pinned `model:` (plus optional `thinking:`) is still supported for personal agents and ignores profile selection.
122
+ - Neither key means the agent inherits the dispatcher's model and thinking.
123
+
124
+ ## Grounding brief
125
+
126
+ Every agent in a run reads one shared brief instead of exploring the repo for itself. `scout` writes it; `worker`, `reviewer`, and `validator` consume it. It lives in a per-user temp directory keyed by the absolute repo or worktree root, so it never touches the repo and two worktrees never collide.
127
+
128
+ [GROUNDING.md](GROUNDING.md) defines the location, the freshness check, and the wait rule. A missing or stale brief is reported, never papered over.
129
+
130
+ ## Harness layout
131
+
132
+ One directory per harness: `pi/` and `claude/`. Every directory carries the full roster with identical bodies; only frontmatter differs.
133
+
134
+ ```text
135
+ sassy-agents/
136
+ ├── pi/ # pi subagent definitions
137
+ │ ├── scout.md
138
+ │ ├── worker.md
139
+ │ ├── reviewer.md
140
+ │ └── validator.md
141
+ ├── claude/ # Claude Code subagent definitions (same four)
142
+ ├── scripts/
143
+ │ ├── install.sh # links one harness's agents into place
144
+ │ ├── sync.sh # bump, commit, push, tag
145
+ │ └── test-profiles.mjs
146
+ └── …
147
+ ```
148
+
149
+ `scripts/install.sh <harness>` takes `pi` (the default) or `claude` and rejects a harness it does not know, rather than guessing a target directory.
150
+
151
+ ## Adding or editing an agent
152
+
153
+ 1. Create or edit the agent in every harness directory: `pi/<name>.md` (`profiles:` or a pinned `model:`) and `claude/<name>.md` (Claude Code `tools` and a `model:` alias).
154
+ 2. Keep the frontmatter `name` equal to the file name.
155
+ 3. Keep the body focused on the role, hard rules, scope, and return shape — and byte-identical across harnesses.
156
+ 4. Update the roster table in `README.md`.
157
+ 5. Run `./scripts/install.sh` once if the agent is new, then `./scripts/sync.sh` to commit and release.
158
+
159
+ Agents that write should say so in `tools:`: `scout` needs `write` (`Write` in Claude Code) for the brief, `worker` needs the full toolset. Reviewer and validator stay read-only so a review cannot change the diff it is judging.
160
+
161
+ ## Repository layout
162
+
163
+ ```text
164
+ sassy-agents/
165
+ ├── pi/
166
+ │ └── *.md
167
+ ├── claude/
168
+ │ └── *.md
169
+ ├── scripts/
170
+ │ ├── install.sh
171
+ │ ├── sync.sh
172
+ │ └── test-profiles.mjs
173
+ ├── .github/workflows/
174
+ │ └── publish.yml
175
+ ├── AGENTS.md
176
+ ├── CONCEPTS.md
177
+ ├── GROUNDING.md
178
+ ├── LICENSE
179
+ ├── NOTICE
180
+ ├── README.md
181
+ └── package.json
182
+ ```
183
+
184
+ | Path | Role |
185
+ |---|---|
186
+ | `pi/*.md` | The pi roster. Linked into `~/.pi/agent/agents/`. |
187
+ | `claude/*.md` | The Claude Code roster. Linked into `~/.claude/agents/`. |
188
+ | `scripts/install.sh` | Symlinks one harness's agents into that harness's user directory. |
189
+ | `scripts/sync.sh` | Bumps, commits, pushes, tags, and releases. |
190
+ | `scripts/test-profiles.mjs` | Checks agent parsing and profile resolution against the real roster plus malformed fixtures. |
191
+ | `.github/workflows/publish.yml` | Validates the roster and publishes on a `v*` tag. |
192
+ | `GROUNDING.md` | The shared grounding brief contract. |
193
+ | `package.json` | npm mirror manifest. |
194
+
195
+ ## Development
196
+
197
+ Agents are read from disk on every dispatch, so there is no build step. Link the working tree once:
198
+
199
+ ```bash
200
+ ./scripts/install.sh
201
+ ```
202
+
203
+ After editing an agent, dispatch it through the `subagent` tool. After changing parsing or profile behavior, run the checks:
204
+
205
+ ```bash
206
+ ./scripts/test-profiles.mjs
207
+ ```
208
+
209
+ The script copies `agents.ts` from a `sassy-pi-extensions` checkout — found as a sibling directory, through `PI_EXTENSIONS_DIR`, or in an install — plus the real roster into a temporary project, and exercises discovery, profile resolution, precedence, and every rejected frontmatter shape. It needs the pi install for peer packages; set `PI_PEER_MODULES` if it cannot find one.
210
+
211
+ ## Repository maintenance
212
+
213
+ `scripts/sync.sh` bumps the patch version when shipped content changed, commits, pushes `main`, then tags and pushes the tag — so a roster change is released in one step. Any agent that changes the roster must run it immediately, without asking for confirmation.
214
+
215
+ ```bash
216
+ ~/Documents/Workspace/Sassywares/sassy-agents/scripts/sync.sh
217
+ ```
218
+
219
+ Releases only happen on `main`. On any other branch the script commits and pushes without tagging, because a tag pushed from a feature branch would publish unmerged content to npm. It installs nothing: consumers get a change when they run `./scripts/install.sh` after pulling, and the npm mirror follows the tag.
220
+
221
+ ### Releasing
222
+
223
+ Publishing is tag-driven and uses npm trusted publishing (OIDC). `publish.yml` validates every harness's agents and their sync, checks that the tag matches `package.json`, refuses a tag that is not an ancestor of `main`, and publishes `@sassywares/agents` with the dist-tag derived from the version.
224
+
225
+ `scripts/sync.sh` does this for you on `main`. The manual sequence is the fallback for recovering a failed run:
226
+
227
+ ```bash
228
+ npm version patch --no-git-tag-version
229
+ git add -A && git commit -m "chore: release v$(node -p "require('./package.json').version")"
230
+ git push origin main
231
+ git tag "v$(node -p "require('./package.json').version")"
232
+ git push origin --tags
233
+ ```
234
+
235
+ The first publish of a new package needs a manual `npm publish --access public` bootstrap before npm's trusted-publisher settings exist. `AGENTS.md` documents the full workflow for agents working on this repo.
236
+
237
+ ## Provenance
238
+
239
+ The agent definitions under `pi/` and `claude/` are derived from pi's MIT-licensed examples and documentation, modified for this workflow. See [NOTICE](NOTICE).
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: reviewer
3
+ description: Code review specialist for quality, correctness, security, project-rule conformance, and design-system conformance
4
+ tools: Read, Grep, Glob, Bash
5
+ model: opus
6
+ ---
7
+
8
+ You are a senior code reviewer. Analyze the changed code for quality, correctness, security, maintainability, and conformance to the project's own rules and design system.
9
+
10
+ Bash is for read-only commands only: `git diff`, `git log`, `git show`. Do NOT modify files or run builds.
11
+
12
+ ## Scope — the diff only
13
+
14
+ You review the change, never the repository. Your working set is:
15
+
16
+ 1. The diff (`git diff`, `git diff --stat`, or the commit range you were given).
17
+ 2. Files the diff touches.
18
+ 3. Files whose symbols the changed lines call or implement, read only enough to judge the changed lines.
19
+ 4. The rule and design-system files the conformance checks name.
20
+
21
+ Everything else is out of scope. Do not grep the repo to orient yourself, do not run a discovery pass, do not audit unchanged files, and do not summarise the surrounding architecture. If a finding needs a file outside this set, report the finding with what you would need to confirm it and stop — do not go exploring.
22
+
23
+ ## Grounding
24
+
25
+ Before reading anything, read the shared grounding brief — the `scout` writes it and it exists so you do not re-derive project context. Locate and check it in one call:
26
+
27
+ ```bash
28
+ ROOT="/tmp/pi-grounding-$(id -u)"
29
+ [ -L "$ROOT" ] && { echo "unsafe symlink: $ROOT" >&2; exit 1; }
30
+ [ -d "$ROOT" ] || { umask 077; mkdir -p "$ROOT"; }
31
+ chmod 700 "$ROOT" 2>/dev/null
32
+ ROOT_ABS=$(cd "$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")" && pwd -P)
33
+ KEY=$(printf '%s' "$ROOT_ABS" | shasum -a 256 | cut -d' ' -f1)
34
+ BRIEF="$ROOT/$KEY.md"
35
+ HEAD=$(git rev-parse HEAD 2>/dev/null || echo none)
36
+ DIRTY=$( { git status --porcelain; git diff; git diff --cached; } 2>/dev/null | shasum -a 256 | cut -d' ' -f1)
37
+ if [ -f "$BRIEF" ]; then
38
+ for _ in $(seq 1 30); do
39
+ { grep -qx "head: $HEAD" "$BRIEF" && grep -qx "dirty: $DIRTY" "$BRIEF"; } && break
40
+ sleep 2
41
+ done
42
+ fi
43
+ echo "$BRIEF"
44
+ ```
45
+
46
+ Read the brief if it exists. If it is fresh and covers the diff's area, use it and skip your own discovery. If it is missing, report `grounding: missing` in your output and do at most 5 bounded reads. If it is stale and not refreshed within the wait, report `grounding: stale` and do the same. Never become a second scout.
47
+
48
+ You review four dimensions, none optional:
49
+
50
+ 1. **Correctness and security** — bugs, regressions, injection, auth gaps, data loss.
51
+ 2. **Project-rule conformance** — does the change follow the workspace and package rules?
52
+ 3. **Design-system conformance** — do UI changes use the project's components, tokens, and patterns?
53
+ 4. **Quality and maintainability** — duplication, clarity, dead code. Simplification opportunities (a needless abstraction, a one-use helper, dead branches) belong here under Suggestions; there is no separate simplify pass.
54
+
55
+ You review the result, not the plan. Whether the work matches what was planned is the validator's job.
56
+
57
+ Rules:
58
+ - Be specific with file paths and line numbers.
59
+ - Distinguish real defects from style preferences. Do not pad the list.
60
+ - Ground every rule or design-system finding in something you actually read: quote the rule file and section, or name the shared component/token the code bypasses. Never invent a standard.
61
+ - If a dimension has no applicable surface (no rules, no UI), say so instead of padding.
62
+ - Contradictory rules are a finding. Report the conflict; do not silently pick a side.
63
+
64
+ ## Project-rule conformance
65
+
66
+ 1. Read the governing rules before judging: the nearest `AGENTS.md` or `CLAUDE.md` at the repo root and in each touched package, plus the conventions they reference (`CONCEPTS.md`, `docs/`, contributor guides, `.editorconfig`, lint and TS config).
67
+ 2. Check the rules that apply to the touched areas, for example:
68
+ - package manager, language, and typing rules (no `any`, explicit types, immutable patterns, early returns)
69
+ - required argument validators and auth checks on public functions
70
+ - forbidden or gated commands (deploys, migrations, force-push), branch and release conventions
71
+ - file placement, naming, and documented domain vocabulary
72
+ - generated files that must not be hand-edited
73
+ 3. A broken rule is a finding unless the rule clearly does not apply; state why when you waive one.
74
+ 4. An intentional departure from a rule needs an explicit reason in the change or a docs update. Flag it if neither exists.
75
+
76
+ ## Design-system conformance
77
+
78
+ 1. Locate the design system first: the UI package (e.g. `@scope/ui`), token and theme files, the shared component library, Storybook, and visual docs. Read how existing components consume it before judging new code.
79
+ 2. For each touched UI component, check:
80
+ - shared components and tokens are used instead of hardcoded colors, spacing, radii, shadows, z-index, or typography
81
+ - no local reimplementation of a primitive the design system already provides
82
+ - variants, sizes, and states match the system (hover, focus, disabled, loading, error, empty)
83
+ - accessibility: semantic elements, labels, focus handling, keyboard support, contrast, alt text
84
+ - responsive and RTL behavior where the system defines it, and localization through the project's i18n path
85
+ - icons and assets come from the approved source
86
+ 3. Prefer the closest existing pattern over a new one. Flag one-off components and magic values.
87
+ 4. If the repo has no design system, state that and fall back to general UI and accessibility checks.
88
+
89
+ Strategy:
90
+ 1. Read the grounding brief (see Grounding above).
91
+ 2. Run `git diff` (and `git diff --stat`) to see the change.
92
+ 3. Read the modified files and only the surrounding code the changed lines require.
93
+ 4. Read the applicable rule files and the design-system sources they point to.
94
+ 5. Check all four dimensions. Drop anything you cannot ground in code or a rule.
95
+
96
+ Output format:
97
+
98
+ ## Files Reviewed
99
+ - `path/to/file.ts` (lines X-Y)
100
+
101
+ ## Rules & Design System Checked
102
+ - `AGENTS.md` (repo root) — sections applied / not applicable
103
+ - `packages/ui/src/tokens.css` — tokens and component conventions applied
104
+ - Design system: found / not found — basis for the UI checks
105
+
106
+ ## Critical (must fix)
107
+ - `file.ts:42` - issue description
108
+
109
+ ## Warnings (should fix)
110
+ - `file.ts:100` - issue description
111
+
112
+ ## Suggestions (consider)
113
+ - `file.ts:150` - improvement idea
114
+
115
+ ## Summary
116
+ Overall assessment in 2-3 sentences, including rule and design-system conformance.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: scout
3
+ description: Grounding scout — scouts the area it is asked about, writes a shared grounding brief other agents read instead of exploring the repo themselves
4
+ tools: Read, Grep, Glob, Bash, Write
5
+ model: haiku
6
+ ---
7
+
8
+ You are the grounding scout. You answer one bounded question about this repository and write the answer to a file that every other subagent in this run reads instead of re-exploring.
9
+
10
+ You do not form opinions, recommend changes, or review code. You gather verified project evidence and cite it.
11
+
12
+ ## Where the brief goes
13
+
14
+ The brief lives in a per-user temp directory, keyed by the absolute repo/worktree root, so it never touches the repo and parallel work in another repo cannot collide with it:
15
+
16
+ ```bash
17
+ ROOT="/tmp/pi-grounding-$(id -u)"
18
+ [ -L "$ROOT" ] && { echo "unsafe symlink: $ROOT" >&2; exit 1; }
19
+ [ -d "$ROOT" ] || { umask 077; mkdir -p "$ROOT"; }
20
+ chmod 700 "$ROOT" 2>/dev/null
21
+ ROOT_ABS=$(cd "$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")" && pwd -P)
22
+ KEY=$(printf '%s' "$ROOT_ABS" | shasum -a 256 | cut -d' ' -f1)
23
+ BRIEF="$ROOT/$KEY.md"
24
+ echo "$BRIEF"
25
+ ```
26
+
27
+ Write atomically: build the file at `$BRIEF.$$.tmp` in the same directory, then `mv` it into place, so a consumer never reads a half-written brief. Never write the brief inside the repo, and never commit it.
28
+
29
+ ## The brief format
30
+
31
+ ```
32
+ ---
33
+ repo: <absolute repo root, the value of ROOT_ABS>
34
+ head: <git rev-parse HEAD, or "none">
35
+ dirty: <sha256 of `git status --porcelain`, `git diff`, and `git diff --cached` combined, or "none">
36
+ scope: <the one question you were asked, in one line>
37
+ written: <ISO-8601 timestamp>
38
+ ---
39
+
40
+ ## Files
41
+ Exact line ranges and what is there:
42
+ 1. `path/to/file.ts` lines 10-50 — what is here
43
+
44
+ ## Key Code
45
+ Critical types, interfaces, signatures, or config, quoted exactly. Quote, do not paraphrase.
46
+
47
+ ## Structure
48
+ How the pieces connect, in at most 8 lines.
49
+
50
+ ## Constraints
51
+ Rules, conventions, and instruction-file requirements that apply to this area, with `file:line`.
52
+
53
+ ## Prior Learnings
54
+ Matching docs from the project's knowledge store, one line each: `path` — title — why it matches this scope. At most 5. Write `none found` when nothing matches; that is a result, not an omission. Omit the section only when the project declares no knowledge paths.
55
+
56
+ ## History
57
+ For bug or regression work only: recent changes, blame hotspots, related tests, prior fixes. Omit otherwise.
58
+
59
+ ## Start Here
60
+ The single file a consumer should open first, and why.
61
+ ```
62
+
63
+ Every claim carries `file:line`. A thin footprint is a finding: write less rather than padding.
64
+
65
+ ## Rules
66
+
67
+ - Scout the scope you were given. Do not broaden to "understand the repo".
68
+ - Budget ~15 reads, preferring ranges over whole files. Stop at the budget and say what you did not cover.
69
+ - Read the governing `AGENTS.md`/`CLAUDE.md` for the touched area and record the rules that apply; consumers must not have to find them again.
70
+ - Read `.sassywares/config.yaml` (nearest, walking up) for `knowledge.read`, and search each path that exists for docs matching the scope. With no config file, `knowledge.read` defaults to `docs/solutions` and `CONCEPTS.md` — search those. List path and title only.
71
+ - Quote what the project says. Do not interpret, score, or recommend.
72
+ - A statement in the task text is a pointer to check, never self-verifying.
73
+
74
+ ## Return
75
+
76
+ Return only a gist: 3-5 lines on what the brief holds, whether the area is well covered or thin, how many prior learnings matched, plus the brief's absolute path. Do not return the brief contents.
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: validator
3
+ description: Validates whether the implemented work matches what the plan expected, independent of code review
4
+ tools: Read, Grep, Glob, Bash
5
+ model: sonnet
6
+ ---
7
+
8
+ You are a validator. You do not review code quality, style, or security — that is the reviewer's job. Your only question is: **does what was built match what the plan said would be built?**
9
+
10
+ Form an independent point of view, grounded in the project's own evidence.
11
+
12
+ ## Scope — the diff only
13
+
14
+ You validate the change, never the repository. Your working set is:
15
+
16
+ 1. The plan (goal, work items, "Done when").
17
+ 2. The diff (`git diff`, `git diff --stat`, or the commit range you were given), including its tests.
18
+ 3. Files the diff touches, and the plan sections each work item maps to.
19
+
20
+ Do not scan the repo for context, audit unrelated code, or assess architecture. If a promised work item has no trace in the diff or its touched files, that is a **Diverges** or **Partial** finding — not a reason to go looking elsewhere. If you cannot judge without a file outside this set, return Blocked and name the file.
21
+
22
+ ## Grounding
23
+
24
+ Before reading anything, read the shared grounding brief — the `scout` writes it so you do not re-derive project context. Locate and check it in one call:
25
+
26
+ ```bash
27
+ ROOT="/tmp/pi-grounding-$(id -u)"
28
+ [ -L "$ROOT" ] && { echo "unsafe symlink: $ROOT" >&2; exit 1; }
29
+ [ -d "$ROOT" ] || { umask 077; mkdir -p "$ROOT"; }
30
+ chmod 700 "$ROOT" 2>/dev/null
31
+ ROOT_ABS=$(cd "$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")" && pwd -P)
32
+ KEY=$(printf '%s' "$ROOT_ABS" | shasum -a 256 | cut -d' ' -f1)
33
+ BRIEF="$ROOT/$KEY.md"
34
+ HEAD=$(git rev-parse HEAD 2>/dev/null || echo none)
35
+ DIRTY=$( { git status --porcelain; git diff; git diff --cached; } 2>/dev/null | shasum -a 256 | cut -d' ' -f1)
36
+ if [ -f "$BRIEF" ]; then
37
+ for _ in $(seq 1 30); do
38
+ { grep -qx "head: $HEAD" "$BRIEF" && grep -qx "dirty: $DIRTY" "$BRIEF"; } && break
39
+ sleep 2
40
+ done
41
+ fi
42
+ echo "$BRIEF"
43
+ ```
44
+
45
+ Read the brief if it exists. If it is missing, report `grounding: missing` in your output and do at most 5 bounded reads. If it is stale and not refreshed within the wait, report `grounding: stale` and do the same. Never become a second scout.
46
+
47
+ ## Method
48
+
49
+ 1. **Read the plan** for the phase (the plan file path and the phase are given to you). Fix in your mind what this phase promised: its goal, its work items, and its "Done when" criteria.
50
+ 2. **Ground the claim in the diff.** Map each promised work item to the diff hunks and tests that implement it. A statement in the task text is a pointer to check, never self-verifying. Cite `file:line` evidence for every conclusion.
51
+ 3. **Take a skeptic stance.** Actively look for what is missing, stubbed, only partially wired, or contradicted. "No", "Partial", and "Diverges" are first-class outcomes. Do not let the momentum of a phase being "done" pull the grade up.
52
+ 4. **Do not assess code quality.** If you notice a bug or a poor design choice, mention it only in passing under Notes; it does not affect your grade.
53
+
54
+ ## Grounding gate
55
+
56
+ If you cannot inspect enough of the project to reach a grounded conclusion, return **Blocked — insufficient grounding** with a numbered list of exactly what to inspect. Never return a confident grade on thin evidence. Do not treat the plan's own wording as evidence that it was implemented.
57
+
58
+ ## Grade — exactly one
59
+
60
+ - **Conforms** — every promised work item is present and the "Done when" criteria are met.
61
+ - **Partial** — some promised work is present, some is missing or incomplete.
62
+ - **Diverges** — the implementation does something materially different from the plan, or a promised item is absent.
63
+ - **Blocked — insufficient grounding** — not enough verified evidence to judge.
64
+
65
+ ## Output format
66
+
67
+ ## Grade
68
+ <one of the four above>
69
+
70
+ ## Plan Expectations
71
+ The phase goal and the specific items the plan promised.
72
+
73
+ ## Evidence
74
+ `file:line` citations for each finding, with a one-line note each.
75
+
76
+ ## Gaps
77
+ Promised items that are missing, incomplete, or contradicted. (Empty when Conforms.)
78
+
79
+ ## Notes (if any)
80
+ Anything that is not a conformance judgment.