From 253ef4a8a0d8445eaec5f8a0bce17a6b647efac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaroslav=20Bene=C5=A1?= Date: Tue, 27 Oct 2026 18:52:24 +0000 Subject: [PATCH] Harness spec 3.0.0-draft: where each tool is offered; the chat's tools Every tool says its `sessions` (chat, agent or both). The file tools read, write, edit, glob, grep and list are shared; mkdir, mv, rm, search, python and the forge verbs (commit, branch, pr, merge, tag, release) are the chat's; show and recall are new and shared. New fields: `requires` (page, display, forge) with the exact `unavailable` answer, and `confirm: always` for merge, tag and release. knowledge_*, notes_search, note_view and note_manage leave the chat. Default rules for the new tools; modes.json says what `confirm` does. Co-Authored-By: Claude Opus 5.5 --- harness/permission/defaults.json | 12 ++++++- harness/permission/modes.json | 1 + harness/tools/apply_patch.json | 1 + harness/tools/ask_user.json | 1 + harness/tools/bash.json | 1 + harness/tools/branch.json | 39 ++++++++++++++++++++++ harness/tools/commit.json | 42 ++++++++++++++++++++++++ harness/tools/decisions.json | 1 + harness/tools/edit.json | 3 +- harness/tools/glob.json | 3 +- harness/tools/grep.json | 3 +- harness/tools/job_list.json | 1 + harness/tools/job_output.json | 1 + harness/tools/job_send.json | 1 + harness/tools/job_stop.json | 1 + harness/tools/knowledge_get.json | 3 +- harness/tools/knowledge_search.json | 3 +- harness/tools/list.json | 3 +- harness/tools/memory.json | 1 + harness/tools/merge.json | 46 ++++++++++++++++++++++++++ harness/tools/mkdir.json | 26 +++++++++++++++ harness/tools/multiedit.json | 1 + harness/tools/mv.json | 31 ++++++++++++++++++ harness/tools/note_manage.json | 10 ++---- harness/tools/note_view.json | 3 +- harness/tools/notes_search.json | 3 +- harness/tools/plan_submit.json | 1 + harness/tools/plan_update.json | 1 + harness/tools/plan_write.json | 1 + harness/tools/pr.json | 46 ++++++++++++++++++++++++++ harness/tools/python.json | 50 ++++++++++++++++++++++++++++ harness/tools/read.json | 3 +- harness/tools/recall.json | 36 ++++++++++++++++++++ harness/tools/release.json | 51 +++++++++++++++++++++++++++++ harness/tools/report.json | 1 + harness/tools/rm.json | 26 +++++++++++++++ harness/tools/search.json | 36 ++++++++++++++++++++ harness/tools/session_search.json | 3 +- harness/tools/settings.json | 1 + harness/tools/show.json | 35 ++++++++++++++++++++ harness/tools/skill_manage.json | 1 + harness/tools/skill_view.json | 1 + harness/tools/skills_list.json | 1 + harness/tools/tag.json | 45 +++++++++++++++++++++++++ harness/tools/task.json | 1 + harness/tools/tasks.json | 1 + harness/tools/view_image.json | 1 + harness/tools/web_fetch.json | 1 + harness/tools/web_search.json | 1 + harness/tools/write.json | 3 +- 50 files changed, 568 insertions(+), 20 deletions(-) create mode 100644 harness/tools/branch.json create mode 100644 harness/tools/commit.json create mode 100644 harness/tools/merge.json create mode 100644 harness/tools/mkdir.json create mode 100644 harness/tools/mv.json create mode 100644 harness/tools/pr.json create mode 100644 harness/tools/python.json create mode 100644 harness/tools/recall.json create mode 100644 harness/tools/release.json create mode 100644 harness/tools/rm.json create mode 100644 harness/tools/search.json create mode 100644 harness/tools/show.json create mode 100644 harness/tools/tag.json diff --git a/harness/permission/defaults.json b/harness/permission/defaults.json index 5b462a6..8e8acf4 100644 --- a/harness/permission/defaults.json +++ b/harness/permission/defaults.json @@ -11,6 +11,10 @@ "glob": "allow", "grep": "allow", "list": "allow", + "search": "allow", + "recall": "allow", + "show": "allow", + "python": "allow", "ask_user": "allow", "plan_submit": "allow", "task": "allow", @@ -74,6 +78,12 @@ "tree *-o*": "ask", "tree *-R*": "ask", "file *-C*": "ask" - } + }, + "commit": "ask", + "branch": "ask", + "pr": "ask", + "merge": "ask", + "tag": "ask", + "release": "ask" } } diff --git a/harness/permission/modes.json b/harness/permission/modes.json index 724dd71..ce87483 100644 --- a/harness/permission/modes.json +++ b/harness/permission/modes.json @@ -4,6 +4,7 @@ "order_about": "Loosest first. A project or a subagent may make the mode stricter, never looser; switching to a looser mode is always asked.", "aliases": { "unrestricted": "auto" }, "floor": "The hardline (hardline.json) and the protected paths are refused in every mode, auto included.", + "confirm": "Spec 3.0.0: a tool with `confirm: always` (merge, tag, release) is put to the person before it runs, in every mode, auto included, as an approval card naming the call and what it reaches; it runs on a yes only. No rule allows it and no approval is remembered (an approval card offers once, never always). With nobody to answer, it is refused, as unattended says.", "modes": { "manual": { "summary": "Everything not already allowed is asked.", diff --git a/harness/tools/apply_patch.json b/harness/tools/apply_patch.json index c9fcbfe..8546ab8 100644 --- a/harness/tools/apply_patch.json +++ b/harness/tools/apply_patch.json @@ -1,6 +1,7 @@ { "name": "apply_patch", "scope": "cli", + "sessions": "agent", "risk": "write", "exclusive": false, "block": "edit", diff --git a/harness/tools/ask_user.json b/harness/tools/ask_user.json index 9da6a86..6e579c8 100644 --- a/harness/tools/ask_user.json +++ b/harness/tools/ask_user.json @@ -1,6 +1,7 @@ { "name": "ask_user", "scope": "shared", + "sessions": "both", "risk": "interact", "exclusive": true, "block": "tool", diff --git a/harness/tools/bash.json b/harness/tools/bash.json index 6580771..90c84f9 100644 --- a/harness/tools/bash.json +++ b/harness/tools/bash.json @@ -1,6 +1,7 @@ { "name": "bash", "scope": "cli", + "sessions": "agent", "risk": "execute", "exclusive": false, "block": "shell", diff --git a/harness/tools/branch.json b/harness/tools/branch.json new file mode 100644 index 0000000..45d2983 --- /dev/null +++ b/harness/tools/branch.json @@ -0,0 +1,39 @@ +{ + "name": "branch", + "scope": "llembas", + "sessions": "chat", + "risk": "execute", + "exclusive": false, + "block": "tool", + "purpose": "purpose", + "requires": [ + "forge" + ], + "unavailable": "No repository from a forge is open to this session, so there is nothing to branch here.", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Create a branch in a repository (a mount), from `from` (default: the branch this session works on), and switch this session's working copy of it to the new branch. Staged changes come along.", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Any path inside the repository (the mount) this is about" + }, + "name": { + "type": "string", + "description": "The new branch's name" + }, + "from": { + "type": "string", + "description": "Branch, tag or commit to start from" + } + }, + "required": [ + "path", + "name" + ] + } +} diff --git a/harness/tools/commit.json b/harness/tools/commit.json new file mode 100644 index 0000000..38ea297 --- /dev/null +++ b/harness/tools/commit.json @@ -0,0 +1,42 @@ +{ + "name": "commit", + "scope": "llembas", + "sessions": "chat", + "risk": "execute", + "exclusive": false, + "block": "tool", + "purpose": "purpose", + "requires": [ + "forge" + ], + "unavailable": "No repository from a forge is open to this session, so there is nothing to commit here.", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Send the staged changes of a repository (a mount) to the forge as one commit on the branch this session works on, under the user's account. Every change this session made in that repository since its last commit goes in, unless `paths` names some of them.\n\n- Refused when the branch has moved on the forge since this session's working copy was based on it: the answer shows what changed there. Look at it, then commit again.\n- Write the message as the repository's history does: a short subject line, then why, where it is not obvious.\n- Needs commit access to the repository in this session. With stage access the changes stay staged, for the user to commit.", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Any path inside the repository (the mount) this is about" + }, + "message": { + "type": "string", + "description": "The commit message" + }, + "paths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Only these changed paths (default: every staged change)" + } + }, + "required": [ + "path", + "message" + ] + } +} diff --git a/harness/tools/decisions.json b/harness/tools/decisions.json index 8088a96..80ac2fc 100644 --- a/harness/tools/decisions.json +++ b/harness/tools/decisions.json @@ -1,6 +1,7 @@ { "name": "decisions", "scope": "cli", + "sessions": "agent", "risk": "interact", "exclusive": false, "block": "tool", diff --git a/harness/tools/edit.json b/harness/tools/edit.json index defdeaa..d0130a5 100644 --- a/harness/tools/edit.json +++ b/harness/tools/edit.json @@ -1,6 +1,7 @@ { "name": "edit", - "scope": "cli", + "scope": "shared", + "sessions": "both", "risk": "write", "exclusive": false, "block": "edit", diff --git a/harness/tools/glob.json b/harness/tools/glob.json index 1c6e6aa..290641b 100644 --- a/harness/tools/glob.json +++ b/harness/tools/glob.json @@ -1,6 +1,7 @@ { "name": "glob", - "scope": "cli", + "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "search", diff --git a/harness/tools/grep.json b/harness/tools/grep.json index 872f943..9c09d1f 100644 --- a/harness/tools/grep.json +++ b/harness/tools/grep.json @@ -1,6 +1,7 @@ { "name": "grep", - "scope": "cli", + "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "search", diff --git a/harness/tools/job_list.json b/harness/tools/job_list.json index 0971cb2..70962ce 100644 --- a/harness/tools/job_list.json +++ b/harness/tools/job_list.json @@ -1,6 +1,7 @@ { "name": "job_list", "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "tool", diff --git a/harness/tools/job_output.json b/harness/tools/job_output.json index 1b7a698..f6c5fbc 100644 --- a/harness/tools/job_output.json +++ b/harness/tools/job_output.json @@ -1,6 +1,7 @@ { "name": "job_output", "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "tool", diff --git a/harness/tools/job_send.json b/harness/tools/job_send.json index f4b78ef..1ae7c93 100644 --- a/harness/tools/job_send.json +++ b/harness/tools/job_send.json @@ -1,6 +1,7 @@ { "name": "job_send", "scope": "shared", + "sessions": "both", "risk": "interact", "exclusive": false, "block": "tool", diff --git a/harness/tools/job_stop.json b/harness/tools/job_stop.json index f65db71..a9d79d7 100644 --- a/harness/tools/job_stop.json +++ b/harness/tools/job_stop.json @@ -1,6 +1,7 @@ { "name": "job_stop", "scope": "shared", + "sessions": "both", "risk": "execute", "exclusive": false, "block": "tool", diff --git a/harness/tools/knowledge_get.json b/harness/tools/knowledge_get.json index 7bc767b..96a3a0e 100644 --- a/harness/tools/knowledge_get.json +++ b/harness/tools/knowledge_get.json @@ -1,6 +1,7 @@ { "name": "knowledge_get", - "scope": "shared", + "scope": "cli", + "sessions": "agent", "risk": "read", "exclusive": false, "block": "read", diff --git a/harness/tools/knowledge_search.json b/harness/tools/knowledge_search.json index 6953a9e..b071e68 100644 --- a/harness/tools/knowledge_search.json +++ b/harness/tools/knowledge_search.json @@ -1,6 +1,7 @@ { "name": "knowledge_search", - "scope": "shared", + "scope": "cli", + "sessions": "agent", "risk": "read", "exclusive": false, "block": "search", diff --git a/harness/tools/list.json b/harness/tools/list.json index 57ef877..f632869 100644 --- a/harness/tools/list.json +++ b/harness/tools/list.json @@ -1,6 +1,7 @@ { "name": "list", - "scope": "cli", + "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "search", diff --git a/harness/tools/memory.json b/harness/tools/memory.json index da10aee..37255d3 100644 --- a/harness/tools/memory.json +++ b/harness/tools/memory.json @@ -1,6 +1,7 @@ { "name": "memory", "scope": "shared", + "sessions": "both", "risk": "interact", "exclusive": false, "block": "tool", diff --git a/harness/tools/merge.json b/harness/tools/merge.json new file mode 100644 index 0000000..dbf4fe8 --- /dev/null +++ b/harness/tools/merge.json @@ -0,0 +1,46 @@ +{ + "name": "merge", + "scope": "llembas", + "sessions": "chat", + "risk": "execute", + "exclusive": true, + "block": "tool", + "purpose": "purpose", + "requires": [ + "forge" + ], + "confirm": "always", + "unavailable": "No repository from a forge is open to this session, so there is nothing to merge here.", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Merge a pull request on the forge. The user is always asked first, in every mode, and shown the pull request: nothing is merged without their yes.", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Any path inside the repository (the mount) this is about" + }, + "number": { + "type": "integer", + "minimum": 1, + "description": "The pull request's number" + }, + "method": { + "type": "string", + "enum": [ + "merge", + "squash", + "rebase" + ], + "description": "How to merge (default: the repository's setting)" + } + }, + "required": [ + "path", + "number" + ] + } +} diff --git a/harness/tools/mkdir.json b/harness/tools/mkdir.json new file mode 100644 index 0000000..0cb93d7 --- /dev/null +++ b/harness/tools/mkdir.json @@ -0,0 +1,26 @@ +{ + "name": "mkdir", + "scope": "llembas", + "sessions": "chat", + "risk": "write", + "exclusive": false, + "block": "tool", + "purpose": "purpose", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Make a directory, and any missing directories above it. Making one that already exists is not an error.\n\n- `path` may be absolute or relative to the working directory.\n- In a repository (a mount), an empty directory stays in this session's working copy; a commit leaves empty directories out.", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Directory to make" + } + }, + "required": [ + "path" + ] + } +} diff --git a/harness/tools/multiedit.json b/harness/tools/multiedit.json index 6abcd76..857bae7 100644 --- a/harness/tools/multiedit.json +++ b/harness/tools/multiedit.json @@ -1,6 +1,7 @@ { "name": "multiedit", "scope": "cli", + "sessions": "agent", "risk": "write", "exclusive": false, "block": "edit", diff --git a/harness/tools/mv.json b/harness/tools/mv.json new file mode 100644 index 0000000..312b5eb --- /dev/null +++ b/harness/tools/mv.json @@ -0,0 +1,31 @@ +{ + "name": "mv", + "scope": "llembas", + "sessions": "chat", + "risk": "write", + "exclusive": false, + "block": "tool", + "purpose": "purpose", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Move or rename a file or directory. A directory moves with everything in it.\n\n- `from` and `to` may be absolute or relative to the working directory; `to` must not exist yet.\n- Inside one repository (a mount) the move is staged like any other change. Between a repository and the rest of the file system, or between two repositories, it is refused: read the file and write it where it should go instead.", + "parameters": { + "type": "object", + "properties": { + "from": { + "type": "string", + "description": "What to move" + }, + "to": { + "type": "string", + "description": "The new path, including the name" + } + }, + "required": [ + "from", + "to" + ] + } +} diff --git a/harness/tools/note_manage.json b/harness/tools/note_manage.json index 2154e30..15282dc 100644 --- a/harness/tools/note_manage.json +++ b/harness/tools/note_manage.json @@ -1,6 +1,7 @@ { "name": "note_manage", - "scope": "shared", + "scope": "cli", + "sessions": "agent", "risk": "interact", "exclusive": false, "block": "tool", @@ -53,12 +54,5 @@ "required": [ "action" ] - }, - "narrow": { - "llembas": { - "drop": [ - "scope" - ] - } } } diff --git a/harness/tools/note_view.json b/harness/tools/note_view.json index 68f2649..fe1957a 100644 --- a/harness/tools/note_view.json +++ b/harness/tools/note_view.json @@ -1,6 +1,7 @@ { "name": "note_view", - "scope": "shared", + "scope": "cli", + "sessions": "agent", "risk": "read", "exclusive": false, "block": "read", diff --git a/harness/tools/notes_search.json b/harness/tools/notes_search.json index 6aa3d45..cd31344 100644 --- a/harness/tools/notes_search.json +++ b/harness/tools/notes_search.json @@ -1,6 +1,7 @@ { "name": "notes_search", - "scope": "shared", + "scope": "cli", + "sessions": "agent", "risk": "read", "exclusive": false, "block": "search", diff --git a/harness/tools/plan_submit.json b/harness/tools/plan_submit.json index 3a3be88..7693ca3 100644 --- a/harness/tools/plan_submit.json +++ b/harness/tools/plan_submit.json @@ -1,6 +1,7 @@ { "name": "plan_submit", "scope": "shared", + "sessions": "both", "risk": "interact", "exclusive": true, "block": "tool", diff --git a/harness/tools/plan_update.json b/harness/tools/plan_update.json index ac2a39a..217be51 100644 --- a/harness/tools/plan_update.json +++ b/harness/tools/plan_update.json @@ -1,6 +1,7 @@ { "name": "plan_update", "scope": "shared", + "sessions": "both", "risk": "interact", "exclusive": false, "block": "plan", diff --git a/harness/tools/plan_write.json b/harness/tools/plan_write.json index 782bc46..21c91e1 100644 --- a/harness/tools/plan_write.json +++ b/harness/tools/plan_write.json @@ -1,6 +1,7 @@ { "name": "plan_write", "scope": "shared", + "sessions": "both", "risk": "interact", "exclusive": false, "block": "plan", diff --git a/harness/tools/pr.json b/harness/tools/pr.json new file mode 100644 index 0000000..ec538b0 --- /dev/null +++ b/harness/tools/pr.json @@ -0,0 +1,46 @@ +{ + "name": "pr", + "scope": "llembas", + "sessions": "chat", + "risk": "execute", + "exclusive": false, + "block": "tool", + "purpose": "purpose", + "requires": [ + "forge" + ], + "unavailable": "No repository from a forge is open to this session, so there is nothing to pr here.", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Open a pull request on the forge, from `head` (default: the branch this session works on) into `base` (default: the repository's default branch). Only committed changes are in it: commit first.", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Any path inside the repository (the mount) this is about" + }, + "title": { + "type": "string" + }, + "body": { + "type": "string", + "description": "What it changes and why" + }, + "head": { + "type": "string", + "description": "The branch with the changes" + }, + "base": { + "type": "string", + "description": "The branch to merge into" + } + }, + "required": [ + "path", + "title" + ] + } +} diff --git a/harness/tools/python.json b/harness/tools/python.json new file mode 100644 index 0000000..9eca9db --- /dev/null +++ b/harness/tools/python.json @@ -0,0 +1,50 @@ +{ + "name": "python", + "scope": "llembas", + "sessions": "chat", + "risk": "execute", + "exclusive": false, + "block": "shell", + "purpose": "purpose", + "requires": [ + "page" + ], + "unavailable": "Python cannot run now: no open browser page is attached to this chat.", + "aliases": { + "cli": [], + "llembas": [] + }, + "variables": { + "packages": "the packages the instance provides beyond the standard library, as a list, or \"none\"", + "seconds": "the time limit of one call, in seconds", + "memory": "the memory limit of one call, with its unit", + "output": "how much printed output comes back, with its unit" + }, + "description": "Run Python for calculations and for working with files — parse JSON or CSV, transform text, compute. It runs in the user's browser (Pyodide), sandboxed: no network, no shell, no packages beyond the standard library and these: {{packages}}. Returns what the code printed and the value of its last expression.\n\n- `files` are copied in before the run, at the same paths, from what this session can read.\n- Files the code writes come back only when listed in `save`: each is written as the write tool would write it, with this session's permissions.\n- At most {{seconds}} seconds and {{memory}} of memory per call; printed output past {{output}} is cut.\n- Every call starts fresh: nothing is kept between calls.", + "parameters": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "The Python code to run" + }, + "files": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Files to copy in before the run" + }, + "save": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Files the code writes that are to be saved back" + } + }, + "required": [ + "code" + ] + } +} diff --git a/harness/tools/read.json b/harness/tools/read.json index e49cd3b..46182e3 100644 --- a/harness/tools/read.json +++ b/harness/tools/read.json @@ -1,6 +1,7 @@ { "name": "read", - "scope": "cli", + "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "read", diff --git a/harness/tools/recall.json b/harness/tools/recall.json new file mode 100644 index 0000000..f67900e --- /dev/null +++ b/harness/tools/recall.json @@ -0,0 +1,36 @@ +{ + "name": "recall", + "scope": "shared", + "sessions": "both", + "risk": "read", + "exclusive": false, + "block": "read", + "purpose": false, + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Show a stored tool result again, in full, by its id (`#a3f2`): the lines a shortened output left out, or a result from before the conversation was summarised. Every result of this session is kept, so nothing is lost.\n\n- Returns up to 2000 lines from `offset` (1-indexed); call again with a larger offset for more.\n- An unchanged file is not worth recalling when its earlier result is still above: that result is the content.", + "parameters": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The result's id, e.g. #a3f2" + }, + "offset": { + "type": "integer", + "minimum": 1, + "description": "First line to return, 1-indexed" + }, + "limit": { + "type": "integer", + "minimum": 1, + "description": "How many lines (default 2000)" + } + }, + "required": [ + "id" + ] + } +} diff --git a/harness/tools/release.json b/harness/tools/release.json new file mode 100644 index 0000000..34b77ca --- /dev/null +++ b/harness/tools/release.json @@ -0,0 +1,51 @@ +{ + "name": "release", + "scope": "llembas", + "sessions": "chat", + "risk": "execute", + "exclusive": true, + "block": "tool", + "purpose": "purpose", + "requires": [ + "forge" + ], + "confirm": "always", + "unavailable": "No repository from a forge is open to this session, so there is nothing to release here.", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Publish a release on the forge from a tag that already exists, with its notes. Make the tag first (tag): a release is never made for a tag that does not exist. The user is always asked first, in every mode.", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Any path inside the repository (the mount) this is about" + }, + "tag": { + "type": "string", + "description": "The existing tag" + }, + "title": { + "type": "string" + }, + "notes": { + "type": "string", + "description": "The release notes (usually the tag's message)" + }, + "prerelease": { + "type": "boolean" + }, + "draft": { + "type": "boolean" + } + }, + "required": [ + "path", + "tag", + "title", + "notes" + ] + } +} diff --git a/harness/tools/report.json b/harness/tools/report.json index 7505fae..485ecb0 100644 --- a/harness/tools/report.json +++ b/harness/tools/report.json @@ -1,6 +1,7 @@ { "name": "report", "scope": "shared", + "sessions": "both", "risk": "interact", "exclusive": false, "block": "tool", diff --git a/harness/tools/rm.json b/harness/tools/rm.json new file mode 100644 index 0000000..ba0c514 --- /dev/null +++ b/harness/tools/rm.json @@ -0,0 +1,26 @@ +{ + "name": "rm", + "scope": "llembas", + "sessions": "chat", + "risk": "write", + "exclusive": false, + "block": "tool", + "purpose": "purpose", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Delete a file or directory by moving it to the trash, from which the user can restore it. A directory goes with everything in it: list it first.\n\n- `path` may be absolute or relative to the working directory.\n- In a repository (a mount) the deletion is staged in this session's working copy and reaches the repository only with a commit.", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "File or directory to delete" + } + }, + "required": [ + "path" + ] + } +} diff --git a/harness/tools/search.json b/harness/tools/search.json new file mode 100644 index 0000000..78025eb --- /dev/null +++ b/harness/tools/search.json @@ -0,0 +1,36 @@ +{ + "name": "search", + "scope": "llembas", + "sessions": "chat", + "risk": "read", + "exclusive": false, + "block": "search", + "purpose": "purpose", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Search the files this session can see, by meaning and by words together: the best passages first, each with its path and line range. Use it to find where something is discussed or answered when you do not know the exact words; use grep for exact text or a pattern, glob for file names.\n\n- `path` limits the search to a directory (default: everything this session can see).\n- A passage is an extract. Read the file around it before answering from it when the answer turns on detail, and cite the path.\n- Only indexed files are searched: text, Markdown, code, JSON and the text of PDF and DOCX files, up to a size limit. A file just written is found once it has been indexed.", + "parameters": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "What to look for, in words: a question or the topic" + }, + "path": { + "type": "string", + "description": "Directory to search (default: everything this session can see)" + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "description": "How many passages (default 10)" + } + }, + "required": [ + "query" + ] + } +} diff --git a/harness/tools/session_search.json b/harness/tools/session_search.json index ed69dbd..0f0424b 100644 --- a/harness/tools/session_search.json +++ b/harness/tools/session_search.json @@ -1,6 +1,7 @@ { "name": "session_search", - "scope": "cli", + "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "search", diff --git a/harness/tools/settings.json b/harness/tools/settings.json index 121c65a..7b76025 100644 --- a/harness/tools/settings.json +++ b/harness/tools/settings.json @@ -1,6 +1,7 @@ { "name": "settings", "scope": "cli", + "sessions": "agent", "risk": "interact", "exclusive": false, "block": "tool", diff --git a/harness/tools/show.json b/harness/tools/show.json new file mode 100644 index 0000000..01f5f91 --- /dev/null +++ b/harness/tools/show.json @@ -0,0 +1,35 @@ +{ + "name": "show", + "scope": "shared", + "sessions": "both", + "risk": "interact", + "exclusive": false, + "block": "tool", + "purpose": "purpose", + "requires": [ + "display" + ], + "unavailable": "Nothing can be shown now: this session has no screen to show a file on. Give the user the path instead.", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Open a file in the user's viewer, beside the conversation, without them having to look for it: Markdown rendered, code highlighted, plain text as it is, and HTML as a page in a sandboxed frame that cannot reach this app, the user's data or anything the instance does not allow. Use it when the user should see the file itself — a page or a chart you made, a document you wrote — not for files you only read.\n\n- `path` may be absolute or relative to the working directory. The file must exist and be readable in this session: write it first.\n- `line` scrolls a text file to that line.", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "File to show" + }, + "line": { + "type": "integer", + "minimum": 1, + "description": "Line to scroll to (text files)" + } + }, + "required": [ + "path" + ] + } +} diff --git a/harness/tools/skill_manage.json b/harness/tools/skill_manage.json index d13d14c..4bf9cee 100644 --- a/harness/tools/skill_manage.json +++ b/harness/tools/skill_manage.json @@ -1,6 +1,7 @@ { "name": "skill_manage", "scope": "shared", + "sessions": "both", "risk": "write", "exclusive": false, "block": "tool", diff --git a/harness/tools/skill_view.json b/harness/tools/skill_view.json index f702c7b..6c4fb31 100644 --- a/harness/tools/skill_view.json +++ b/harness/tools/skill_view.json @@ -1,6 +1,7 @@ { "name": "skill_view", "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "read", diff --git a/harness/tools/skills_list.json b/harness/tools/skills_list.json index 0e70aeb..163605e 100644 --- a/harness/tools/skills_list.json +++ b/harness/tools/skills_list.json @@ -1,6 +1,7 @@ { "name": "skills_list", "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "search", diff --git a/harness/tools/tag.json b/harness/tools/tag.json new file mode 100644 index 0000000..546e0b9 --- /dev/null +++ b/harness/tools/tag.json @@ -0,0 +1,45 @@ +{ + "name": "tag", + "scope": "llembas", + "sessions": "chat", + "risk": "execute", + "exclusive": true, + "block": "tool", + "purpose": "purpose", + "requires": [ + "forge" + ], + "confirm": "always", + "unavailable": "No repository from a forge is open to this session, so there is nothing to tag here.", + "aliases": { + "cli": [], + "llembas": [] + }, + "description": "Create an annotated tag on the forge, at `at` (default: the newest commit of the branch this session works on), its message being the release note. The user is always asked first, in every mode.", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Any path inside the repository (the mount) this is about" + }, + "name": { + "type": "string", + "description": "The tag, e.g. v1.2.0" + }, + "message": { + "type": "string", + "description": "The tag's message" + }, + "at": { + "type": "string", + "description": "Branch or commit to tag" + } + }, + "required": [ + "path", + "name", + "message" + ] + } +} diff --git a/harness/tools/task.json b/harness/tools/task.json index 94baaba..a7e1549 100644 --- a/harness/tools/task.json +++ b/harness/tools/task.json @@ -1,6 +1,7 @@ { "name": "task", "scope": "shared", + "sessions": "both", "risk": "interact", "exclusive": false, "block": "task", diff --git a/harness/tools/tasks.json b/harness/tools/tasks.json index f1f2629..d0f5710 100644 --- a/harness/tools/tasks.json +++ b/harness/tools/tasks.json @@ -1,6 +1,7 @@ { "name": "tasks", "scope": "cli", + "sessions": "agent", "risk": "interact", "exclusive": false, "block": "tool", diff --git a/harness/tools/view_image.json b/harness/tools/view_image.json index b536e3b..d170b9c 100644 --- a/harness/tools/view_image.json +++ b/harness/tools/view_image.json @@ -1,6 +1,7 @@ { "name": "view_image", "scope": "cli", + "sessions": "agent", "risk": "read", "exclusive": false, "block": "read", diff --git a/harness/tools/web_fetch.json b/harness/tools/web_fetch.json index 1cea9d6..20bf84a 100644 --- a/harness/tools/web_fetch.json +++ b/harness/tools/web_fetch.json @@ -1,6 +1,7 @@ { "name": "web_fetch", "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "web", diff --git a/harness/tools/web_search.json b/harness/tools/web_search.json index b6f46d8..bd89b5c 100644 --- a/harness/tools/web_search.json +++ b/harness/tools/web_search.json @@ -1,6 +1,7 @@ { "name": "web_search", "scope": "shared", + "sessions": "both", "risk": "read", "exclusive": false, "block": "web", diff --git a/harness/tools/write.json b/harness/tools/write.json index 8042ecc..9d052c3 100644 --- a/harness/tools/write.json +++ b/harness/tools/write.json @@ -1,6 +1,7 @@ { "name": "write", - "scope": "cli", + "scope": "shared", + "sessions": "both", "risk": "write", "exclusive": false, "block": "edit",