@jesdi/skills 0.0.19 → 0.0.21
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 +1 -1
- package/skills/crap-gate/SKILL.md +6 -2
- package/skills/crap-gate/crap.py +19 -2
- package/skills/crap-gate/run.sh +2 -1
- package/skills/crap-gate/test_cli.py +24 -0
- package/skills/implement-spec/SKILL.md +13 -4
- package/skills/red-team-data-model/SKILL.md +21 -2
- package/skills/review-diff/correctness.md +1 -1
- package/skills/to-openspec/SKILL.md +7 -2
- package/skills/to-openspec/templates/design.md +8 -0
- package/skills/to-tickets/SKILL.md +13 -3
- package/skills-manifest.json +13 -13
package/package.json
CHANGED
|
@@ -71,8 +71,12 @@ TypeScript targets still need `node` and the project's own `typescript` package.
|
|
|
71
71
|
Coverage commands still need the project's test dependencies; configure them
|
|
72
72
|
with its normal runner (for example, `cd backend && pipenv run pytest ...`).
|
|
73
73
|
The launcher preserves PATH and the caller's environment for these commands;
|
|
74
|
-
its private Python is only for the gate engine.
|
|
75
|
-
|
|
74
|
+
its private Python is only for the gate engine. One exception: when no
|
|
75
|
+
virtualenv is active and the repo root has `.venv/bin`, that directory goes
|
|
76
|
+
first on PATH, so a bare `python -m coverage` reaches the project's
|
|
77
|
+
interpreter. It does not install project dependencies or edit project
|
|
78
|
+
environments. When a command writes no report, the error ends with the last
|
|
79
|
+
lines of its log.
|
|
76
80
|
|
|
77
81
|
By default the engine runs each target's coverage command only when that
|
|
78
82
|
target has changed files, so a backend-only change never runs the frontend
|
package/skills/crap-gate/crap.py
CHANGED
|
@@ -12,6 +12,7 @@ from __future__ import annotations
|
|
|
12
12
|
|
|
13
13
|
import argparse
|
|
14
14
|
import json
|
|
15
|
+
import os
|
|
15
16
|
import subprocess
|
|
16
17
|
import sys
|
|
17
18
|
import tempfile
|
|
@@ -109,6 +110,18 @@ def _score_target(
|
|
|
109
110
|
|
|
110
111
|
# ── coverage commands ───────────────────────────────────────────────────────
|
|
111
112
|
|
|
113
|
+
def _coverage_env(root: Path) -> dict[str, str]:
|
|
114
|
+
"""The caller's environment, plus the repo's `.venv/bin` first on PATH when
|
|
115
|
+
no virtualenv is active, so a bare `python -m coverage` finds the project's
|
|
116
|
+
interpreter instead of one without its test dependencies."""
|
|
117
|
+
env = dict(os.environ)
|
|
118
|
+
venv = root / ".venv"
|
|
119
|
+
if not env.get("VIRTUAL_ENV") and (venv / "bin").is_dir():
|
|
120
|
+
env["VIRTUAL_ENV"] = str(venv)
|
|
121
|
+
env["PATH"] = f"{venv / 'bin'}{os.pathsep}{env.get('PATH', '')}"
|
|
122
|
+
return env
|
|
123
|
+
|
|
124
|
+
|
|
112
125
|
def _maybe_run_coverage(target: Target, root: Path, run_mode: str, needed: bool) -> TargetRun:
|
|
113
126
|
report = root / target.coverage_report
|
|
114
127
|
should_run = run_mode == "run" or (run_mode == "auto" and needed)
|
|
@@ -126,13 +139,17 @@ def _maybe_run_coverage(target: Target, root: Path, run_mode: str, needed: bool)
|
|
|
126
139
|
# config (same trust model as a Makefile or no-mistakes' commands.*), never
|
|
127
140
|
# user input — it needs `cd … && …`, env assignments and pipes.
|
|
128
141
|
with log.open("w") as fh:
|
|
129
|
-
proc = subprocess.run(
|
|
142
|
+
proc = subprocess.run(
|
|
143
|
+
target.coverage_command, shell=True, cwd=root, env=_coverage_env(root),
|
|
144
|
+
stdout=fh, stderr=subprocess.STDOUT,
|
|
145
|
+
)
|
|
130
146
|
seconds = time.monotonic() - started
|
|
131
147
|
fresh = report.exists() and (before is None or report.stat().st_mtime_ns > before)
|
|
132
148
|
if not fresh:
|
|
133
149
|
raise ToolError(
|
|
134
150
|
f"{target.name}: coverage command exited {proc.returncode} and wrote no report "
|
|
135
|
-
f"({target.coverage_report}); see {log.relative_to(root)}"
|
|
151
|
+
f"({target.coverage_report}); see {log.relative_to(root)}. Last lines:\n"
|
|
152
|
+
+ "\n".join(log.read_text(errors="replace").splitlines()[-10:])
|
|
136
153
|
)
|
|
137
154
|
if proc.returncode != 0:
|
|
138
155
|
print(
|
package/skills/crap-gate/run.sh
CHANGED
|
@@ -69,7 +69,8 @@ if [ ! -x "$uv" ]; then
|
|
|
69
69
|
fi
|
|
70
70
|
|
|
71
71
|
# Limit uv settings to this subprocess. Do not activate a venv or change PATH:
|
|
72
|
-
# coverage commands
|
|
72
|
+
# coverage commands inherit the caller's project environment (the engine adds
|
|
73
|
+
# only the repo's own .venv/bin, when no virtualenv is active).
|
|
73
74
|
managed_uv() (
|
|
74
75
|
unset UV_NO_MANAGED_PYTHON UV_PYTHON UV_PYTHON_DOWNLOADS UV_PYTHON_BIN_DIR
|
|
75
76
|
export UV_PYTHON_INSTALL_DIR="$cache/python"
|
|
@@ -150,3 +150,27 @@ def test_config_not_at_git_toplevel_is_a_tool_error(tmp_path, monkeypatch, capsy
|
|
|
150
150
|
monkeypatch.chdir(sub)
|
|
151
151
|
assert crap.main([]) == 2
|
|
152
152
|
assert "git repository root" in capsys.readouterr().err
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def test_coverage_command_prefers_the_repo_venv(repo, monkeypatch, capsys):
|
|
156
|
+
# A bare `python` in the command must reach the repo's .venv, not whatever
|
|
157
|
+
# interpreter the caller's PATH has (which may lack coverage).
|
|
158
|
+
monkeypatch.delenv("VIRTUAL_ENV", raising=False)
|
|
159
|
+
venv_bin = repo / ".venv" / "bin"
|
|
160
|
+
venv_bin.mkdir(parents=True)
|
|
161
|
+
(venv_bin / "venvpy").write_text('#!/bin/sh\nexec python3 "$@"\n')
|
|
162
|
+
(venv_bin / "venvpy").chmod(0o755)
|
|
163
|
+
cfg = json.loads((repo / ".crap-gate.json").read_text())
|
|
164
|
+
cfg["targets"][0]["coverage"]["command"] = "venvpy fake_cov.py"
|
|
165
|
+
(repo / ".crap-gate.json").write_text(json.dumps(cfg))
|
|
166
|
+
(repo / "pkg" / "m.py").write_text(BASE_SRC + "\n\ndef k():\n return 1\n")
|
|
167
|
+
assert crap.main([]) == 0
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def test_coverage_command_without_report_shows_the_log_tail(repo, capsys):
|
|
171
|
+
cfg = json.loads((repo / ".crap-gate.json").read_text())
|
|
172
|
+
cfg["targets"][0]["coverage"]["command"] = "echo 'No module named coverage' && exit 1"
|
|
173
|
+
(repo / ".crap-gate.json").write_text(json.dumps(cfg))
|
|
174
|
+
(repo / "pkg" / "m.py").write_text(BASE_SRC + "\n\ndef k():\n return 1\n")
|
|
175
|
+
assert crap.main([]) == 2
|
|
176
|
+
assert "No module named coverage" in capsys.readouterr().err
|
|
@@ -11,7 +11,10 @@ Changes: a model tier per subagent; a context-isolated test-writer commits
|
|
|
11
11
|
locked acceptance tests at the ticket's Seam, the implementer turns them green
|
|
12
12
|
with /tdd and reports to a contract; per-ticket review before merge, fix loop
|
|
13
13
|
capped at 4 rounds with escalation; a ruling ledger and four stop conditions;
|
|
14
|
-
a per-ticket gate (check command + crap-gate) before DONE, re-run by the reviewer;
|
|
14
|
+
a per-ticket gate (check command + crap-gate) before DONE, re-run by the reviewer;
|
|
15
|
+
already-green locked tests need a demonstrated mutation; a Codex correctness
|
|
16
|
+
pass per risky ticket; tickets touching the same functions run in sequence;
|
|
17
|
+
check command after each merge; final /review-diff on the most capable model, one
|
|
15
18
|
fixer; closes tickets only if they are issues. Review loop and ledger adapt
|
|
16
19
|
superpowers' subagent-driven-development (obra/superpowers, MIT).
|
|
17
20
|
-->
|
|
@@ -26,6 +29,8 @@ Communication to and from subagents should be sparse. Communicate primarily thro
|
|
|
26
29
|
|
|
27
30
|
Run ticket subagents in the background where possible for **maximum concurrency**.
|
|
28
31
|
|
|
32
|
+
**Every dispatch prompt says: never `git stash`, reset or check out other branches; worktrees share one stash and one ref store.**
|
|
33
|
+
|
|
29
34
|
**Name the model on every dispatch.** Omitted, it inherits yours. Exploration, test-writer, reviewer: mid tier (reviewer higher for risky diffs). Implementer: mid tier; cheapest when the ticket carries the complete code; most capable for design judgment or broad codebase work. Merger: cheapest. Escalations: one tier above the agent that got stuck. Final reviewer: most capable.
|
|
30
35
|
|
|
31
36
|
**Rule, don't stall.** Keep a **ledger** file in the notes directory: every decision as `Ruling: <what> — <why> — <cost if wrong>`, and each ticket's state, so you can resume after compaction. Don't check in between tickets. Stop and ask only for: an irreversible or destructive operation, a security-sensitive action, a side effect outside the worktrees (a push to a shared branch, a publish), or a spec so broken that every path forward is a guess.
|
|
@@ -38,15 +43,19 @@ Run ticket subagents in the background where possible for **maximum concurrency*
|
|
|
38
43
|
|
|
39
44
|
3. Create a branch, and a draft PR. If the spec and tickets are issues, mark the PR as 'closing' them.
|
|
40
45
|
|
|
41
|
-
4. Each ticket gets its own worktree and branch. For a ticket with behavioral criteria, a **test-writer subagent** goes first. It sees ONLY the spec, the ticket, CONTEXT.md/ADRs and the public interface of the ticket's **Seam** line (pointers, not summaries), never the implementer's plan or code. It writes one black-box acceptance test per criterion through that interface (defining the interface if it doesn't exist yet), confirms each fails for the right reason (missing behavior, not an import or syntax error), commits them red, and reports the SHA and files. Those files are now **locked**. A ticket with no behavioral criteria (Seam: `none — refactor`) skips this: its existing tests are the contract, unmodified.
|
|
46
|
+
4. Each ticket gets its own worktree and branch. For a ticket with behavioral criteria, a **test-writer subagent** goes first. It sees ONLY the spec, the ticket, CONTEXT.md/ADRs and the public interface of the ticket's **Seam** line (pointers, not summaries), never the implementer's plan or code. It writes one black-box acceptance test per criterion through that interface (defining the interface if it doesn't exist yet), confirms each fails for the right reason (missing behavior, not an import or syntax error), commits them red, and reports the SHA and files. A test that is already green before any implementation is vacuous until proven otherwise (an earlier guard or early return often satisfies it for an unrelated reason): the test-writer rewrites it to fail, or, when the criterion truly holds already, reports the production-code mutation that turns it red and the red output. Those files are now **locked**. A ticket with no behavioral criteria (Seam: `none — refactor`) skips this: its existing tests are the contract, unmodified.
|
|
42
47
|
|
|
43
48
|
5. An **implementer subagent** starts from that commit and makes the locked tests green, using /tdd vertical slices for anything internal. It never edits locked files and never dispatches subagents. Before reporting DONE it runs the **gate** in its worktree: the repo's check command (lint, typecheck, full test suite: `make check`, or what AGENTS.md documents) and, when the repo has `.crap-gate.json`, crap-gate scoped to the ticket (`run.sh --base <PR branch>`, or the repo's `make crap-gate` wrapper). DONE means both are green; a gate it can't turn green is BLOCKED, with the output. It reports: status (DONE, DONE_WITH_CONCERNS, NEEDS_CONTEXT or BLOCKED), commits, red→green evidence for locked tests and its own slices, the gate's final lines, files touched, concerns. If a locked test contradicts the spec or ticket, it reports BLOCKED with evidence; you rule, and either send the test-writer a correction or overrule the implementer. Handle any BLOCKED by changing something: more context, a stronger model, a split ticket, or a ruling. Never retry unchanged.
|
|
44
49
|
|
|
45
|
-
6. On DONE, a **reviewer subagent** re-runs the gate first (a red gate is a Critical finding; don't trust the report), then checks the diff against the ticket and spec, then for quality. It also checks that `git diff <test-writer-sha>..HEAD -- <locked files>` is empty and that every criterion has a locked test.
|
|
50
|
+
6. On DONE, a **reviewer subagent** re-runs the gate first (a red gate is a Critical finding; don't trust the report), then checks the diff against the ticket and spec, then for quality. It also checks that `git diff <test-writer-sha>..HEAD -- <locked files>` is empty and that every criterion has a locked test. For each locked test, it breaks the production line the test exists to protect (a temporary edit, reverted after) and confirms that test goes red; a test that stays green is Critical. It re-runs every mutation the test-writer reported. Name your specific suspicions in the reviewer prompt (a sibling caller, a key built from the old identity, a guard another ticket added): named suspicions find regressions a generic review misses.
|
|
51
|
+
|
|
52
|
+
A **risky** ticket touches shared state, persistence keys or identities, concurrency, money or auth. For those, run the correctness pass from /review-diff yourself, in parallel with the reviewer: `codex exec` with that skill's `correctness.md` on range `<PR branch>...<ticket branch>` (three dots: from the merge-base, so tickets merged meanwhile don't show up), in quick mode (the command is in the review-diff skill). Its findings join the reviewer's, with the same severities.
|
|
53
|
+
|
|
54
|
+
Critical or Important findings start a fix loop of at most 4 rounds, each a fix plus a re-review scoped to that fix: rounds 1-2 resume the implementer; rounds 3-4 go to a fresh implementer one tier up. After round 4, rule on each open finding in the ledger and move on. Minor findings go to the ledger for the final review.
|
|
46
55
|
|
|
47
56
|
7. Once a ticket passes review, a **merger subagent** merges it to the PR branch and runs the repo's check command (lint, typecheck, full suite). If it fails, an implementer fixes the PR branch before the next merge.
|
|
48
57
|
|
|
49
|
-
8. If this changes the **frontier** of available tickets, start the next tickets. This allows for maximum concurrency.
|
|
58
|
+
8. If this changes the **frontier** of available tickets, start the next tickets. This allows for maximum concurrency. Exception: two ready tickets that change the same function never run at once. Compare their **Touches** lines (or ask the exploration subagent where each will land); on overlap, start one and hold the other until the first merges, then branch it from the updated PR branch. Record the hold as a ruling.
|
|
50
59
|
|
|
51
60
|
9. Once all tickets are complete, a reviewer on the most capable model runs /review-diff on the PR branch, given the ledger's minor findings and rulings. One **implementer subagent** fixes every finding, then re-review that fix once. Rule on anything left.
|
|
52
61
|
|
|
@@ -40,11 +40,30 @@ Given the tables/fields (from `design.md` or a sketch), produce:
|
|
|
40
40
|
4. **Permissions** — who can see or mutate what; staff vs. customer vs. owner
|
|
41
41
|
boundaries; what an authenticated-but-wrong-role request can still reach.
|
|
42
42
|
|
|
43
|
+
## Identity inventory (when the change widens a key)
|
|
44
|
+
|
|
45
|
+
When the change widens an identity or key space (`issue` becomes
|
|
46
|
+
`target#issue`, `user` becomes `tenant+user`), the top 5 is not enough: one
|
|
47
|
+
missed identity is a cross-tenant bug. After the top 5, grep the code for every
|
|
48
|
+
identity built from the old key and list each one as **covered** (the design
|
|
49
|
+
rekeys it) or **out of scope** (with the reason). Look for:
|
|
50
|
+
|
|
51
|
+
- file and directory names (`task-{N}.json`, `messages/{issue}.jsonl`),
|
|
52
|
+
including legacy files a save or migration retires;
|
|
53
|
+
- hashes, fingerprints and dedupe keys;
|
|
54
|
+
- cache keys, lock names, markers, dict and set keys;
|
|
55
|
+
- command and URL arguments that take the bare key (`/attach N`);
|
|
56
|
+
- log and event fields other code reads back.
|
|
57
|
+
|
|
58
|
+
This list is exhaustive, not ranked. It is not a fix: say what is keyed by
|
|
59
|
+
the old identity, not how to rekey it.
|
|
60
|
+
|
|
43
61
|
## What NOT to do
|
|
44
62
|
|
|
45
63
|
- Don't suggest schema changes, indexes, or constraints — that's the design
|
|
46
64
|
session's job, after this list exists.
|
|
47
65
|
- Don't hedge with "it depends" — pick the worst plausible interpretation and
|
|
48
66
|
state its consequence.
|
|
49
|
-
- Don't produce more than 5. Rank and cut; the top failure
|
|
50
|
-
a complete list.
|
|
67
|
+
- Don't produce more than 5 failure scenarios. Rank and cut; the top failure
|
|
68
|
+
matters more than a complete list. (The identity inventory is the one
|
|
69
|
+
exhaustive list.)
|
|
@@ -18,7 +18,7 @@ Read `git diff <range>` in full, then only the surrounding code a check needs
|
|
|
18
18
|
| N+1 | One query per loop iteration where a join or `IN (…)` would do. |
|
|
19
19
|
| Migrations | Not reversible, or unsafe on a live table (a NOT NULL column without a default, a rewrite under lock). |
|
|
20
20
|
| Failure paths | A payment-provider, checkout or stock-decrement call whose failure (timeout, decline, provider error) is unhandled or silently swallowed. |
|
|
21
|
-
| Test quality | Tautological tests (asserting a mock's return value, or a value the test just set with no code in between) and tests on internals instead of the public seam. Say what they should assert. |
|
|
21
|
+
| Test quality | Tautological tests (asserting a mock's return value, or a value the test just set with no code in between) and tests on internals instead of the public seam. Unreadable tests, which protect nothing because nobody can tell what they guarantee: a name that doesn't state the behavior, one test asserting several behaviors, logic in the test (`if`, loops), setup that hides what the test depends on, fixtures shared and mutated across tests. Say what they should assert, or how to split them. |
|
|
22
22
|
|
|
23
23
|
Every finding: `file:line`, the concrete failure scenario (inputs or
|
|
24
24
|
interleaving → wrong result), and the fix. "Consider reviewing" is not a
|
|
@@ -43,12 +43,15 @@ the spec before the design is written. Don't write code.
|
|
|
43
43
|
Run only when asked (for example "/to-openspec <slug> stage 2"), after the human has reviewed
|
|
44
44
|
stage 1. Re-read `proposal.md` and `spec.md` first; the human may have edited them.
|
|
45
45
|
|
|
46
|
-
1. Run the `red-team-data-model` skill against the data model. Print the top 5
|
|
47
|
-
to a file.
|
|
46
|
+
1. Run the `red-team-data-model` skill against the data model. Print the top 5, and its identity
|
|
47
|
+
inventory when the change widens a key; don't write them to a file.
|
|
48
48
|
2. Write `specs/<slug>/design.md`:
|
|
49
49
|
- **Decisions**: one line each with its tradeoff. Include the ones the red-team findings force.
|
|
50
50
|
- **Data model**: every invariant a DB constraint can enforce (`CHECK`, `UNIQUE`, `NOT NULL`,
|
|
51
51
|
FK, conditional `UPDATE ... WHERE`) goes in the table, not only in app code.
|
|
52
|
+
- **Identities**: when the change widens a key, every item of the red-team's identity
|
|
53
|
+
inventory, marked covered (task IDs filled in step 3) or out of scope (why). Otherwise "None." Add the
|
|
54
|
+
heading when the repo's template lacks it.
|
|
52
55
|
- **Seams**: the endpoint, function, or command the tests drive through, marked existing or
|
|
53
56
|
new. Prefer one high seam.
|
|
54
57
|
3. Write `specs/<slug>/tasks.md`: vertical slices, each small enough for one commit and one green
|
|
@@ -58,6 +61,8 @@ stage 1. Re-read `proposal.md` and `spec.md` first; the human may have edited th
|
|
|
58
61
|
makes the list a task graph `implement-spec` can run directly.
|
|
59
62
|
- A slice adds only the tables and columns its own scenarios need, not the whole model up front.
|
|
60
63
|
- No standalone "run the checks" task: every task already ends with the check command green.
|
|
64
|
+
- Then fill the task IDs into `design.md`'s **Identities**: every identity marked covered names
|
|
65
|
+
the task that rekeys it. A covered identity with no task is a missing task; add it.
|
|
61
66
|
|
|
62
67
|
Print the task list, then **Open questions**: every red-team finding the design leaves
|
|
63
68
|
unresolved, and every input the design assumes but the sources don't provide. Then stop. Don't
|
|
@@ -14,6 +14,14 @@ Tables/fields touched or added, and the invariants that go in DB constraints (no
|
|
|
14
14
|
|---|---|---|---|
|
|
15
15
|
| | | | |
|
|
16
16
|
|
|
17
|
+
## Identities
|
|
18
|
+
|
|
19
|
+
When this change widens a key, each identity built from the old key (file names, hashes,
|
|
20
|
+
dedupe keys, command args, dict keys): covered by which task, or out of scope and why. Otherwise
|
|
21
|
+
"None."
|
|
22
|
+
|
|
23
|
+
- `<identity>` — covered by <task> | out of scope: <why>.
|
|
24
|
+
|
|
17
25
|
## Seams
|
|
18
26
|
|
|
19
27
|
Where tests drive through: module, function, command, or endpoint. Mark each existing or new.
|
|
@@ -9,8 +9,9 @@ Modified copy of https://github.com/mattpocock/skills/tree/3cca18b368ae95cdbdebb
|
|
|
9
9
|
Changes: tickets always go to `.agent/tickets/<NN>-<slug>.md` (no tracker path);
|
|
10
10
|
numbering is contiguous from 01 in dependency order; acceptance criteria must state
|
|
11
11
|
observable behavior; every ticket names its **Seam** (the public interface its
|
|
12
|
-
acceptance tests hit)
|
|
13
|
-
invocation is
|
|
12
|
+
acceptance tests hit) and what it **Touches** (files and functions, for
|
|
13
|
+
scheduling); the approval quiz is skipped when unattended; model invocation is
|
|
14
|
+
allowed.
|
|
14
15
|
-->
|
|
15
16
|
|
|
16
17
|
# To Tickets
|
|
@@ -53,6 +54,7 @@ When a human is in the loop, present the proposed breakdown as a numbered list.
|
|
|
53
54
|
- **Title**: short descriptive name
|
|
54
55
|
- **Blocked by**: which other tickets (if any) must complete first
|
|
55
56
|
- **Seam**: the public interface its acceptance tests hit
|
|
57
|
+
- **Touches**: the files and functions it expects to change
|
|
56
58
|
- **What it delivers**: the end-to-end behaviour this ticket makes work
|
|
57
59
|
|
|
58
60
|
Ask the user:
|
|
@@ -85,6 +87,8 @@ Do NOT close or modify any parent issue.
|
|
|
85
87
|
|
|
86
88
|
**Seam:** the public interface the acceptance tests hit (a function, an HTTP route, a CLI command, a config loader…), or `none — refactor`.
|
|
87
89
|
|
|
90
|
+
**Touches:** the files, and the functions within them, this ticket expects to change.
|
|
91
|
+
|
|
88
92
|
- [ ] Acceptance criterion 1
|
|
89
93
|
- [ ] Acceptance criterion 2
|
|
90
94
|
|
|
@@ -102,4 +106,10 @@ Every ticket carries a **Seam** line: the one public interface through which its
|
|
|
102
106
|
|
|
103
107
|
</seam-rule>
|
|
104
108
|
|
|
105
|
-
|
|
109
|
+
<touches-rule>
|
|
110
|
+
|
|
111
|
+
The **Touches** line is a best guess, for scheduling: `implement-spec` never runs two tickets at once that change the same function, because parallel restructures of one function turn into rebase churn and broken locked tests. Name functions, not only files, when a file is shared (`dispatcher/main.py: _run_pass, _resume_woken`). Two tickets restructuring the same function is also a hint to add a blocking edge between them, or to merge them.
|
|
112
|
+
|
|
113
|
+
</touches-rule>
|
|
114
|
+
|
|
115
|
+
Outside the **Touches** line, avoid specific file paths or code snippets: they go stale fast. Exception: if a prototype produced a snippet that encodes a decision more precisely than prose can (state machine, reducer, schema, type shape), inline it and note briefly that it came from a prototype. Trim to the decision-rich parts, not a working demo, just the important bits.
|
package/skills-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"generatedAt": "2026-09-24T19:16:41.414Z",
|
|
4
4
|
"skills": [
|
|
5
5
|
{
|
|
6
6
|
"name": "backlog",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"name": "crap-gate",
|
|
25
|
-
"version": "0.1.
|
|
26
|
-
"hash": "sha256-
|
|
25
|
+
"version": "0.1.4",
|
|
26
|
+
"hash": "sha256-a3fe7bcb7ad6566aa25c44b0bc7823c625b536b4f3eb5cdfe73e6628ad04ee05",
|
|
27
27
|
"description": "Score every function a branch changed with CRAP (cyclomatic complexity × untested fraction), fail on existing functions above 15 and new functions above 9, and drive a fixer + independent reviewer loop until the gate passes. Use when implementation is done and before pushing, when the user says \"run the crap gate\", \"check CRAP\", \"is this change tested enough\", or when a push gate reports CRAP violations."
|
|
28
28
|
},
|
|
29
29
|
{
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"name": "implement-spec",
|
|
49
|
-
"version": "0.1.
|
|
50
|
-
"hash": "sha256-
|
|
49
|
+
"version": "0.1.2",
|
|
50
|
+
"hash": "sha256-ae8c88981b359c9b19ba285bacc38264ba11dca163be7b1fde4ff73ac278465b",
|
|
51
51
|
"description": "Implement a specification in code."
|
|
52
52
|
},
|
|
53
53
|
{
|
|
@@ -64,20 +64,20 @@
|
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
"name": "red-team-data-model",
|
|
67
|
-
"version": "0.1.
|
|
68
|
-
"hash": "sha256-
|
|
67
|
+
"version": "0.1.1",
|
|
68
|
+
"hash": "sha256-37737ab44c3c2f4812ceedbf2a14cdb259ceca0c8d8b9bb9ac9af92b23742808",
|
|
69
69
|
"description": "Attack a proposed or existing data model for the ways it breaks under real conditions — concurrency, time windows, money, permissions — without proposing a redesign. Use right after sketching a data model, before writing the spec, so the top failure scenarios shape the spec's requirements and tests instead of getting discovered mid-build. Trigger on \"red-team my data model\", \"what breaks in this schema\", or \"/red-team\"."
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
"name": "review-diff",
|
|
73
|
-
"version": "0.1.
|
|
74
|
-
"hash": "sha256-
|
|
73
|
+
"version": "0.1.1",
|
|
74
|
+
"hash": "sha256-ac4b526f0436f06acc4e5e2254b83b5318a14065caab3f922f20fa7da9e87c5f",
|
|
75
75
|
"description": "Review a branch before merge: first a gate (the repo's check command plus crap-gate), then three independent reviewers in parallel — spec (did we build what was asked, no more, no less), correctness via Codex (races, idempotency, money, time, authz, indexes, N+1, migrations, error paths, test quality) and structure (deep-quality-review). `--quick` runs only spec and correctness, shortened, for a live interview. Use when the user says \"/review-diff\", \"review this branch\", \"review this slice\", \"review before merge\", or before closing out a spec task."
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
"name": "to-openspec",
|
|
79
|
-
"version": "0.1.
|
|
80
|
-
"hash": "sha256-
|
|
79
|
+
"version": "0.1.1",
|
|
80
|
+
"hash": "sha256-223f00ac309e5365e77708e8f3fc22c36a02e52f4c071af54ea25ea4d9461965",
|
|
81
81
|
"description": "Turn settled discovery notes and a sketched data model into a spec folder in openspec shape (proposal, spec, design, tasks) under specs/<slug>/. Runs in two stages with a human review between them. No interview, just synthesis of decisions already made. Trigger on \"write the spec\", \"to-openspec\", or \"/to-openspec <slug> [stage 2]\"."
|
|
82
82
|
},
|
|
83
83
|
{
|
|
@@ -88,8 +88,8 @@
|
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
"name": "to-tickets",
|
|
91
|
-
"version": "0.1.
|
|
92
|
-
"hash": "sha256-
|
|
91
|
+
"version": "0.1.2",
|
|
92
|
+
"hash": "sha256-13e639c6412c6d875d285e452fd0f8c64597c4653cedbbe0e7aa0c19cd717ec1",
|
|
93
93
|
"description": "Break a spec, plan, or the current conversation into numbered tracer-bullet ticket files under .agent/tickets/, each declaring its blocking edges and acceptance criteria phrased as observable behavior. Use after a spec is approved and before implementation starts."
|
|
94
94
|
},
|
|
95
95
|
{
|