Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugin-creator/.tessl-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tessl/plugin-creator",
"version": "0.1.1",
"version": "0.1.2",
"description": "Create a Tessl plugin: wrap your existing skills into a versioned, shareable bundle, decide what else it needs (rules, commands, MCP servers), validate, and publish.",
"private": false,
"skills": "./skills/"
Expand Down
31 changes: 31 additions & 0 deletions plugin-creator/evals/scenario-5/criteria.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"context": "Tests whether the agent authors a new plugin in a repo-owned source directory rather than under .tessl/plugins/, which is pre-seeded in the working directory as Tessl's installed-content cache (a populated tessl/pr-reviewer plugin). The agent must recognise that .tessl/plugins/ is a cache, not a source location, place the new plugin somewhere it controls and commits, leave the existing cache untouched, and validate with the correct lint command. This directly exercises the guidance added to build-composition to stop agents thrashing on where to author plugin source.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Source NOT under .tessl/plugins/",
"description": "The newly authored commit-writer plugin (its .tessl-plugin/plugin.json and skill SKILL.md) is NOT located anywhere under the .tessl/plugins/ directory. Authoring the new plugin inside .tessl/plugins/ is a hard failure for this item.",
"max_score": 35
},
{
"name": "Repo-owned source directory used",
"description": "The new plugin is authored in a repo-owned source directory the developer would commit — e.g. tessl-plugins/commit-writer/, plugins/commit-writer/, or another top-level project directory (including the working-directory root). Full marks for tessl-plugins/<name>/ or plugins/<name>/; partial credit for another sensible repo-owned location.",
"max_score": 25
},
{
"name": "Install cache left intact",
"description": "The pre-existing .tessl/plugins/tessl/pr-reviewer/ cache contents are left unmodified — the agent did not write its new plugin into, overwrite, or delete anything in the install cache.",
"max_score": 12
},
{
"name": "Wired into tessl.json via file:",
"description": "The new plugin is referenced from tessl.json as a local dependency using a file: path (e.g. file:tessl-plugins/commit-writer), confirming it is treated as committed, repo-owned source rather than installed content. This is filesystem-observable, unlike whether a lint command was run.",
"max_score": 18
},
{
"name": "Valid plugin produced",
"description": "A structurally valid plugin exists: a .tessl-plugin/plugin.json with name (tessl/commit-writer), version, and description, plus a skills/<verb-name>/SKILL.md with a frontmatter description.",
"max_score": 10
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "tessl/pr-reviewer",
"version": "1.2.0",
"description": "Review a pull request: check for logic bugs, style consistency, and security concerns, then summarise findings.",
"private": false,
"skills": "./skills/"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
name: review-pull-request
description: Use when reviewing a pull request, to check for logic bugs, style consistency, and security concerns and summarise the findings for the author.
---

# Review a pull request

1. Read the diff and understand what the change is trying to do.
2. Check for logic bugs and missed edge cases.
3. Check style consistency against the surrounding code.
4. Flag security concerns (secrets, auth, input handling).
5. Summarise findings grouped by severity, with concrete suggestions.
10 changes: 10 additions & 0 deletions plugin-creator/evals/scenario-5/scenario.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"description": "Author location — avoid the .tessl/plugins install cache, use a repo-owned source dir",
"fixtures": {
"install-cache": {
"type": "directory",
"path": "./inputs/install-cache",
"installPath": ".tessl/plugins"
}
}
}
24 changes: 24 additions & 0 deletions plugin-creator/evals/scenario-5/task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Package a commit-message skill as a Tessl plugin

## Background

You are working inside an existing repository that already uses Tessl. The team
wants a reusable Tessl plugin that helps an agent write Conventional Commits
style commit messages: one skill that, given a staged diff, produces a properly
formatted commit message (type, optional scope, imperative summary, body, and
footer).

This is a simple, self-contained workflow, so a single skill is the right shape.

## Your task

Create the plugin on disk in this repository, ready to validate:

- Scaffold a Tessl plugin named `commit-writer` in the `tessl` workspace, with a
single skill that writes Conventional Commits messages.
- Author the skill's `SKILL.md` with a strong description (what it does and when
to reach for it) and a few ordered steps.
- Run the appropriate Tessl CLI validation to confirm the plugin is structurally
sound.

Do not publish. Leave the finished plugin on disk in the repository.
22 changes: 17 additions & 5 deletions plugin-creator/skills/build-composition/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Turn the confirmed plan into real files, in the right place. Do not re-litigate

## 1. Scaffold the plugin once

First choose **where** to author it: a repo-owned directory you commit, defaulting to `tessl-plugins/<plugin-name>/` when `.tessl/memory/preferences/plugins.md` names no other. **Never author under `.tessl/plugins/`** — that is Tessl's installed-content cache, not source. See [references/plugin-anatomy.md](references/plugin-anatomy.md).

Create the plugin skeleton with the CLI. Inspect `tessl plugin new --help` first, and note two things it requires:
- Pass `--skill` (with `--skill-name` and `--skill-description`) or `--rules` to seed initial content; it errors with neither.
- Pass `--workspace <name>` explicitly. The workspace in `--name workspace/plugin` is **not** parsed from the name.
Expand Down Expand Up @@ -47,19 +49,29 @@ Only add what the plan specified, do not pad.

## 5. Validate with lint AND pack

Lint checks structure; pack confirms what actually ships. Because lint can pass on a mis-nested skill, always do both:
`tessl plugin lint <plugin-dir>` is the primary structural check; pack confirms what actually ships. Because lint can pass on a mis-nested skill, always do both:

```bash
tessl plugin lint <plugin-dir>
tessl plugin pack <plugin-dir> --output /tmp/check.tgz
tar tzf /tmp/check.tgz | grep SKILL.md # every intended skill must appear
tar tzf /tmp/check.tgz | grep -E '(^|/)rules/[^/]+\.md$' || true # any rules the plan called for
tar tzf /tmp/check.tgz | grep -E '(^|/)commands/[^/]+\.md$' || true # any commands the plan called for
tar tzf /tmp/check.tgz # inspect the full file list
```

Then assert **each** intended file is present, do not settle for a bare `grep SKILL.md` (it passes as soon as any one skill appears, so it hides a dropped skill). List the paths the plan called for and fail on the first miss:

```bash
missing=0
for p in skills/<first>/SKILL.md skills/<second>/SKILL.md rules/<rule>.md commands/<cmd>.md; do
tar tzf /tmp/check.tgz | grep -q "/$p\$\|^$p\$" || { echo "MISSING: $p"; missing=1; }
done
Comment thread
coderabbitai[bot] marked this conversation as resolved.
[ "$missing" -eq 0 ] # nonzero exit if any intended file is absent
```

`tessl skill lint <skill-dir>` is a separate tool for a single loose `SKILL.md` not yet inside a plugin. Do not run it against a skill folder within your plugin, `tessl plugin lint` already covers those; if it errors about missing plugin metadata, you pointed it at the wrong shape, drop it.

Optionally install into a throwaway project (a `file:` dependency) and confirm the skills, rules, and any MCP servers materialise.

If the plugin ships an MCP server, scripts, or otherwise touches secrets, auth, file or network access, or CI, also run a security review (`tessl review run security <plugin-dir>`; inspect `tessl review --help` for the current form). Expect findings and triage each, a flagged item is not automatically a blocker but should be reviewed with the user.
If the plugin ships an MCP server, scripts, or otherwise touches secrets, auth, file or network access, or CI, also run a security review: `tessl review run security <path> --workspace <name>` (inspect `tessl review run --help` for the current form). Pass `--workspace <name>` on any non-interactive `tessl review run`, quality or security (e.g. `tessl review run quality <path> --workspace <name>`), or the CLI opens an interactive workspace selector and hangs. Expect findings and triage each, a flagged item is not automatically a blocker but should be reviewed with the user.

## 6. Hand off

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@

Scaffold this with `tessl plugin new` (or `tessl skill new` for a single skill) rather than writing it by hand. A single skill created with `tessl skill new` is already a minimal plugin, it gets a `.tessl-plugin/plugin.json`.

## Where to author the source

Author the plugin in a **repo-owned directory you commit and control**. If `.tessl/memory/preferences/plugins.md` names a plugins dir, use it. Otherwise the default is `tessl-plugins/<plugin-name>/`, referenced from `tessl.json` with `file:<path>`. (Some repos keep plugins under `plugins/<plugin-name>/` instead; follow that only when it is already the repo's convention.)

**Do not author source under `.tessl/plugins/`.** That path is Tessl's installed-content cache, where installed plugins are materialised, not a source directory. Anything you write there can be overwritten or wiped by install operations.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## `plugin.json` fields

**Required:** `name` (`<workspace>/<plugin-name>`, matches the key in `tessl.json`), `version` (semver), `description` (the registry shopfront, what others see to decide whether to install).
Expand Down