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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 170 additions & 0 deletions .freethinking/specs/spec-approval-summary/design.md

Large diffs are not rendered by default.

113 changes: 113 additions & 0 deletions .freethinking/specs/spec-approval-summary/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Requirements Document

## Introduction

On its spec route, the start-task skill writes `requirements.md`, `design.md` and `tasks.md` in turn and asks the author to approve each one. Today it prints each document in full into the conversation before the approval question, and prints it again after every change-request round, so a three-document spec with one revision each puts six full documents in front of the author, who reads the file in an editor anyway. This change makes the skill show the document's path and a short summary instead: enough for the author to know what they are approving at a high level and to trust it, without flooding the conversation. The author opens the file before approving; the approval question itself does not change. Only start-task changes. GitHub issue #47 is the ticket.

## Glossary

- **Skill**: The start-task skill at `plugins/freethinking/skills/start-task/SKILL.md`.
- **Author**: The person running the Skill, who approves each document.
- **Spec_Folder**: `.freethinking/specs/<task-name>/`, where the three Spec_Documents of a task live.
- **Spec_Document**: One of `requirements.md`, `design.md` and `tasks.md` in the Spec_Folder.
- **Approval_Question**: The question the Skill puts with the AskUserQuestion tool after each Spec_Document, header `Approve`, options `Approved` and `Changes needed`.
- **Document_Summary**: The text the Skill shows in place of a Spec_Document's body: the document's path, its Highlights, and a short account of the rest at the depth the requirements below set for that document.
- **Highlight**: A passage of a Spec_Document that its Document_Summary quotes verbatim because the document's shape names it: the user story of each requirement in `requirements.md`, and the paragraph of each Key_Decision in `design.md`.
- **Leaf_Task**: A checkbox task in `tasks.md` with no sub-tasks, the unit the Task Dependency Graph lists.
- **Revision_Summary**: The text the Skill shows after revising a Spec_Document on a change request: the document's path and what changed, section by section.
- **Key_Decision**: A design decision that chose between alternatives with a real trade-off, so the Author may disagree with it.
- **Wave**: One entry of the `waves` block in a `tasks.md` Task Dependency Graph.
- **Hand_Backs_Bullet**: The bullet in the Skill's "Working with the author" section that says what the Skill hands back on each route.
- **README**: The plugin README at `plugins/freethinking/README.md`, whose Skills table describes the Skill.
- **Eval_Case**: A folder under `evals/` with a `prompt.md` and graders, run by its component's make target; Requirement 7's case is under `evals/skills/start-task/`, run with `make eval-skill-start-task`.
- **System**: The handbook plugin: the Skill, the README and the Eval_Cases.

## Requirements

### Requirement 1: The path and a summary replace the full text

**User Story:** As an Author approving a Spec_Document, I want the Skill to tell me where the file is and what it says at a high level, so that I can open the file and approve it without the whole document being printed into the conversation.

#### Acceptance Criteria

1. WHEN the Skill has written a Spec_Document, THE Skill SHALL show a Document_Summary and put the Approval_Question, in that order and in the same message, and SHALL not reproduce the Spec_Document's body in the conversation.
2. THE Document_Summary SHALL open with the Spec_Document's path, relative to the repository root, on its own line.
3. THE Document_Summary SHALL say, once, that the Author can open the file before answering.
4. THE Document_Summary SHALL quote from the Spec_Document only the Highlights Requirements 2 and 3 name for that document, and SHALL summarise the rest, so the Document_Summary stays far shorter than the file.
5. THE Approval_Question SHALL keep its header, its options and its wording as they are today.
6. WHEN the Skill resumes at an existing Spec_Document that the Author says is not approved, THE Skill SHALL show it the same way, as a Document_Summary followed by the Approval_Question.

### Requirement 2: The requirements summary

**User Story:** As an Author, I want the requirements summarised as each requirement's user story, so that I know at a high level what is being built and for whom before I read the criteria in the file.

#### Acceptance Criteria

1. THE Document_Summary for `requirements.md` SHALL list every requirement, in order, as one entry giving its number and title, then its user story, the first sentence of the requirement, quoted verbatim as its Highlight.
2. THE Document_Summary for `requirements.md` SHALL quote no acceptance criterion and SHALL not list the glossary.
3. IF the requirements leave a question open that the Author did not answer, THEN THE Document_Summary SHALL name it after the requirement entries.

### Requirement 3: The design summary

**User Story:** As an Author, I want the design's key decisions quoted for review and the rest summarised for discussion, so that I can push back on a decision and talk through the shape of the solution without reading the lower-level detail in the conversation.

#### Acceptance Criteria

1. THE Document_Summary for `design.md` SHALL open with each Key_Decision as a Highlight, its decision paragraph quoted verbatim, in the document's order, as the things for the Author to review.
2. THE Document_Summary for `design.md` SHALL then summarise the rest for discussion: the main flows and design concepts, the components or parts, what each is for, and how a request or piece of work moves through them, in a few lines.
3. THE Document_Summary for `design.md` SHALL leave out the lower-level content: data fields and types, the operations table, the correctness properties, the error-handling rows and the testing strategy.
4. WHEN the Skill's traceability check finds a requirement the design does not satisfy or a decision that traces to no requirement, THE Document_Summary SHALL name it, as the Skill already requires.

### Requirement 4: The tasks summary

**User Story:** As an Author, I want the task list shown as a table of its leaf tasks by wave, so that I can accept the order of the work at a glance, in the shape implement-spec later shows me at its graph check.

#### Acceptance Criteria

1. THE Document_Summary for `tasks.md` SHALL be a table with one row per Leaf_Task in Wave order, with columns for the Wave, the task's number, what it builds in one line, whether it is an optional test, the requirements it cites and the design property it names if any.
2. THE Document_Summary for `tasks.md` SHALL carry none of a task's detail bullets and SHALL quote nothing else from the document.

### Requirement 5: A revision shows what changed

**User Story:** As an Author who asked for changes, I want to see plainly what changed in the document, so that I can check my request was understood without rereading the whole file.

#### Acceptance Criteria

1. WHEN the Author answers `Changes needed` and the Skill has revised the Spec_Document, THE Skill SHALL show a Revision_Summary and put the Approval_Question again, in that order and in the same message.
2. THE Revision_Summary SHALL open with the Spec_Document's path and SHALL list one line per section that changed, saying what changed in it; a section that did not change SHALL not be listed.
3. IF part of the Author's change request was not applied, THEN THE Revision_Summary SHALL say which part and why, before the Approval_Question.
4. THE Revision_Summary SHALL quote a Highlight that changed, a user story or a Key_Decision, and SHALL otherwise say what changed without reproducing the Spec_Document's body.

### Requirement 6: The skill text and the README agree

**User Story:** As a reader of the Skill or the README, I want them to describe the hand-back as it now works, so that neither promises a full print the Skill no longer makes.

#### Acceptance Criteria

1. THE Hand_Backs_Bullet SHALL say that on Spec_Route the Skill hands back each Spec_Document as its path and a Document_Summary, and a revision as a Revision_Summary.
2. THE Skill's steps that write the three Spec_Documents SHALL each say to show the Document_Summary at the depth Requirements 2, 3 and 4 set for that document, and the Skill SHALL hold the shape of the Revision_Summary once, where the three steps can refer to it.
3. THE README's row for the Skill SHALL say that the Author sees each document's path and a summary and approves each before the next.
4. THE System SHALL change no skill, agent or rule beyond what Requirements 1 to 7 and 8.1 name.

### Requirement 7: An eval proves the shape

**User Story:** As a maintainer, I want an Eval_Case that reaches a written Spec_Document and grades its hand-back, so that the change is proven by behaviour rather than by reading the skill text.

#### Acceptance Criteria

1. THE System SHALL add one Eval_Case that gives the Skill a request on the calc fixture with the spec questions answered in the request, so that the run writes `requirements.md` and ends at its Approval_Question.
2. THE Eval_Case SHALL grade that `requirements.md` was written in the Spec_Folder, at `.freethinking/specs/*/requirements.md`, that the final message names its path, that it does not reproduce the document's sections, that it quotes a user story, that no criterion is reproduced, and that every entry quotes its user story; whether there is one entry per requirement is read by the wave reviewer and by the first real spec written with the Skill, since a grader that sees only the reply cannot count the document's requirements.
3. THE Eval_Case SHALL pass `make validate` and carry the `start-task` tag so `make eval-skill-start-task` selects it.
4. THE System SHALL run `make eval-skill-start-task` after the change, and SHALL record the result table in the pull request's Testing section, with every existing case still passing.

### Requirement 8: Specs live under `.freethinking/specs/`

**User Story:** As a maintainer of the plugin and its forks, I want every spec to live in the Spec_Folder, `.freethinking/specs/<task-name>/`, instead of `.claude/specs/<task-name>/`, so that the folder names the plugin rather than one tool, a fork for another tool keeps the same path, and the eval sandbox, which refuses every write under `.claude/`, can grade a spec being written. GitHub issue #48 is the ticket.

#### Acceptance Criteria

1. THE start-task Skill, THE implement-spec Skill, THE task-executor agent, THE workflow Rule and THE README SHALL name the Spec_Folder wherever they name `.claude/specs/<task-name>/` today, and THE README's "Tune the plugin for a repository" section SHALL say that `.freethinking/specs/` holds specs beside the `<skill>/<file>.md` overrides.
2. THE root README SHALL name the Spec_Folder where it names the old folder.
3. THE Eval_Cases SHALL plant, name and grade the Spec_Folder wherever they plant, name or grade `.claude/specs/` today, their fixture folders moved with `git mv`, and `evals/README.md` SHALL replace its note that edits under `.claude/` cannot be graded with one saying the Spec_Folder is writable in the sandbox while `.claude/` is not.
4. THE System SHALL move this repository's spec records from `.claude/specs/` to `.freethinking/specs/` with `git mv`, content untouched, this spec included.
5. IF the sandbox refuses a write under `.freethinking/` too, THEN THE System SHALL stop and report it, since the folder would then need another name.
57 changes: 57 additions & 0 deletions .freethinking/specs/spec-approval-summary/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Implementation Plan

## Overview

The skill text comes first, since the README row and the eval case both describe what it says. The README row and the eval case follow in one wave, touching disjoint files. The spec folder move, found necessary when the eval sandbox refused the write under `.claude/`, is one wave of three tasks on disjoint file groups. The last wave is the author's: the eval runs that cost tokens, with the table for the pull request. Each task is proved by `make validate` plus the ephemeral check its text names; the eval run is the integration proof. GitHub issue #47 is the ticket.

## Tasks

- [x] 1. Change the start-task skill's hand-back
- In `plugins/freethinking/skills/start-task/SKILL.md`, make the five edits of the design's SKILL.md section, each quoted there as it will read: the Hand-backs bullet; the new "Showing a document" section after "Working with the author" and before step 1, with its two paragraphs; the resume sentence in step 1; the closing paragraph of steps 4, 5 and 6, each saying its summary's depth and the Showing a document section, with the AskUserQuestion sentence kept as it is; and nothing else. Ephemeral check: `grep -c 'in full' SKILL.md` is 0, `grep -c 'Showing a document' SKILL.md` is 6 (the heading, the Hand-backs bullet, step 1 and the three steps), the Approve question's header, options and wording are unchanged by `git diff`; `make validate` passes
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.1, 2.2, 2.3, 3.1, 3.2, 3.3, 3.4, 4.1, 4.2, 5.1, 5.2, 5.3, 5.4, 6.1, 6.2, 6.4_

- [x] 2. Update the README row
- In `plugins/freethinking/README.md`, replace the last clause of the `start-task` row, "with you approving each document before the next", with "showing you each document as its path and a short summary and asking you to approve it before the next", as the design's README section gives it; `make validate` passes, which runs `checks/test_descriptions.py`
- _Requirements: 6.3_

- [x] 3. Add the eval case
- Create `evals/skills/start-task/summarises-requirements/` as the design's eval section lays it out: `case.yaml` naming `scaffold.sh`; `scaffold.sh` as a regular executable file that finds the repository root and runs `evals/fixtures/setup.sh calc main`; `prompt.md` with the frontmatter fields and the prompt quoted in the design; and the eight graders of the design's table, `writes-requirements`, `names-the-path`, `not-reprinted`, `offers-approval`, `quotes-a-user-story`, `no-criteria-reproduced`, `every-entry-quotes-a-story` and `no-code-written`, each with the type and fields the table gives. Ephemeral check: run the scaffold by hand in an empty directory as `evals/README.md` shows and confirm `calc/ops.py` and `tests/test_ops.py` exist on `main`; `make validate` passes, which runs `checks/test_eval_cases.py`
- _Requirements: 7.1, 7.2, 7.3_

- [x] 4. Run the start-task evals
- The author runs `make eval-skill-start-task EVAL_ARGS="--runs 1 --case summarises-requirements"` to iterate the new case, fixing a grader or the skill text as the design's error-handling rows say, then `make eval-skill-start-task` at the default three runs, and pastes the table into the pull request's Testing section with every existing case still passing
- **Property 1: A document is never printed for approval**
- **Validates: Requirements 7.4, 1.1, 1.2, 1.4, 2.2**

- [x] 5. Move the spec folder in the plugin text
- In `plugins/freethinking/skills/start-task/SKILL.md`, `plugins/freethinking/skills/implement-spec/SKILL.md`, `plugins/freethinking/agents/task-executor.md`, `plugins/freethinking/rules/workflow.md` and `plugins/freethinking/README.md`, replace `.claude/specs` with `.freethinking/specs`; add the "Tune the plugin" sentence the design's move table gives; replace the path in the root `README.md`. Ephemeral check: `grep -r '\.claude/specs' plugins/ README.md` finds nothing; `make validate` passes
- _Requirements: 8.1, 8.2_

- [x] 6. Move the spec folder in the evals
- `git mv` the four `files/.claude/specs` fixture folders to `files/.freethinking/specs`; replace `.claude/specs` with `.freethinking/specs` in every prompt, grader, scaffold and case README under `evals/`; rewrite the sandbox note in `evals/README.md` as the design's move table gives it. Ephemeral check: `grep -r '\.claude/specs' evals` finds nothing; the `works-one-wave` and `closed-spec-is-a-record` scaffolds run by hand in an empty directory plant the spec at the new path; `make validate` passes
- _Requirements: 8.3_

- [x] 7. Move the records
- `git mv .claude/specs .freethinking/specs`, the untracked `spec-approval-summary` folder moving with the directory; `git status` shows renames and the untracked folder at the new path only, and `.claude/settings.json` stays
- _Requirements: 8.4_

## Notes

- Every task runs `make validate` before it is done; an ephemeral check is created in a scratch location and deleted afterwards.
- Tasks 1 and 5 are the only edits to the skill; the executor quotes the design's text as given and changes no other sentence, so the four existing start-task cases stay the regression check.
- Task 4 is the author's, since the eval runs cost tokens; it gets no sub-agent.
- The `report` skill's templates, the `pr` skill and `bugfix` are not touched, beyond the path replacement of task 5 where one of them names the spec folder.
- After task 7 this spec lives at `.freethinking/specs/spec-approval-summary/`; ticks after that go there.

## Task Dependency Graph

```json
{
"waves": [
{ "id": 0, "tasks": ["1"] },
{ "id": 1, "tasks": ["2", "3"] },
{ "id": 2, "tasks": ["5", "6", "7"] },
{ "id": 3, "tasks": ["4"] }
]
}
```
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ its free checks and its spec records. To install and use the plugin, read
plugin directory scans every file in that folder when the plugin is
submitted.
- `checks/`: the free unit tests.
- `.claude/specs/`: the design records of past tasks.
- `.freethinking/specs/`: the design records of past tasks.
- `.claude-plugin/marketplace.json`: the marketplace entry that points at the
plugin folder.

Expand Down
9 changes: 5 additions & 4 deletions evals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,11 @@ the worked example.
files and git state only; nothing it writes is loaded as configuration.
- The harness puts the workspace's git status into the session context at
start, so a skill can know the branch and dirty state without running git.
- Edits to files under `.claude/` in the workspace are refused even when Edit
is granted, and so is a shell fallback. A skill that writes there (ticking a
spec's task list) cannot be graded on that write; grade the rest and expect
the skill to report the refusal.
- Writes and edits under `.claude/` in the workspace are refused even when
Write or Edit is granted, and so is a shell fallback; a path-scoped grant such
as `Write(.claude/**)` does not lift it, and a committed `CLAUDE.md` is not
loaded. Specs live under `.freethinking/specs/`, which the sandbox lets a
skill write, so a spec being written or ticked can be graded there.
- A prompt that starts with `/freethinking:<skill>` is expanded before the model
runs, so a `tool_used` grader on `Skill` never fires for it; grade the
behaviour instead. A Skill call the model makes later, to another skill, is
Expand Down
4 changes: 2 additions & 2 deletions evals/rules/workflow/closed-spec-is-a-record/prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ description: A request on an area whose only spec is closed takes the route the
tags: [rule, workflow]
max_turns: 10
allowed_tools: [Read, Glob, Grep, Skill]
expected_outcome: Claude reads .claude/specs/calc-subtract/ as a record of merged work, since every task is ticked, subtract is already in calc/ops.py and the prompt says its branch merged, and does not invoke /freethinking:implement-spec. The request is a new change, so /freethinking:start-task is invoked, proposes a route for divide and asks the author which to take. Nothing is written.
expected_outcome: Claude reads .freethinking/specs/calc-subtract/ as a record of merged work, since every task is ticked, subtract is already in calc/ops.py and the prompt says its branch merged, and does not invoke /freethinking:implement-spec. The request is a new change, so /freethinking:start-task is invoked, proposes a route for divide and asks the author which to take. Nothing is written.
---
Add divide(a, b) to calc/ops.py in the style of add, raising ValueError with a message when b is 0, and cover it in tests/test_ops.py. An earlier task left a spec in .claude/specs/calc-subtract/; its branch merged.
Add divide(a, b) to calc/ops.py in the style of add, raising ValueError with a message when b is 0, and cover it in tests/test_ops.py. An earlier task left a spec in .freethinking/specs/calc-subtract/; its branch merged.
Loading
Loading