From 52d8f8b59c138398783aae493ed4568f1f1073c4 Mon Sep 17 00:00:00 2001 From: Louis Choquel Date: Sat, 26 Sep 2026 17:33:11 +0200 Subject: [PATCH] pipelex-explain keeps the workshop's method graph page and points at it Louis ruled on 2026-09-26 that the flowchart page mthds_validate writes beside path files is explain's default: step 3 no longer passes graph_page: false, and step 5 gives the page's path before the text flow, passes on the workshop's first-write note about ignoring it, and gives a graph_page.error in one line. The promise now reads that the skill writes nothing of its own and that the page is the one file it leaves, in the description, the opening line, the guard and the stop row. The catalog's "would this save?" check keeps its opt-out. Guards, the explain test, docs/skills.md, docs/decisions.md and the Unreleased entry follow. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01EJVC48w18XEdnvEc48jFAf --- CHANGELOG.md | 4 ++-- docs/decisions.md | 12 ++++++------ docs/skills.md | 4 ++-- pipelex-codex/skills/pipelex-explain/SKILL.md | 12 +++++++----- pipelex-vibe/skills/pipelex-explain/SKILL.md | 12 +++++++----- pipelex/skills/pipelex-explain/SKILL.md | 12 +++++++----- templates/skills/pipelex-explain/SKILL.md.j2 | 12 +++++++----- tests/unit/test_gen_skill_docs.py | 8 +++++--- tests/unit/test_skill_guards.py | 4 ++-- 9 files changed, 45 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac861b4..a89e26e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,9 @@ ## [Unreleased] -### Fixed +### Changed -- **`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. +- **`pipelex-explain` points at the method graph page**: the Pipelex tools are about to write a method's flowchart, `method-graph.html`, beside the files a validation reads by path, and `pipelex-explain` now gives that page's path before its text flow, so the whole method can be opened in a browser. The skill still writes nothing of its own, and the page is the one file an explanation of a bundle on disk leaves. `pipelex-catalog`'s check of whether a bundle would save asks the tools not to write the page, since that check is a question and writes no file. ## [0.9.2] - 2026-09-25 diff --git a/docs/decisions.md b/docs/decisions.md index 7cbe646..595a142 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -276,7 +276,7 @@ Boxes F and M of `wip/plugin-skills-gaps/design.md`. The skill was written for a - **A `PipeSignature` is pending only when no concrete pipe of the same code exists anywhere in the files read** (Louis's precision at ratification). Signature-driven design is additive: it leaves the satisfied header behind in the file that declared it. That is the same judgement `/pipelex-organize` already makes when it drops one, so the two skills agree about what a leftover header means. Where the workshop answered, its `pending_signatures` is the authority and a disagreement is reported rather than smoothed over — it means a file was missed or a code is spelled two ways. - **The workshop is optional, and the skill is deliberately outside `MCP_SKILLS`.** That tuple asserts a hard stop, and this skill does not have one for a bundle on disk: the source is right there, so an absent tool costs the verdict line and nothing else. The stop exists only for a catalog id or a published address, where nothing is on disk — so both bullets of the shared requirements block are scoped with `mcp_absent_suffix` and `mcp_config_suffix` rather than left to read as unconditional. - **A remote method is explained at the level of its contract.** `mthds_validate` with `method_ref` or `method_id` gives the verdict and the `main_pipe` signature, and `mthds_inputs_template` with `explicit: true` gives the input shapes; no bundle enters the conversation, which is the platform's design (`pipelex-mcp/SPEC.md`, Method Selectors) and not a gap in this skill. The skill says so plainly, so that a user knows they have the contract rather than a walkthrough. Reading a saved method's source waits on `mthds_get_method`, which box P adds in the workshop release; until then a catalog id is contract-level too. **Superseded in part (2026-09-22)** — that release shipped, so a catalog id is now read in full and only a published address stays at contract level; see *A catalog id is a target in every skill*. -- **Strictly read-only, amended at ratification.** The first draft wrote a `README.md` on request. It writes nothing now, and "document this pipeline" left the description because that phrase is what recruited the skill into writing files. The explanation stays in the conversation because that is where the user can read it, correct it and keep what they want of it. +- **Strictly read-only, amended at ratification.** The first draft wrote a `README.md` on request. It writes nothing now, and "document this pipeline" left the description because that phrase is what recruited the skill into writing files. The explanation stays in the conversation because that is where the user can read it, correct it and keep what they want of it. *(Amended 2026-09-26: the workshop's method graph page is the one file an explanation of a bundle on disk leaves; see "The workshop's method graph page".)* **`allowed-tools` pre-approves; it does not restrict.** Checked against Claude Code's current documentation while implementing box M: listing a tool waives its permission prompt for the skill, and a tool left off the list stays callable and simply asks first. So the narrow `Read`/`Grep`/`Glob` list does not make a write impossible in `pipelex-explain` — it makes one stop for the user, which is the guarantee worth having and the one the prose already claims. The shared frontmatter takes the list as `skill_tools` and defaults to the writing set, so every other skill renders byte-identically. @@ -682,15 +682,15 @@ 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) +## The workshop's method graph page: `pipelex-explain` shows it, the catalog's check turns 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-explain` keeps the page and says where it is**, ruled by Louis on 2026-09-26. The skill first passed `graph_page: false` (pipelex-plugins#88, `18a5101`) to keep its promise to write nothing, and the ruling reversed that the same day. Every other skill that validates by path already writes the page, so in most projects it is there anyway, and explain is the skill where a user most wants to see the flow. The read-only ruling above was about the skill writing its own documents, a README on request, and the page is not one: the workshop generates it, marks it, rewrites it on every validation and never replaces a file it did not write. So the promise now says that the skill writes nothing of its own and that the page is the one file it leaves, and the explanation gives the page's path before the text flow. That pointer is a guard, registered in `tests/unit/test_skill_guards.py`, because skipping it leaves a file in the user's tree without a word. `mthds_validate` is pre-approved in the skill's tool list, so the write takes no prompt, and the workshop's replacement policy is what bounds it. Only a bundle validated by path gets a page: a catalog id, a published address and inline files get none. +- **`pipelex-catalog`'s check of whether a bundle would save passes `graph_page: false`.** 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 check names 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. +- **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 from those skills is a change of its own. ## License & distribution diff --git a/docs/skills.md b/docs/skills.md index 8199a38..e5e369c 100644 --- a/docs/skills.md +++ b/docs/skills.md @@ -12,7 +12,7 @@ What each skill of the Pipelex plugin does, what it needs, and the tools it call Those three work on files, and each also takes a saved method's catalog id (`mt_…`): it finds the directory already linked to that method, or hands the pull to `/pipelex-catalog` first. Each ends by saying when the saved copy lacks the change it has made, and offers the update without making it. -**`pipelex-explain`** explains a method in plain language: its contract, its flow and every pipe in it, saying first whether the method is complete or a scaffold with a backlog. It reads a bundle directory or a single file, fetches and explains a saved method's source the same way, since it belongs to the organization asking, and explains a published method's address at the level of its contract, since its internals stay in the repository it names. It is strictly read-only and writes nothing to disk. For a bundle on disk the Pipelex tools are optional: they add a validation verdict to the explanation. +**`pipelex-explain`** explains a method in plain language: its contract, its flow and every pipe in it, saying first whether the method is complete or a scaffold with a backlog. It reads a bundle directory or a single file, fetches and explains a saved method's source the same way, since it belongs to the organization asking, and explains a published method's address at the level of its contract, since its internals stay in the repository it names. It changes nothing in the method and writes nothing of its own: the one file it leaves is the method's flowchart, which the Pipelex tools write beside a bundle on disk when they validate it, and the explanation says where it is. For a bundle on disk the Pipelex tools are optional: they add a validation verdict and that flowchart. ## Prepare inputs @@ -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. 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. +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` tells you where the page is, and `pipelex-catalog`'s check of whether a bundle would save turns it off, since a question writes no file. - **`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-explain/SKILL.md b/pipelex-codex/skills/pipelex-explain/SKILL.md index 5833ac4..8acbd7e 100644 --- a/pipelex-codex/skills/pipelex-explain/SKILL.md +++ b/pipelex-codex/skills/pipelex-explain/SKILL.md @@ -1,11 +1,11 @@ --- name: pipelex-explain -description: Explain an MTHDS method in plain language — its contract, its flow, and every pipe in it. Use when the user says "what does this pipeline do?", "explain this workflow", "explain this method", "walk me through this .mthds file", "describe the flow", "how does this work?", or wants to understand an existing MTHDS method. Takes a bundle directory, a single file, a registered method's catalog id (mt_…) — whose stored source it reads — or a published method's address, explained at the level of its contract. Strictly read-only — it explains in the conversation and writes nothing. +description: Explain an MTHDS method in plain language — its contract, its flow, and every pipe in it. Use when the user says "what does this pipeline do?", "explain this workflow", "explain this method", "walk me through this .mthds file", "describe the flow", "how does this work?", or wants to understand an existing MTHDS method. Takes a bundle directory, a single file, a registered method's catalog id (mt_…) — whose stored source it reads — or a published method's address, explained at the level of its contract. It changes nothing in the method — the explanation stays in the conversation, and the one file it leaves is the flowchart page the workshop writes beside a bundle on disk. --- # Explain an MTHDS method -Read a method and say what it does, in plain language. Reading costs nothing and changes nothing, so there is no confirmation to ask for. It takes: +Read a method and say what it does, in plain language. Reading costs nothing and changes nothing in the method, so there is no confirmation to ask for. It takes: - **A bundle directory**: every `.mthds` file beneath it outside `runs/`, read as one library. A single file is the same job with one file in it. - **A registered method's catalog id** (`mt_…`): the user's own organization's method, so its stored source is read and explained exactly as a bundle on disk is. @@ -20,7 +20,7 @@ Read a method and say what it does, in plain language. Reading costs nothing and ## Guards -- **This skill is strictly read-only.** It writes no file, saves no document and changes nothing in the bundle, not even when asked to "document" the method. The explanation stays in the conversation; a user who wants it written down is told that `/pipelex-design` and `/pipelex-edit` own the bundle, and the rest is theirs to paste. +- **This skill writes nothing of its own.** It saves no document and changes nothing in the bundle, not even when asked to "document" the method; the one file it leaves is the workshop's method graph page (step 3). The explanation stays in the conversation; a user who wants it written down is told that `/pipelex-design` and `/pipelex-edit` own the bundle, and the rest is theirs to paste. ## Steps @@ -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. **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. +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 to the explanation: 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. On `{path}` files the workshop also writes the method's flowchart beside them as `method-graph.html`, rewritten on every validation, and reports it as `graph_page`. 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.** @@ -46,6 +46,8 @@ Say first whether it is **complete** or a **scaffold with a backlog**, from step ### 5. The flow: the root first, then one passage per module +**When the verdict carries `graph_page.written: true`, give the page's `path` before the text flow**: it opens in a browser and draws the whole method. When the summary says the page is new, pass on its note that a project under git may want to ignore it. A `graph_page.error` gets one line, and the verdict stands. + **The root file gives the contract and the top-level flow**, then **one passage per module file**, each named by its file; a one-file method gets one passage, the simple case and not a missing structure. Trace the flow from the main pipe, reading the controllers in their own terms: | Pipe | How to read it | @@ -72,7 +74,7 @@ Output: final_output | Condition | Do this | |---|---| -| the user asks for the explanation in a file | explain in the conversation, say this skill writes nothing, and name the skill that does | +| the user asks for the explanation in a file | explain in the conversation, say this skill writes no document, and name the skill that does | | the workshop is absent, on a local bundle | explain from the source and say the verdict was not checked | | the workshop is absent, on an id or an address | stop per the Requirements: there is nothing to read | | `mthds_get_method` is absent while the other tools answer | explain the id at contract level, say the source was not read, and name the cause [not-on-disk.md](references/not-on-disk.md) gives | diff --git a/pipelex-vibe/skills/pipelex-explain/SKILL.md b/pipelex-vibe/skills/pipelex-explain/SKILL.md index 9256d6c..4830bcb 100644 --- a/pipelex-vibe/skills/pipelex-explain/SKILL.md +++ b/pipelex-vibe/skills/pipelex-explain/SKILL.md @@ -1,11 +1,11 @@ --- name: pipelex-explain -description: Explain an MTHDS method in plain language — its contract, its flow, and every pipe in it. Use when the user says "what does this pipeline do?", "explain this workflow", "explain this method", "walk me through this .mthds file", "describe the flow", "how does this work?", or wants to understand an existing MTHDS method. Takes a bundle directory, a single file, a registered method's catalog id (mt_…) — whose stored source it reads — or a published method's address, explained at the level of its contract. Strictly read-only — it explains in the conversation and writes nothing. +description: Explain an MTHDS method in plain language — its contract, its flow, and every pipe in it. Use when the user says "what does this pipeline do?", "explain this workflow", "explain this method", "walk me through this .mthds file", "describe the flow", "how does this work?", or wants to understand an existing MTHDS method. Takes a bundle directory, a single file, a registered method's catalog id (mt_…) — whose stored source it reads — or a published method's address, explained at the level of its contract. It changes nothing in the method — the explanation stays in the conversation, and the one file it leaves is the flowchart page the workshop writes beside a bundle on disk. --- # Explain an MTHDS method -Read a method and say what it does, in plain language. Reading costs nothing and changes nothing, so there is no confirmation to ask for. It takes: +Read a method and say what it does, in plain language. Reading costs nothing and changes nothing in the method, so there is no confirmation to ask for. It takes: - **A bundle directory**: every `.mthds` file beneath it outside `runs/`, read as one library. A single file is the same job with one file in it. - **A registered method's catalog id** (`mt_…`): the user's own organization's method, so its stored source is read and explained exactly as a bundle on disk is. @@ -20,7 +20,7 @@ Read a method and say what it does, in plain language. Reading costs nothing and ## Guards -- **This skill is strictly read-only.** It writes no file, saves no document and changes nothing in the bundle, not even when asked to "document" the method. The explanation stays in the conversation; a user who wants it written down is told that `/pipelex-design` and `/pipelex-edit` own the bundle, and the rest is theirs to paste. +- **This skill writes nothing of its own.** It saves no document and changes nothing in the bundle, not even when asked to "document" the method; the one file it leaves is the workshop's method graph page (step 3). The explanation stays in the conversation; a user who wants it written down is told that `/pipelex-design` and `/pipelex-edit` own the bundle, and the rest is theirs to paste. ## Steps @@ -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. **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. +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 to the explanation: 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. On `{path}` files the workshop also writes the method's flowchart beside them as `method-graph.html`, rewritten on every validation, and reports it as `graph_page`. 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.** @@ -46,6 +46,8 @@ Say first whether it is **complete** or a **scaffold with a backlog**, from step ### 5. The flow: the root first, then one passage per module +**When the verdict carries `graph_page.written: true`, give the page's `path` before the text flow**: it opens in a browser and draws the whole method. When the summary says the page is new, pass on its note that a project under git may want to ignore it. A `graph_page.error` gets one line, and the verdict stands. + **The root file gives the contract and the top-level flow**, then **one passage per module file**, each named by its file; a one-file method gets one passage, the simple case and not a missing structure. Trace the flow from the main pipe, reading the controllers in their own terms: | Pipe | How to read it | @@ -72,7 +74,7 @@ Output: final_output | Condition | Do this | |---|---| -| the user asks for the explanation in a file | explain in the conversation, say this skill writes nothing, and name the skill that does | +| the user asks for the explanation in a file | explain in the conversation, say this skill writes no document, and name the skill that does | | the workshop is absent, on a local bundle | explain from the source and say the verdict was not checked | | the workshop is absent, on an id or an address | stop per the Requirements: there is nothing to read | | `mthds_get_method` is absent while the other tools answer | explain the id at contract level, say the source was not read, and name the cause [not-on-disk.md](references/not-on-disk.md) gives | diff --git a/pipelex/skills/pipelex-explain/SKILL.md b/pipelex/skills/pipelex-explain/SKILL.md index 3d95067..ee8ea76 100644 --- a/pipelex/skills/pipelex-explain/SKILL.md +++ b/pipelex/skills/pipelex-explain/SKILL.md @@ -1,6 +1,6 @@ --- name: pipelex-explain -description: Explain an MTHDS method in plain language — its contract, its flow, and every pipe in it. Use when the user says "what does this pipeline do?", "explain this workflow", "explain this method", "walk me through this .mthds file", "describe the flow", "how does this work?", or wants to understand an existing MTHDS method. Takes a bundle directory, a single file, a registered method's catalog id (mt_…) — whose stored source it reads — or a published method's address, explained at the level of its contract. Strictly read-only — it explains in the conversation and writes nothing. +description: Explain an MTHDS method in plain language — its contract, its flow, and every pipe in it. Use when the user says "what does this pipeline do?", "explain this workflow", "explain this method", "walk me through this .mthds file", "describe the flow", "how does this work?", or wants to understand an existing MTHDS method. Takes a bundle directory, a single file, a registered method's catalog id (mt_…) — whose stored source it reads — or a published method's address, explained at the level of its contract. It changes nothing in the method — the explanation stays in the conversation, and the one file it leaves is the flowchart page the workshop writes beside a bundle on disk. allowed-tools: - Read - Grep @@ -12,7 +12,7 @@ allowed-tools: # Explain an MTHDS method -Read a method and say what it does, in plain language. Reading costs nothing and changes nothing, so there is no confirmation to ask for. It takes: +Read a method and say what it does, in plain language. Reading costs nothing and changes nothing in the method, so there is no confirmation to ask for. It takes: - **A bundle directory**: every `.mthds` file beneath it outside `runs/`, read as one library. A single file is the same job with one file in it. - **A registered method's catalog id** (`mt_…`): the user's own organization's method, so its stored source is read and explained exactly as a bundle on disk is. @@ -27,7 +27,7 @@ Read a method and say what it does, in plain language. Reading costs nothing and ## Guards -- **This skill is strictly read-only.** It writes no file, saves no document and changes nothing in the bundle, not even when asked to "document" the method. The explanation stays in the conversation; a user who wants it written down is told that `/pipelex-design` and `/pipelex-edit` own the bundle, and the rest is theirs to paste. +- **This skill writes nothing of its own.** It saves no document and changes nothing in the bundle, not even when asked to "document" the method; the one file it leaves is the workshop's method graph page (step 3). The explanation stays in the conversation; a user who wants it written down is told that `/pipelex-design` and `/pipelex-edit` own the bundle, and the rest is theirs to paste. ## Steps @@ -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. **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. +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 to the explanation: 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. On `{path}` files the workshop also writes the method's flowchart beside them as `method-graph.html`, rewritten on every validation, and reports it as `graph_page`. 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.** @@ -53,6 +53,8 @@ Say first whether it is **complete** or a **scaffold with a backlog**, from step ### 5. The flow: the root first, then one passage per module +**When the verdict carries `graph_page.written: true`, give the page's `path` before the text flow**: it opens in a browser and draws the whole method. When the summary says the page is new, pass on its note that a project under git may want to ignore it. A `graph_page.error` gets one line, and the verdict stands. + **The root file gives the contract and the top-level flow**, then **one passage per module file**, each named by its file; a one-file method gets one passage, the simple case and not a missing structure. Trace the flow from the main pipe, reading the controllers in their own terms: | Pipe | How to read it | @@ -79,7 +81,7 @@ Output: final_output | Condition | Do this | |---|---| -| the user asks for the explanation in a file | explain in the conversation, say this skill writes nothing, and name the skill that does | +| the user asks for the explanation in a file | explain in the conversation, say this skill writes no document, and name the skill that does | | the workshop is absent, on a local bundle | explain from the source and say the verdict was not checked | | the workshop is absent, on an id or an address | stop per the Requirements: there is nothing to read | | `mthds_get_method` is absent while the other tools answer | explain the id at contract level, say the source was not read, and name the cause [not-on-disk.md](references/not-on-disk.md) gives | diff --git a/templates/skills/pipelex-explain/SKILL.md.j2 b/templates/skills/pipelex-explain/SKILL.md.j2 index a3c313b..ae47c0c 100644 --- a/templates/skills/pipelex-explain/SKILL.md.j2 +++ b/templates/skills/pipelex-explain/SKILL.md.j2 @@ -1,6 +1,6 @@ --- name: pipelex-explain -description: Explain an MTHDS method in plain language — its contract, its flow, and every pipe in it. Use when the user says "what does this pipeline do?", "explain this workflow", "explain this method", "walk me through this .mthds file", "describe the flow", "how does this work?", or wants to understand an existing MTHDS method. Takes a bundle directory, a single file, a registered method's catalog id (mt_…) — whose stored source it reads — or a published method's address, explained at the level of its contract. Strictly read-only — it explains in the conversation and writes nothing. +description: Explain an MTHDS method in plain language — its contract, its flow, and every pipe in it. Use when the user says "what does this pipeline do?", "explain this workflow", "explain this method", "walk me through this .mthds file", "describe the flow", "how does this work?", or wants to understand an existing MTHDS method. Takes a bundle directory, a single file, a registered method's catalog id (mt_…) — whose stored source it reads — or a published method's address, explained at the level of its contract. It changes nothing in the method — the explanation stays in the conversation, and the one file it leaves is the flowchart page the workshop writes beside a bundle on disk. {%- set skill_tools = ["Read", "Grep", "Glob"] %} {%- include "skills/shared/frontmatter.md.j2" %} {%- if platform == "claude" %} @@ -12,7 +12,7 @@ description: Explain an MTHDS method in plain language — its contract, its flo # Explain an MTHDS method -Read a method and say what it does, in plain language. Reading costs nothing and changes nothing, so there is no confirmation to ask for. It takes: +Read a method and say what it does, in plain language. Reading costs nothing and changes nothing in the method, so there is no confirmation to ask for. It takes: - **A bundle directory**: every `.mthds` file beneath it outside `runs/`, read as one library. A single file is the same job with one file in it. - **A registered method's catalog id** (`mt_…`): the user's own organization's method, so its stored source is read and explained exactly as a bundle on disk is. @@ -29,7 +29,7 @@ Read a method and say what it does, in plain language. Reading costs nothing and ## Guards -- **This skill is strictly read-only.** It writes no file, saves no document and changes nothing in the bundle, not even when asked to "document" the method. The explanation stays in the conversation; a user who wants it written down is told that `/pipelex-design` and `/pipelex-edit` own the bundle, and the rest is theirs to paste. +- **This skill writes nothing of its own.** It saves no document and changes nothing in the bundle, not even when asked to "document" the method; the one file it leaves is the workshop's method graph page (step 3). The explanation stays in the conversation; a user who wants it written down is told that `/pipelex-design` and `/pipelex-edit` own the bundle, and the rest is theirs to paste. ## Steps @@ -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" %} **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. +One `mthds_validate` call over the same files. {% include "skills/shared/validate-call.md.j2" %} The call adds two things to the explanation: 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. On `{path}` files the workshop also writes the method's flowchart beside them as `method-graph.html`, rewritten on every validation, and reports it as `graph_page`. 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.** @@ -55,6 +55,8 @@ Say first whether it is **complete** or a **scaffold with a backlog**, from step ### 5. The flow: the root first, then one passage per module +**When the verdict carries `graph_page.written: true`, give the page's `path` before the text flow**: it opens in a browser and draws the whole method. When the summary says the page is new, pass on its note that a project under git may want to ignore it. A `graph_page.error` gets one line, and the verdict stands. + **The root file gives the contract and the top-level flow**, then **one passage per module file**, each named by its file; a one-file method gets one passage, the simple case and not a missing structure. Trace the flow from the main pipe, reading the controllers in their own terms: | Pipe | How to read it | @@ -81,7 +83,7 @@ Output: final_output | Condition | Do this | |---|---| -| the user asks for the explanation in a file | explain in the conversation, say this skill writes nothing, and name the skill that does | +| the user asks for the explanation in a file | explain in the conversation, say this skill writes no document, and name the skill that does | | the workshop is absent, on a local bundle | explain from the source and say the verdict was not checked | | the workshop is absent, on an id or an address | stop per the Requirements: there is nothing to read | | `mthds_get_method` is absent while the other tools answer | explain the id at contract level, say the source was not read, and name the cause [not-on-disk.md](references/not-on-disk.md) gives | diff --git a/tests/unit/test_gen_skill_docs.py b/tests/unit/test_gen_skill_docs.py index f8dded9..60d343c 100644 --- a/tests/unit/test_gen_skill_docs.py +++ b/tests/unit/test_gen_skill_docs.py @@ -2209,10 +2209,12 @@ def test_one_selector_per_call(self) -> None: def test_the_skill_writes_nothing_and_says_so(self) -> None: """Box F, amended at ratification: the first draft wrote a `README.md` on - request.""" + request. Amended 2026-09-26: the workshop's method graph page is the one + file an explanation of a bundle on disk leaves, and the skill says so.""" body = self.body() - assert "strictly read-only" in body.lower() - assert "writes no file" in body + assert "writes nothing of its own" in body + assert "the one file it leaves is the workshop's method graph page" in body + assert "graph_page: false" not in body def test_the_description_no_longer_offers_to_document(self) -> None: """Box F: "document this pipeline" leaves the description, because it is diff --git a/tests/unit/test_skill_guards.py b/tests/unit/test_skill_guards.py index 5a75ae9..4e57842 100644 --- a/tests/unit/test_skill_guards.py +++ b/tests/unit/test_skill_guards.py @@ -57,14 +57,14 @@ "a narrower explanation, not a stop", "That stop is only for a target that lives on the platform", "Same scope: on a local bundle a `config` error costs the verdict line and nothing else", - "**This skill is strictly read-only.** It writes no file, saves no document and changes nothing in the bundle", + "**This skill writes nothing of its own.** It saves no document and changes nothing in the bundle", "**Read them all before saying anything about any of them.**", "with the `method_id` and **no `output_dir`**", "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**", + "give the page's `path` before the text flow", "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.**", "whether it is **complete** or a **scaffold with a backlog**",