From aa106b13d30add1dda11f350929c148a96ad7220 Mon Sep 17 00:00:00 2001 From: Louis Choquel Date: Sat, 26 Sep 2026 17:09:05 +0200 Subject: [PATCH] pipelex-explain and the catalog's validity check opt out of the method graph page The workshop's mthds_validate is about to write method-graph.html beside files given by path unless graph_page is false. pipelex-explain promises to write nothing yet validates by path, so it now passes graph_page: false wherever the tool lists that argument; pipelex-catalog's optional "would this save?" check does the same. Both sentences are registered guards, and docs/decisions.md records why organize and the writing skills keep the page. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01EJVC48w18XEdnvEc48jFAf --- CHANGELOG.md | 6 ++++++ docs/decisions.md | 10 ++++++++++ docs/skills.md | 2 +- pipelex-codex/skills/pipelex-catalog/SKILL.md | 2 +- pipelex-codex/skills/pipelex-explain/SKILL.md | 2 +- pipelex-vibe/skills/pipelex-catalog/SKILL.md | 2 +- pipelex-vibe/skills/pipelex-explain/SKILL.md | 2 +- pipelex/skills/pipelex-catalog/SKILL.md | 2 +- pipelex/skills/pipelex-explain/SKILL.md | 2 +- templates/skills/pipelex-catalog/SKILL.md.j2 | 2 +- templates/skills/pipelex-explain/SKILL.md.j2 | 2 +- tests/unit/test_skill_guards.py | 2 ++ 12 files changed, 27 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08d2537d..ac861b45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased] + +### Fixed + +- **`pipelex-explain` leaves no method graph page behind**: the Pipelex tools are about to write a method's flowchart, `method-graph.html`, beside the files a validation reads by path, which would have left a file in the bundle every time `pipelex-explain`, a skill that writes nothing, checked a method on disk. The skill now asks the tools not to write the page, and so does `pipelex-catalog` when it checks whether a bundle would save, since that check is a question and writes no file either. + ## [0.9.2] - 2026-09-25 ### Fixed diff --git a/docs/decisions.md b/docs/decisions.md index 11dbf5e8..7cbe646c 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -682,6 +682,16 @@ Until the console's own release, the hosted console and the local workshop regis - **What the skills said of the console is corrected.** The shared submission include no longer calls the inline form "the only form the hosted console accepts", since the console takes no files at all, and `pipelex-explain`'s not-on-disk reference names one cause of an absent `mthds_get_method` where it named two: a workshop older than the release that brought it. The connection reference a skill reads when its tools are absent now tells the user that the plugin's MCP server is the one not connected, which a user who can see a connected Pipelex connector would otherwise doubt, and both references say that the connector's `pipelex_*` tools do not stand in for the workshop's. - **The README's quick-start paragraph is not changed here.** It lives in the onboarding region, which is generated from the workspace's onboarding source (the Claude Code sync block) and is replaced from there, so it moves when that block does. +## The workshop's method graph page, and the two skills that turn it off (2026-09-26) + +`pipelex-mcp` made `mthds_validate` write the method's flowchart as a standalone page, `method-graph.html`, beside the files whenever every file is given as `{ path }`, whatever the verdict, and rewrite it on each validation; a caller turns it off with `graph_page: false` (`pipelex-mcp/SPEC.md`, "The method graph page"). The default is the workshop's to keep, because it is what gives a builder in a host with no views the graph at all, so a skill that must not leave a file behind is the one that opts out. + +- **`pipelex-explain` passes `graph_page: false`.** It promises to write nothing, and it validates a bundle on disk by path, as the shared submission convention prefers, so without the argument every explanation of a local method would have left the page in the user's tree. The argument goes on the skill's own step rather than in `shared/validate-call.md.j2`, since the writing skills want the page. It is a guard, registered in `tests/unit/test_skill_guards.py`, because skipping it breaks the promise silently: nothing in the verdict says a file was written. +- **`pipelex-catalog`'s check of whether a bundle would save passes it too.** The skill writes no file itself and names the two the workshop writes for it, the pulled sources and the link; a page written by a question would have been a third. `mthds_save_method`'s own validation writes no page, so a save needs nothing. +- **"Wherever the tool lists that argument."** A workshop older than the page lists no `graph_page` and writes no page. `@pipelex/mcp` 0.20.0, the release before the page, ignored the argument when it was sent from Claude Code on 2026-09-26 and answered the verdict as usual, but Codex and Mistral Vibe were not tried, and a host may hold the model to the advertised schema; so the skills name the argument only where the tool offers it rather than sending it blind. +- **`pipelex-organize` is left as it is.** Its baseline validation writes the page before the layout changes, and its confirmation after the swap rewrites it from the new layout, so the page it leaves matches the files. Its promises are about the bundle's `.mthds` files, which the page is not, and it deletes only `.mthds` files. Where the confirmation fails and the original layout is restored, the page shows the rejected candidate until the next validation rewrites it; that is not worth another validation call. +- **The writing skills keep the page.** `pipelex-design`, `pipelex-edit`, `pipelex-inputs`, `pipelex-run` and `pipelex-integrate` validate by path and let the workshop write it. Pointing the user at it is a change of its own. + ## License & distribution **Apache 2.0**; repo made public when ready (required for easy marketplace install). Versions start at **0.1.0** (plugin and marketplace). GitHub home assumed `Pipelex/pipelex-plugins` — confirm at first push. diff --git a/docs/skills.md b/docs/skills.md index 016e2524..8199a38c 100644 --- a/docs/skills.md +++ b/docs/skills.md @@ -44,7 +44,7 @@ The skills share one reference for MTHDS, the language a method is written in: ` ## The Pipelex tools -The tools reach the Pipelex API with your key, the same one the hook uses. Each tool that takes a method takes the files themselves, a saved method's catalog id as `method_id`, or a published method's address as `method_ref`; a call by id needs an API key, because the catalog belongs to an organization. The tools read a file by path only inside the directory the agent was started in, an absolute path included; for a bundle outside it, start the agent from a directory that holds the bundle, or the skills send the files' contents instead. +The tools reach the Pipelex API with your key, the same one the hook uses. Each tool that takes a method takes the files themselves, a saved method's catalog id as `method_id`, or a published method's address as `method_ref`; a call by id needs an API key, because the catalog belongs to an organization. The tools read a file by path only inside the directory the agent was started in, an absolute path included; for a bundle outside it, start the agent from a directory that holds the bundle, or the skills send the files' contents instead. A version of the tools that draws the method graph also writes the method's flowchart, `method-graph.html`, beside files it validates by path, and rewrites it on each validation; `pipelex-explain` and `pipelex-catalog`'s check of whether a bundle would save turn the page off, since neither writes files. - **`mthds_validate`** validates a method. Its verdict carries the main pipe's signature, from which `/pipelex-integrate` types a call site. - **`mthds_inputs_template`** returns the input template of a pipe. diff --git a/pipelex-codex/skills/pipelex-catalog/SKILL.md b/pipelex-codex/skills/pipelex-catalog/SKILL.md index b0b7ca87..bea6dfac 100644 --- a/pipelex-codex/skills/pipelex-catalog/SKILL.md +++ b/pipelex-codex/skills/pipelex-catalog/SKILL.md @@ -12,7 +12,7 @@ Every gesture between a bundle directory and the organization's method catalog: - **`mthds_list_methods`**, **`mthds_save_method`** and **`mthds_get_method`** are required, with no fallback: the catalog lives behind the API key. - **If the catalog tools are absent from this session**, the Pipelex MCP server isn't connected: STOP, and tell the user in one line what [the connection reference](../shared/credentials.md#the-tool-is-absent) says for Codex. Never report a method id, a name, or a method as saved when the answer did not come from these tools. - **If a call returns `status: "error"` with an error of class `config`** (missing or rejected `PIPELEX_API_KEY`, unreachable API), STOP the same way and surface the error's `hint` verbatim; when it is about the key, read [where the key comes from](../shared/credentials.md#where-the-key-comes-from) before saying anything more. -- **`mthds_validate`** is optional, for one question: *would this save?* Never call it on the way to a save: `mthds_save_method` reads the files, validates them and saves those same bytes in one call. +- **`mthds_validate`** is optional, for one question: *would this save?* Never call it on the way to a save: `mthds_save_method` reads the files, validates them and saves those same bytes in one call. Ask it with `graph_page: false` wherever the tool lists that argument: a question writes no file, and `{path}` files would otherwise get `method-graph.html` beside them. ## Guards diff --git a/pipelex-codex/skills/pipelex-explain/SKILL.md b/pipelex-codex/skills/pipelex-explain/SKILL.md index 71ec0f5b..5833ac44 100644 --- a/pipelex-codex/skills/pipelex-explain/SKILL.md +++ b/pipelex-codex/skills/pipelex-explain/SKILL.md @@ -36,7 +36,7 @@ A `PipeSignature` is **pending only when no concrete pipe of the same code exist ### 3. The verdict, when the workshop is there -One `mthds_validate` call over the same files. Submit every `.mthds` file beneath the bundle directory **except anything under a `runs/` directory**, where `/pipelex-run` saves a completed run's artifacts: a method that emits or echoes a `.mthds` file would otherwise have its own output submitted as part of its source. Prefer the path form `{path: }`. The workshop refuses a path outside **its own** working directory, where the harness launched it; relaunching the harness from a directory holding the bundle cures that. Inline `{content: , uri: }` is the fallback. The call adds two things and nothing else: the **verdict line** (whether it is valid, whether it is runnable, what is still pending) and, when the verdict carries a `main_pipe`, the **main pipe's typed signature**: its namespaced ref, each declared input with its concept and whether it is required, and the concept it produces. +One `mthds_validate` call over the same files. Submit every `.mthds` file beneath the bundle directory **except anything under a `runs/` directory**, where `/pipelex-run` saves a completed run's artifacts: a method that emits or echoes a `.mthds` file would otherwise have its own output submitted as part of its source. Prefer the path form `{path: }`. The workshop refuses a path outside **its own** working directory, where the harness launched it; relaunching the harness from a directory holding the bundle cures that. Inline `{content: , uri: }` is the fallback. **Pass `graph_page: false`** wherever the tool lists that argument: on `{path}` files the workshop otherwise writes the method's flowchart, `method-graph.html`, beside them, and this skill writes nothing. The call adds two things and nothing else: the **verdict line** (whether it is valid, whether it is runnable, what is still pending) and, when the verdict carries a `main_pipe`, the **main pipe's typed signature**: its namespaced ref, each declared input with its concept and whether it is required, and the concept it produces. Without the tool, explain from the source and **say the verdict was not checked**. Your own reading of the source is not a guess: the pipe types, the concepts and step 2's backlog are yours to state, saying whose reading it is. But do not present a validation verdict, a typed signature or a pending list as the workshop's when the workshop did not answer, and do not guess at validity. **On a target that is not on disk there is no such fallback.** diff --git a/pipelex-vibe/skills/pipelex-catalog/SKILL.md b/pipelex-vibe/skills/pipelex-catalog/SKILL.md index 9692d4e5..b2b2085d 100644 --- a/pipelex-vibe/skills/pipelex-catalog/SKILL.md +++ b/pipelex-vibe/skills/pipelex-catalog/SKILL.md @@ -12,7 +12,7 @@ Every gesture between a bundle directory and the organization's method catalog: - **`mthds_list_methods`**, **`mthds_save_method`** and **`mthds_get_method`** are required, with no fallback: the catalog lives behind the API key. - **If the catalog tools are absent from this session**, the Pipelex MCP server isn't connected: STOP, and tell the user in one line what [the connection reference](../shared/credentials.md#the-tool-is-absent) says for Mistral Vibe. Never report a method id, a name, or a method as saved when the answer did not come from these tools. - **If a call returns `status: "error"` with an error of class `config`** (missing or rejected `PIPELEX_API_KEY`, unreachable API), STOP the same way and surface the error's `hint` verbatim; when it is about the key, read [where the key comes from](../shared/credentials.md#where-the-key-comes-from) before saying anything more. -- **`mthds_validate`** is optional, for one question: *would this save?* Never call it on the way to a save: `mthds_save_method` reads the files, validates them and saves those same bytes in one call. +- **`mthds_validate`** is optional, for one question: *would this save?* Never call it on the way to a save: `mthds_save_method` reads the files, validates them and saves those same bytes in one call. Ask it with `graph_page: false` wherever the tool lists that argument: a question writes no file, and `{path}` files would otherwise get `method-graph.html` beside them. ## Guards diff --git a/pipelex-vibe/skills/pipelex-explain/SKILL.md b/pipelex-vibe/skills/pipelex-explain/SKILL.md index db972b96..9256d6c5 100644 --- a/pipelex-vibe/skills/pipelex-explain/SKILL.md +++ b/pipelex-vibe/skills/pipelex-explain/SKILL.md @@ -36,7 +36,7 @@ A `PipeSignature` is **pending only when no concrete pipe of the same code exist ### 3. The verdict, when the workshop is there -One `mthds_validate` call over the same files. Submit every `.mthds` file beneath the bundle directory **except anything under a `runs/` directory**, where `/pipelex-run` saves a completed run's artifacts: a method that emits or echoes a `.mthds` file would otherwise have its own output submitted as part of its source. Prefer the path form `{path: }`. The workshop refuses a path outside **its own** working directory, where the harness launched it; relaunching the harness from a directory holding the bundle cures that. Inline `{content: , uri: }` is the fallback. The call adds two things and nothing else: the **verdict line** (whether it is valid, whether it is runnable, what is still pending) and, when the verdict carries a `main_pipe`, the **main pipe's typed signature**: its namespaced ref, each declared input with its concept and whether it is required, and the concept it produces. +One `mthds_validate` call over the same files. Submit every `.mthds` file beneath the bundle directory **except anything under a `runs/` directory**, where `/pipelex-run` saves a completed run's artifacts: a method that emits or echoes a `.mthds` file would otherwise have its own output submitted as part of its source. Prefer the path form `{path: }`. The workshop refuses a path outside **its own** working directory, where the harness launched it; relaunching the harness from a directory holding the bundle cures that. Inline `{content: , uri: }` is the fallback. **Pass `graph_page: false`** wherever the tool lists that argument: on `{path}` files the workshop otherwise writes the method's flowchart, `method-graph.html`, beside them, and this skill writes nothing. The call adds two things and nothing else: the **verdict line** (whether it is valid, whether it is runnable, what is still pending) and, when the verdict carries a `main_pipe`, the **main pipe's typed signature**: its namespaced ref, each declared input with its concept and whether it is required, and the concept it produces. Without the tool, explain from the source and **say the verdict was not checked**. Your own reading of the source is not a guess: the pipe types, the concepts and step 2's backlog are yours to state, saying whose reading it is. But do not present a validation verdict, a typed signature or a pending list as the workshop's when the workshop did not answer, and do not guess at validity. **On a target that is not on disk there is no such fallback.** diff --git a/pipelex/skills/pipelex-catalog/SKILL.md b/pipelex/skills/pipelex-catalog/SKILL.md index c68c2002..de4d1069 100644 --- a/pipelex/skills/pipelex-catalog/SKILL.md +++ b/pipelex/skills/pipelex-catalog/SKILL.md @@ -21,7 +21,7 @@ Every gesture between a bundle directory and the organization's method catalog: - **`mthds_list_methods`**, **`mthds_save_method`** and **`mthds_get_method`** are required, with no fallback: the catalog lives behind the API key. - **If the catalog tools are absent from this session**, the Pipelex MCP server isn't connected: STOP, and tell the user in one line what [the connection reference](../shared/credentials.md#the-tool-is-absent) says for Claude Code. Never report a method id, a name, or a method as saved when the answer did not come from these tools. - **If a call returns `status: "error"` with an error of class `config`** (missing or rejected `PIPELEX_API_KEY`, unreachable API), STOP the same way and surface the error's `hint` verbatim; when it is about the key, read [where the key comes from](../shared/credentials.md#where-the-key-comes-from) before saying anything more. -- **`mthds_validate`** is optional, for one question: *would this save?* Never call it on the way to a save: `mthds_save_method` reads the files, validates them and saves those same bytes in one call. +- **`mthds_validate`** is optional, for one question: *would this save?* Never call it on the way to a save: `mthds_save_method` reads the files, validates them and saves those same bytes in one call. Ask it with `graph_page: false` wherever the tool lists that argument: a question writes no file, and `{path}` files would otherwise get `method-graph.html` beside them. ## Guards diff --git a/pipelex/skills/pipelex-explain/SKILL.md b/pipelex/skills/pipelex-explain/SKILL.md index 5baaaecb..3d95067d 100644 --- a/pipelex/skills/pipelex-explain/SKILL.md +++ b/pipelex/skills/pipelex-explain/SKILL.md @@ -43,7 +43,7 @@ A `PipeSignature` is **pending only when no concrete pipe of the same code exist ### 3. The verdict, when the workshop is there -One `mthds_validate` call over the same files. Submit every `.mthds` file beneath the bundle directory **except anything under a `runs/` directory**, where `/pipelex-run` saves a completed run's artifacts: a method that emits or echoes a `.mthds` file would otherwise have its own output submitted as part of its source. Prefer the path form `{path: }`. The workshop refuses a path outside **its own** working directory, where the harness launched it; relaunching the harness from a directory holding the bundle cures that. Inline `{content: , uri: }` is the fallback. The call adds two things and nothing else: the **verdict line** (whether it is valid, whether it is runnable, what is still pending) and, when the verdict carries a `main_pipe`, the **main pipe's typed signature**: its namespaced ref, each declared input with its concept and whether it is required, and the concept it produces. +One `mthds_validate` call over the same files. Submit every `.mthds` file beneath the bundle directory **except anything under a `runs/` directory**, where `/pipelex-run` saves a completed run's artifacts: a method that emits or echoes a `.mthds` file would otherwise have its own output submitted as part of its source. Prefer the path form `{path: }`. The workshop refuses a path outside **its own** working directory, where the harness launched it; relaunching the harness from a directory holding the bundle cures that. Inline `{content: , uri: }` is the fallback. **Pass `graph_page: false`** wherever the tool lists that argument: on `{path}` files the workshop otherwise writes the method's flowchart, `method-graph.html`, beside them, and this skill writes nothing. The call adds two things and nothing else: the **verdict line** (whether it is valid, whether it is runnable, what is still pending) and, when the verdict carries a `main_pipe`, the **main pipe's typed signature**: its namespaced ref, each declared input with its concept and whether it is required, and the concept it produces. Without the tool, explain from the source and **say the verdict was not checked**. Your own reading of the source is not a guess: the pipe types, the concepts and step 2's backlog are yours to state, saying whose reading it is. But do not present a validation verdict, a typed signature or a pending list as the workshop's when the workshop did not answer, and do not guess at validity. **On a target that is not on disk there is no such fallback.** diff --git a/templates/skills/pipelex-catalog/SKILL.md.j2 b/templates/skills/pipelex-catalog/SKILL.md.j2 index 6b8b3f02..878f9791 100644 --- a/templates/skills/pipelex-catalog/SKILL.md.j2 +++ b/templates/skills/pipelex-catalog/SKILL.md.j2 @@ -20,7 +20,7 @@ Every gesture between a bundle directory and the organization's method catalog: - **`mthds_list_methods`**, **`mthds_save_method`** and **`mthds_get_method`** are required, with no fallback: the catalog lives behind the API key. {% set mcp_absent_lead %}the catalog tools are{% endset -%} {% set mcp_absent_suffix %} Never report a method id, a name, or a method as saved when the answer did not come from these tools.{% endset -%} -{% set mcp_requirements_extra %}- **`mthds_validate`** is optional, for one question: *would this save?* Never call it on the way to a save: `mthds_save_method` reads the files, validates them and saves those same bytes in one call.{% endset -%} +{% set mcp_requirements_extra %}- **`mthds_validate`** is optional, for one question: *would this save?* Never call it on the way to a save: `mthds_save_method` reads the files, validates them and saves those same bytes in one call. Ask it with `graph_page: false` wherever the tool lists that argument: a question writes no file, and `{path}` files would otherwise get `method-graph.html` beside them.{% endset -%} {% include "skills/shared/mcp-requirements.md.j2" %} ## Guards diff --git a/templates/skills/pipelex-explain/SKILL.md.j2 b/templates/skills/pipelex-explain/SKILL.md.j2 index 30eab477..a3c313be 100644 --- a/templates/skills/pipelex-explain/SKILL.md.j2 +++ b/templates/skills/pipelex-explain/SKILL.md.j2 @@ -45,7 +45,7 @@ A `PipeSignature` is **pending only when no concrete pipe of the same code exist ### 3. The verdict, when the workshop is there -One `mthds_validate` call over the same files. {% include "skills/shared/validate-call.md.j2" %} The call adds two things and nothing else: the **verdict line** (whether it is valid, whether it is runnable, what is still pending) and, when the verdict carries a `main_pipe`, the **main pipe's typed signature**: its namespaced ref, each declared input with its concept and whether it is required, and the concept it produces. +One `mthds_validate` call over the same files. {% include "skills/shared/validate-call.md.j2" %} **Pass `graph_page: false`** wherever the tool lists that argument: on `{path}` files the workshop otherwise writes the method's flowchart, `method-graph.html`, beside them, and this skill writes nothing. The call adds two things and nothing else: the **verdict line** (whether it is valid, whether it is runnable, what is still pending) and, when the verdict carries a `main_pipe`, the **main pipe's typed signature**: its namespaced ref, each declared input with its concept and whether it is required, and the concept it produces. Without the tool, explain from the source and **say the verdict was not checked**. Your own reading of the source is not a guess: the pipe types, the concepts and step 2's backlog are yours to state, saying whose reading it is. But do not present a validation verdict, a typed signature or a pending list as the workshop's when the workshop did not answer, and do not guess at validity. **On a target that is not on disk there is no such fallback.** diff --git a/tests/unit/test_skill_guards.py b/tests/unit/test_skill_guards.py index eda3667a..5a75ae93 100644 --- a/tests/unit/test_skill_guards.py +++ b/tests/unit/test_skill_guards.py @@ -63,6 +63,7 @@ "Do not pass it, not even to a temporary directory.", "**pending only when no concrete pipe of the same code exists anywhere in the files you read.**", "**When the workshop answered, its `pending_signatures` is the authority**", + "**Pass `graph_page: false`** wherever the tool lists that argument", "explain from the source and **say the verdict was not checked**", "do not present a validation verdict, a typed signature or a pending list as the workshop's when the workshop did not answer", "**On a target that is not on disk there is no such fallback.**", @@ -161,6 +162,7 @@ "pipelex-catalog": ( "Never report a method id, a name, or a method as saved when the answer did not come from these tools.", "Never call it on the way to a save", + "Ask it with `graph_page: false` wherever the tool lists that argument", "**This skill writes no file itself.**", "Never hand-write or hand-edit a link file.", "**A save is never proposed as a side effect of other work**",