From 20294b68d18faf7f890e3d27e6d3a10653b8aacc Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Sat, 29 Aug 2026 22:20:30 +0200 Subject: [PATCH 1/2] Say where a plan file belongs, in the skill that writes one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `rhei-plan-writer` skill specified the plan format, states, ids, and validation, and never said where the file goes. An agent following it saved a plan at a host repository's root; `rhei init` then refused to adopt the directory until the file moved. The refusal is the good case. Inside a project that already exists there is no refusal at all: discovery reads the project directory's immediate children, so a plan at the repository root or under `panta/plans/` is not a rhei, `rhei list` never shows its tickets, and `rhei validate` prints "Validation succeeded" over both. The plan is simply not there, and nothing says so. `## File Extension` becomes `## File Location and Name`, because naming and placing a plan are one decision taken at one moment and the old heading advertised half of it. It gives the default location for both plan shapes, says to look for `index.panta.md` or run `rhei list` before writing, and names what silence looks like when the guess is wrong. Creating the project stays the human's call. `rhei init` writes `.gitignore` and `AGENTS.md` in someone's repository, and the skill already says so under `rhei new`; the guidance is to ask for it and write to `panta/.rhei.md` meanwhile, which a later `rhei init` adopts. It also says that init gitignores `panta/`, so the plan will not appear in `git status` — and that the versioned route is `rhei init --here`, rather than leaving the question hanging. The naming rule grew the two constraints that fail loudly and were unwritten: a Directory Workspace takes its id from the directory name, and an id must start with a letter and hold only letters, digits, `_` or `-`, with `basin` reserved for the project's unfiled inbox. Planning Workflow gains a save step. The section is only read by an agent that reaches it, and an agent working the numbered list went from "set initial states" to "run the validation checklist" without ever being told where the file goes. Fixes #68 --- crates/rhei-cli/skills/rhei-plan-writer/SKILL.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/rhei-cli/skills/rhei-plan-writer/SKILL.md b/crates/rhei-cli/skills/rhei-plan-writer/SKILL.md index bcdfc713..65a3739b 100644 --- a/crates/rhei-cli/skills/rhei-plan-writer/SKILL.md +++ b/crates/rhei-cli/skills/rhei-plan-writer/SKILL.md @@ -43,7 +43,7 @@ Use this exact block shape for every task node (root and child): ``` Apply these rules: -- **Every task MUST have a `**State:**` field**, placed as the first metadata line directly under the heading (no blank line between). A task without `**State:**` is invalid and will fail validation — this is the single most common authoring mistake, so check for it before finishing (see *Planning Workflow* step 9). +- **Every task MUST have a `**State:**` field**, placed as the first metadata line directly under the heading (no blank line between). A task without `**State:**` is invalid and will fail validation — this is the single most common authoring mistake, so check for it before finishing (see *Planning Workflow* step 10). - Place `**Prior:**` second when present; omit it when no prerequisites exist. - **Do not author `**Assignee:**` or `> **Result:**` blocks** — both are runtime-owned: `rhei next` writes `**Assignee:**` when a task is claimed; `rhei complete` removes it and writes `> **Result:** [](runtime/results/.md)`, where `` is the project-qualified ticket id (e.g. `plan.1` for `plan.rhei.md`). - Separate metadata from description with a blank line. Emit no other metadata fields. @@ -110,8 +110,9 @@ structure: 7. Set initial states correctly: - New plan: set every task to the active machine's profile `initial` (`pending` for the built-in machine). - Existing plan update: preserve truthful terminal states (`completed`, `cancelled`) unless explicitly changed, and preserve any `**Assignee:**` / `> **Result:**` blocks the runtime has written. -8. Run the validation checklist before returning output. -9. **Final scan:** re-read every `### Task` / `#### Task` / deeper heading (or other declared kinds) and confirm each is immediately followed by a `**State:**` line. This is the most common defect — always perform this check last. +8. Save the plan where *File Location and Name* says — in the host project's `panta/`, never at the repository root. +9. Run the validation checklist before returning output. +10. **Final scan:** re-read every `### Task` / `#### Task` / deeper heading (or other declared kinds) and confirm each is immediately followed by a `**State:**` line. This is the most common defect — always perform this check last. ## Validation Checklist @@ -129,9 +130,13 @@ Validate every response against all checks: When the CLI is available, run `rhei validate ` after writing — it performs the full grammar, state, dependency, link, and terminal-coherence checks the checklist only approximates. -## File Extension +## File Location and Name -Save Single-File Plans as `.rhei.md` — the file stem becomes the rhei id that prefixes every ticket id in command output (`plan.rhei.md` → tickets `plan.1`, `plan.2`, ...), so choose it like an identifier. A bare `.md` extension is not a valid single-file rhei. The Directory Workspace root file is always `index.rhei.md`. +Plans live in the host repository's Panta project: `panta/.rhei.md` for a Single-File Plan, `panta//index.rhei.md` for a Directory Workspace. Before writing anything, look for `index.panta.md` — in the working directory or in its `panta/` child — or just run `rhei list`. When the project is there, `rhei new ""` writes the file into it from any directory beneath the host and you never choose a path (see *Adding to a Live Project*); hand-write into that same directory only when the CLI is unavailable. Discovery reads the project directory's immediate children and nothing else, so a plan left at the repository root or tucked into a subfolder of `panta/` is not a rhei — and nothing tells you: `rhei list` never shows its tickets and `rhei validate` still succeeds. + +When the host has no project yet, creating one stays the human's call, because `rhei init` writes `.gitignore` and `AGENTS.md` in their repository. Ask for it, and write the plan to `panta/<id>.rhei.md` meanwhile — `rhei init` adopts the plans it finds there, while a `.rhei.md` left at the repository root makes it refuse until the file is moved. Init also gitignores `panta/`, so say that the plan will not appear in `git status`; leave that entry alone unless the user wants the plan versioned, which is `rhei init --here` or dropping the host's `panta/` line, and is theirs to decide. + +Name a Single-File Plan `<id>.rhei.md` and a Directory Workspace directory `<id>/` — the file stem, or the directory name, becomes the rhei id that prefixes every ticket id in command output (`plan.rhei.md` → tickets `plan.1`, `plan.2`, ...), so choose it like an identifier: it must start with a letter and contain only letters, digits, `_`, or `-`, and `basin` is reserved for the project's unfiled inbox. A bare `.md` extension is not a valid single-file rhei. The Directory Workspace root file is always `index.rhei.md`. ## Adding to a Live Project From ed2e954ea52d9f4c07a4dbca4beea596f45eea25 Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic <vojin.jovanovic@oracle.com> Date: Sat, 29 Aug 2026 22:21:08 +0200 Subject: [PATCH 2/2] Record the plan-location skill fix in the changelog --- docs/changelog.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index 50d258f5..46c5fc46 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,30 @@ ## Unreleased +- **The `rhei-plan-writer` skill says where a plan file belongs.** It specified + the plan format, states, ids, and validation and never named a location, so an + agent following it saved a plan at a host repository's root and `rhei init` + refused to adopt the directory until the file moved. The refusal is the good + case: inside a project that already exists, discovery reads the project + directory's immediate children and nothing else, so a plan at the repository + root or under `panta/plans/` is not a rhei — `rhei list` never shows its + tickets and `rhei validate` prints "Validation succeeded" over it. `## File + Extension` becomes `## File Location and Name`, because naming a plan and + placing it are one decision taken at one moment; it gives the default for both + plan shapes, says to look for `index.panta.md` or run `rhei list` first, + prefers `rhei new` over hand-writing a path, and names what the silence looks + like when the guess is wrong. Creating the project stays the human's call, as + the skill already said of `rhei init` under `rhei new` — the guidance is to ask + for it and write to `panta/<id>.rhei.md` meanwhile, which a later init adopts — + and the gitignored `panta/` now comes with its answer, `rhei init --here`, + rather than only the question. The naming rule gained the two constraints that + fail loudly and were unwritten: a Directory Workspace takes its id from the + directory name, and an id must start with a letter and hold only letters, + digits, `_` or `-`, with `basin` reserved. `## Planning Workflow` gained a save + step, because an agent working the numbered list went from setting initial + states to running the validation checklist without ever being told where the + file goes. (PR #109) + - **`rhei run` asks the whole completion condition before a pass skips an agent invocation.** The condition has three parts — exit `0`, the declared `outputs:` on disk, and, when the edge the exit selects lands on a `final: