@jesdi/skills 0.0.41 → 0.0.42
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/implement-spec/ARCHITECTURE.md +2 -0
- package/skills/implement-spec/README.md +2 -2
- package/skills/implement-spec/driver.py +1 -1
- package/skills/implement-spec/driver_final.py +2 -1
- package/skills/implement-spec/prompts/final-fixer.md +2 -1
- package/skills/implement-spec/prompts/fixer.md +2 -1
- package/skills/implement-spec/prompts/implementer.md +2 -1
- package/skills/implement-spec/tests/test_agents.py +1 -1
- package/skills/implement-spec/tests/test_driver.py +1 -0
- package/skills/implement-spec/tests/test_final.py +6 -1
- package/skills/implement-spec/tests/test_review.py +15 -0
- package/skills-manifest.json +3 -3
package/package.json
CHANGED
|
@@ -112,6 +112,8 @@ and do not know about the run, except `driver_run.py`, which the three deciding
|
|
|
112
112
|
provider of the implementer.
|
|
113
113
|
- A red gate on the implementer's or a fixer's commit is a finding of the next round (`driver_fixloop._gate`), so
|
|
114
114
|
it blocks only after round 4. A red gate on a test-writer correction blocks.
|
|
115
|
+
- The implementer and each fixer get the `--gate` command and run it before they report. The gate of the driver
|
|
116
|
+
stays the source of truth: an agent's run of the gate counts for nothing.
|
|
115
117
|
|
|
116
118
|
### Questions
|
|
117
119
|
|
|
@@ -95,7 +95,7 @@ Everything is under `.agent/`, which is never committed.
|
|
|
95
95
|
A ticket is ready when each ticket in its **Blocked by** line is merged and no running ticket touches the same place. The places are the backticked entries of the **Touches** lines: `file` or `file: function`. Two entries are the same place when they name the same file and the same function, or when one of them names the whole file. Each ready ticket takes the lowest free slot.
|
|
96
96
|
|
|
97
97
|
1. **test-writer** (`prompts/test-writer.md`). It writes one black-box test for each criterion through the Seam and commits them red. Those files are locked. A ticket with Seam `none — refactor` has no test-writer.
|
|
98
|
-
2. **implementer** (`prompts/implementer.md`). It starts from that commit and makes the locked tests green.
|
|
98
|
+
2. **implementer** (`prompts/implementer.md`). It starts from that commit and makes the locked tests green. Its prompt gives the `--gate` command: it runs the gate on its final commit and makes it green before it reports DONE or DONE_WITH_CONCERNS.
|
|
99
99
|
3. **Gate.** The driver runs `--gate` on the ticket tip.
|
|
100
100
|
4. **Review.** The driver compares each locked file of the ticket with the test-writer commit. A file that differs is a critical finding `locked file changed: <path>`. Then the **reviewer** (`prompts/reviewer.md`) runs, and for a ticket with a **Risk** line the **correctness** pass (`prompts/correctness.md`) runs at the same time in the same slot.
|
|
101
101
|
5. **Merge.** The driver merges the reviewed tip into the PR branch with git plumbing, then deletes the ticket branch. A conflict goes to the **conflict** agent (`prompts/conflict.md`) once. Its resolution may change no locked file of the ticket. A second conflict blocks the ticket.
|
|
@@ -117,7 +117,7 @@ Rules for each agent:
|
|
|
117
117
|
| `critical` or `important` | One fix round. |
|
|
118
118
|
| `minor` | It stays in the ledger and in the findings file. The final reviewer gets the list. |
|
|
119
119
|
|
|
120
|
-
A fix round is one **fixer** (`prompts/fixer.md`), then the gate on the new tip, then a re-review of the range of the fix. A mutation proof is repeated only when the fix changed its production line.
|
|
120
|
+
A fix round is one **fixer** (`prompts/fixer.md`), which runs the gate on its final commit before it reports, as the implementer does, then the gate of the driver on the new tip, then a re-review of the range of the fix. A mutation proof is repeated only when the fix changed its production line.
|
|
121
121
|
|
|
122
122
|
A red gate on the commit of the implementer or of a fixer is a critical finding with source `gate`. Its file is the gate record, and the record holds the output. No review runs on that tip, and the next round starts: a red gate on the commit of the implementer starts round 1. The review after that round covers each fix since the last review and repeats each proof that one of them made due. A red gate after round 4 blocks the ticket, as does a red gate on the commit of a test-writer correction: the correction is outside the fix rounds, and a fixer may not edit the locked files.
|
|
123
123
|
|
|
@@ -81,7 +81,7 @@ def _prompt_values(ticket: Ticket, slot: str, run: Run) -> dict[str, str]:
|
|
|
81
81
|
folder = OUT / ticket.number
|
|
82
82
|
return {"spec": os.path.relpath(run.args.spec, slot), "seam": ticket.seam, "pr_branch": run.pr,
|
|
83
83
|
"branch": f"ticket/{ticket.number}", "ticket": os.path.relpath(Path(run.args.tickets) / ticket.file, slot),
|
|
84
|
-
"correctness": str(driver_review.CORRECTNESS),
|
|
84
|
+
"correctness": str(driver_review.CORRECTNESS), "gate": run.args.gate,
|
|
85
85
|
"blocked_report": os.path.relpath(_blocked_report(ticket.number, run), slot),
|
|
86
86
|
"writer_report": os.path.relpath(folder / "test-writer-0.json", slot)}
|
|
87
87
|
|
|
@@ -79,7 +79,8 @@ def finish_interrupted_move(state: State, pr: str) -> None:
|
|
|
79
79
|
|
|
80
80
|
def _prompt_values(run: Run) -> dict[str, str]:
|
|
81
81
|
"""The pointers every prompt of the end of run gets. Its agents work in slot 1, the PR worktree."""
|
|
82
|
-
return {"spec": run.args.spec, "tickets": run.args.tickets, "pr_branch": run.pr, "branch": run.pr
|
|
82
|
+
return {"spec": run.args.spec, "tickets": run.args.tickets, "pr_branch": run.pr, "branch": run.pr,
|
|
83
|
+
"gate": run.args.gate}
|
|
83
84
|
|
|
84
85
|
|
|
85
86
|
def _title(finding: dict) -> str:
|
|
@@ -11,7 +11,8 @@ Findings to fix:
|
|
|
11
11
|
Fix each finding in the list as one batch, in one commit or in several. Leave the minor findings of the findings file.
|
|
12
12
|
Each commit belongs to one ticket: the ticket whose criterion or code the commit changes. A fix for two tickets is two commits.
|
|
13
13
|
Never edit a locked file: each one stays as it is at {start_sha}, and a locked file that differs is a critical finding of the next review.
|
|
14
|
-
Use targeted tests while you work.
|
|
14
|
+
Use targeted tests while you work.
|
|
15
|
+
Before you report DONE or DONE_WITH_CONCERNS, run the gate on your final commit, with IMPLEMENT_SPEC_BASE={pr_branch} in the environment: `{gate}`. Fix each failure, commit, and run it again until it is green. The driver runs the gate again on your final commit, and a scoped review reads your commits.
|
|
15
16
|
Commit your work on the checked-out PR branch and change no commit that is on it now. Do not dispatch subagents.
|
|
16
17
|
In `commits`, give every commit you made with the number of its ticket: the driver names each commit `fix(NN): <your subject>` from it, and a commit with no ticket is a violation. In `green`, give the summary lines of the passing test output.
|
|
17
18
|
|
|
@@ -10,7 +10,8 @@ Findings of the review: {findings}
|
|
|
10
10
|
Fix each finding of severity critical or important in the findings file. Leave the minor findings: the final review gets them. Leave each finding of kind `fixture` and each finding of kind `test` on a locked file: the test-writer corrects those.
|
|
11
11
|
Never edit a locked file. The one exception is a finding `locked file changed`: make that file equal to its content at {test_writer_sha}.
|
|
12
12
|
If a locked test contradicts the spec or the ticket, so that no fix can make it green, stop and report BLOCKED with a concern that starts with `locked test contradicts spec:`, then the test and the evidence.
|
|
13
|
-
Use targeted tests while you work.
|
|
13
|
+
Use targeted tests while you work.
|
|
14
|
+
Before you report DONE or DONE_WITH_CONCERNS, run the gate on your final commit, with IMPLEMENT_SPEC_BASE={pr_branch} in the environment: `{gate}`. Fix each failure, commit, and run it again until it is green. The driver runs the gate again on your final commit, and a re-review reads the lines you changed.
|
|
14
15
|
A finding from the `gate` is a red gate: its file is the gate record. Read the output there and make the gate green.
|
|
15
16
|
Commit your work on the checked-out ticket branch. Do not dispatch subagents.
|
|
16
17
|
In `ticket`, give the number of the ticket that owns your commits. In `green`, give the summary lines of the passing test output.
|
|
@@ -9,7 +9,8 @@ Locked files: {locked}
|
|
|
9
9
|
Make the locked tests green and meet each criterion of the ticket. For internal code, work in vertical test-first slices: one failing test, the smallest code that passes it, then the next slice.
|
|
10
10
|
Never edit a locked file. If a locked test contradicts the spec or the ticket, stop and report BLOCKED with a concern that starts with `locked test contradicts spec:`, then the test and the evidence.
|
|
11
11
|
Commit your work on the checked-out ticket branch. Do not dispatch subagents.
|
|
12
|
-
Run targeted tests while you work.
|
|
12
|
+
Run targeted tests while you work.
|
|
13
|
+
Before you report DONE or DONE_WITH_CONCERNS, run the gate on your final commit, with IMPLEMENT_SPEC_BASE={pr_branch} in the environment: `{gate}`. Fix each failure, commit, and run it again until it is green. The driver runs the gate again on your final commit.
|
|
13
14
|
In `green`, give the summary lines of the passing test output.
|
|
14
15
|
|
|
15
16
|
Write one JSON report at {report} that matches this schema:
|
|
@@ -247,7 +247,7 @@ def test_implementer_prompt_carries_pointers_and_only_template_sentences(env):
|
|
|
247
247
|
for prefix in (str(w.repo.resolve()) + "/", str(w.repo) + "/"):
|
|
248
248
|
prompt = prompt.replace(prefix, "")
|
|
249
249
|
for value in (report, "specs/csv/spec.md", ".agent/tickets/01-export-rows.md", "`export_csv()`", sha,
|
|
250
|
-
"tests/test_export.py"):
|
|
250
|
+
"tests/test_export.py", "feat/csv", "true"):
|
|
251
251
|
prompt = prompt.replace(value, "")
|
|
252
252
|
lines = lambda text: {" ".join(l.split()) for l in text.splitlines() if l.strip()}
|
|
253
253
|
assert lines(prompt) <= lines(re.sub(r"\{[a-z_]+\}", "", template))
|
|
@@ -229,6 +229,7 @@ def test_a_rerun_prompt_holds_only_template_lines_and_keeps_its_ending(repo, tmp
|
|
|
229
229
|
prompt = prompt_of(tmp_path)
|
|
230
230
|
first = driver_agents.render("implementer", {
|
|
231
231
|
"spec": "spec.md", "ticket": ".agent/tickets/01-t.md", "seam": "none — refactor", "locked": "",
|
|
232
|
+
"gate": "true", "pr_branch": "feat/x",
|
|
232
233
|
"start_sha": subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True, text=True).stdout.strip(),
|
|
233
234
|
"report": ".agent/implement/01/implementer-0.json"})
|
|
234
235
|
ending = first[first.index("\nWrite one JSON report"):]
|
|
@@ -31,7 +31,7 @@ from types import SimpleNamespace
|
|
|
31
31
|
import pytest
|
|
32
32
|
|
|
33
33
|
from test_cli import git, ticket
|
|
34
|
-
from test_review import FABLE, HOOKED, ONE, OPUS, Review, finding, review
|
|
34
|
+
from test_review import FABLE, HOOKED, ONE, OPUS, Review, finding, gate_rule, review
|
|
35
35
|
from test_stops import UNATTENDED, decisions, stage
|
|
36
36
|
from test_walk import impl, plan, tw
|
|
37
37
|
|
|
@@ -296,6 +296,11 @@ def test_two_findings_make_one_fixer_batch_of_fix_commits_on_top_of_the_unchange
|
|
|
296
296
|
assert ref(fixed.repo, "feat/csv~2") == reviewed
|
|
297
297
|
|
|
298
298
|
|
|
299
|
+
def test_the_fixer_of_the_final_review_gets_the_gate_command_and_runs_it_before_it_reports(fixed):
|
|
300
|
+
(batch,) = fixed.final_calls("fixer")
|
|
301
|
+
gate_rule(batch["prompt"], str(fixed.rig / "gate"))
|
|
302
|
+
|
|
303
|
+
|
|
299
304
|
def test_a_scoped_review_covers_the_range_after_the_reviewed_tip_and_one_gate_runs_on_the_new_tip(fixed):
|
|
300
305
|
reviewed, tip = fixed.final_calls("final-reviewer")[0]["head"], fixed.branch()
|
|
301
306
|
first, scoped = fixed.final_calls("final-reviewer")
|
|
@@ -194,6 +194,21 @@ def test_each_round_ends_with_one_gate_record_and_a_re_review_scoped_to_the_fix(
|
|
|
194
194
|
assert tips[k - 1][:7] in reviews[k]["prompt"] and tips[k][:7] in reviews[k]["prompt"], k
|
|
195
195
|
|
|
196
196
|
|
|
197
|
+
def gate_rule(prompt, gate):
|
|
198
|
+
"""The line of `prompt` that gives the gate command; it must say to run it before the report."""
|
|
199
|
+
(line,) = [l for l in prompt.splitlines() if f"`{gate}`" in l]
|
|
200
|
+
assert "IMPLEMENT_SPEC_BASE=feat/csv" in line and "Before you report DONE" in line, line
|
|
201
|
+
return line
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def test_the_implementer_and_each_fixer_get_the_gate_command_and_run_it_before_they_report(escalated):
|
|
205
|
+
gate = str(escalated.rig / "gate")
|
|
206
|
+
agents = escalated.calls("01", "implementer") + escalated.calls("01", "fixer")
|
|
207
|
+
assert len(agents) == 4, "the implementer and the fixers of rounds 1, 2 and 3 (the next model)"
|
|
208
|
+
for call in agents:
|
|
209
|
+
gate_rule(call["prompt"], gate)
|
|
210
|
+
|
|
211
|
+
|
|
197
212
|
def test_reports_are_named_by_role_and_round(escalated):
|
|
198
213
|
for name in ("reviewer-0", "reviewer-1", "reviewer-2", "reviewer-3", "fixer-1", "fixer-2", "fixer-3"):
|
|
199
214
|
assert (escalated.folder() / f"{name}.json").exists(), name
|
package/skills-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-16T10:22:13.328Z",
|
|
4
4
|
"skills": [
|
|
5
5
|
{
|
|
6
6
|
"name": "backlog",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"name": "implement-spec",
|
|
49
|
-
"version": "0.1.
|
|
50
|
-
"hash": "sha256-
|
|
49
|
+
"version": "0.1.18",
|
|
50
|
+
"hash": "sha256-b10cd79532e2c8a33ddb8c55934ee26ee7f98d104ff7805bc3e2b819d0bb9241",
|
|
51
51
|
"description": "Implement a specification in code."
|
|
52
52
|
},
|
|
53
53
|
{
|