Spec driven development setup
This commit is contained in:
12
AGENTS.md
Normal file
12
AGENTS.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Project skills and specifications
|
||||
|
||||
- Project skills are stored in `skills/`; specifications belong in `specs/`.
|
||||
- Use `grill-me` only when the user explicitly requests it, for example
|
||||
`Use grill-me to review this plan` or `Gebruik grill-me voor dit ontwerp`.
|
||||
- Before using it, read `skills/grill-me/SKILL.md` and its dependency
|
||||
`skills/grilling/SKILL.md`. If no dedicated Skill tool is available, load these
|
||||
files directly and follow their instructions within the available tools.
|
||||
- Installing or mentioning a skill does not start an interview. Do not apply
|
||||
`grilling` automatically to ordinary development requests.
|
||||
- Keep the upstream skill files unchanged. Source revision and license are
|
||||
recorded in `skills/upstream.json` and `skills/LICENSE.mattpocock`.
|
||||
21
skills/LICENSE.mattpocock
Normal file
21
skills/LICENSE.mattpocock
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Matt Pocock
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
22
skills/README.md
Normal file
22
skills/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Project skills
|
||||
|
||||
Reusable agent instructions for this repository. Invoke them explicitly in the
|
||||
conversation, for example:
|
||||
|
||||
> Gebruik grill-me om de JSON-import en -export met mij uit te werken.
|
||||
|
||||
## Installed skills
|
||||
|
||||
| Skill | Purpose |
|
||||
| --- | --- |
|
||||
| [grill-me](grill-me/SKILL.md) | Entry point for reviewing a plan or design through questions. |
|
||||
| [grilling](grilling/SKILL.md) | Interview instructions required by `grill-me`. |
|
||||
|
||||
The skills are copied from [Matt Pocock's skills.sh listing](https://skills.sh/mattpocock/skills/grill-me)
|
||||
and its [upstream repository](https://github.com/mattpocock/skills).
|
||||
The exact upstream commit and paths are recorded in [upstream.json](upstream.json).
|
||||
The upstream [MIT license](LICENSE.mattpocock) is included.
|
||||
|
||||
These project-local files are available to the agent from the next conversation
|
||||
turn through the instructions in the root `AGENTS.md`. They are not installed
|
||||
globally. Updating them requires explicitly downloading a new upstream revision.
|
||||
7
skills/grill-me/SKILL.md
Normal file
7
skills/grill-me/SKILL.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: grill-me
|
||||
description: A relentless interview to sharpen a plan or design.
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
Call the Skill tool with "grilling".
|
||||
5
skills/grill-me/agents/openai.yaml
Normal file
5
skills/grill-me/agents/openai.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
interface:
|
||||
display_name: "Grill Me"
|
||||
short_description: "Sharpen a plan through interview"
|
||||
policy:
|
||||
allow_implicit_invocation: false
|
||||
30
skills/grilling/SKILL.md
Normal file
30
skills/grilling/SKILL.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: grilling
|
||||
description: Grill the user relentlessly about a plan, decision, or idea. Use when the user wants to stress-test their thinking, or uses any 'grill' trigger phrases.
|
||||
---
|
||||
|
||||
Interview the user relentlessly until you reach a shared understanding. Map this as a **design tree**: every decision branches into the decisions that hang off it.
|
||||
|
||||
Work the tree in **rounds**. The **frontier** is every decision whose prerequisites are already settled: the questions you can ask _now_ without guessing at answers you haven't heard yet. Ask the whole frontier in one round: number each question and give your recommended answer. Then wait for the user's answers before the next round.
|
||||
|
||||
Format a round like so:
|
||||
|
||||
```
|
||||
❓ **Q1** - **<question title>**: <question body, might be multiple paragraphs, including multiple choices>
|
||||
|
||||
➡️ <your recommended answer>
|
||||
|
||||
---
|
||||
|
||||
❓ **Q2** - **<question title>**: <question body, might be multiple paragraphs, including multiple choices>
|
||||
|
||||
➡️ <your recommended answer>
|
||||
```
|
||||
|
||||
Word each question so "yes" accepts your recommended answer.
|
||||
|
||||
Each round the user answers reshapes the tree: settled decisions push the frontier outward and unblock questions that depended on them. Recompute the frontier and ask the next round. A question whose answer depends on another question still open in this round belongs to a _later_ round, not this one.
|
||||
|
||||
Finding _facts_ is your job, never the user's. When a frontier question needs a fact from the environment (filesystem, tools, etc.), dispatch a sub-agent to find it; don't ask the user for anything you could look up yourself. Don't block on it: a running exploration is an unsettled prerequisite, so only the questions downstream of it wait for the sub-agent to report; ask the rest of the frontier now. The _decisions_ are the user's: put each to them and wait.
|
||||
|
||||
The session is done when the frontier is empty: every branch of the design tree visited, nothing left silently assumed. Do not act on it until the user confirms you have reached a shared understanding.
|
||||
3
skills/grilling/agents/openai.yaml
Normal file
3
skills/grilling/agents/openai.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
interface:
|
||||
display_name: "Grilling"
|
||||
short_description: "Stress-test thinking a round of questions at a time"
|
||||
9
skills/upstream.json
Normal file
9
skills/upstream.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"repository": "https://github.com/mattpocock/skills",
|
||||
"commit": "59db609eb1e18aaf59b63284d0e52255aff0c63c",
|
||||
"source": "https://skills.sh/mattpocock/skills/grill-me",
|
||||
"skills": {
|
||||
"grill-me": "skills/productivity/grill-me",
|
||||
"grilling": "skills/productivity/grilling"
|
||||
}
|
||||
}
|
||||
4
specs/README.md
Normal file
4
specs/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Specifications
|
||||
|
||||
Store feature specifications, requirements and agreed design decisions here.
|
||||
Use descriptive Markdown filenames, for example `school-json-import-export.md`.
|
||||
160
specs/S1_School-JSON-import-export.md
Normal file
160
specs/S1_School-JSON-import-export.md
Normal file
@@ -0,0 +1,160 @@
|
||||
# S1 — School JSON import and export
|
||||
|
||||
Status: agreed after the grill-me review.
|
||||
|
||||
## User story
|
||||
|
||||
**As** a school maintainer,
|
||||
**I want** to export and import my dance school as a JSON file,
|
||||
**so that** I can store my school configuration locally while the application does
|
||||
not offer persistent storage,
|
||||
**and so that** I retain ownership of my data.
|
||||
|
||||
## Intent
|
||||
|
||||
Export downloads a complete snapshot of one dance school to a local JSON file.
|
||||
Import restores that snapshot as a new school or replaces the corresponding
|
||||
existing school after explicit confirmation.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
|
||||
- Exporting an existing school to a readable JSON file.
|
||||
- Importing a school that does not exist or no longer exists.
|
||||
- Replacing an existing school with the complete imported snapshot.
|
||||
- Preserving all configured school data and relationships, including:
|
||||
- School details and its persistent unique key.
|
||||
- Dancers and their details.
|
||||
- Dance groups, types, age ranges and styles.
|
||||
- Dancer memberships, including dancers belonging to multiple groups.
|
||||
- Shows, dates, day parts and any existing group assignments to day parts.
|
||||
- Coaches and any existing links between coaches and groups.
|
||||
- Full validation, an import preview, confirmation and clear error messages.
|
||||
|
||||
Preserving existing data does not add management screens for coaches or the
|
||||
ability to assign groups to show day parts.
|
||||
|
||||
### Out of scope
|
||||
|
||||
- Merging an imported snapshot with an existing school.
|
||||
- Persistent server-side storage.
|
||||
|
||||
The existing-school prompt includes a merge option, but selecting it only displays
|
||||
that merging is not yet supported. It must not change any data. Implementing merge
|
||||
behavior requires a separate specification.
|
||||
|
||||
## Identity and file format
|
||||
|
||||
- Every school has a persistent unique key that is included in exports and
|
||||
preserved through imports and subsequent exports.
|
||||
- Import identifies an existing school by that key, not by its name or a
|
||||
runtime-generated numeric ID. The key remains meaningful after a server restart.
|
||||
- A school with the same name but a different unique key is a separate school.
|
||||
- A file contains one school and all data needed to restore it without accessing
|
||||
another school or the original server state.
|
||||
- The readable, documented JSON format includes a `formatVersion` field.
|
||||
- Users may edit the JSON manually. Edited files undergo the same validation as
|
||||
files produced by the application.
|
||||
- Unknown fields and unsupported format versions are rejected explicitly; data
|
||||
must not be silently ignored.
|
||||
- Relationships in the file must be unambiguous and restored correctly. Internal
|
||||
numeric IDs need not remain identical, provided school identity and all
|
||||
relationships are preserved without collisions with other schools.
|
||||
|
||||
## Export flow
|
||||
|
||||
1. The maintainer opens an existing school's management screen.
|
||||
2. The maintainer selects the JSON export option.
|
||||
3. The application downloads a JSON file containing a consistent, complete
|
||||
snapshot of that school.
|
||||
4. Export does not change the school or any other application data.
|
||||
|
||||
## Import flow
|
||||
|
||||
1. The maintainer selects the JSON import option and chooses a local file.
|
||||
2. The application validates the entire file before changing any stored data.
|
||||
3. For a valid file, the application shows a preview containing the school name
|
||||
and the numbers of dancers, dance groups and shows.
|
||||
4. If the unique school key is unknown, the maintainer confirms adding the school
|
||||
or cancels the import.
|
||||
5. If the key already exists, the application identifies the school that would be
|
||||
replaced and offers replace, merge or cancel:
|
||||
- **Replace:** explicitly warn that the existing school is replaced completely.
|
||||
After confirmation, replace all its configured data with the snapshot.
|
||||
- **Merge:** show a message that this functionality is not yet supported and
|
||||
leave all data unchanged.
|
||||
- **Cancel:** leave all data unchanged.
|
||||
6. A confirmed import is committed as one operation. The application must not
|
||||
expose a partially imported or partially replaced school.
|
||||
7. If validation or importing fails, show **"Import niet gelukt"** together with
|
||||
the concrete cause. The user can correct the file and try again.
|
||||
|
||||
## Validation and failure behavior
|
||||
|
||||
- Validate JSON syntax, the supported file structure and format version, required
|
||||
data, field values and all relationships before applying the import.
|
||||
- Reject unknown fields and references to missing objects, including a group's
|
||||
reference to a dancer absent from the snapshot.
|
||||
- A failure must not create a partial school, partially replace an existing
|
||||
school, or modify another school.
|
||||
- A replacement must not remove the original school until the complete
|
||||
replacement can succeed. If it fails, the original school remains intact.
|
||||
- Error messages explain the cause specifically enough to correct the file.
|
||||
For example: **"Import niet gelukt: groep Hiphop verwijst naar een onbekende
|
||||
danser."**
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
### Export
|
||||
|
||||
1. Each existing school offers a JSON-file export that can be downloaded and
|
||||
stored locally.
|
||||
2. The export includes its persistent unique key, `formatVersion`, all configured
|
||||
data listed in scope and all relationships between those objects.
|
||||
3. Exporting leaves the application data unchanged.
|
||||
4. A school with no dancers, groups or shows can be exported and imported.
|
||||
|
||||
### Adding a school
|
||||
|
||||
5. A valid file with an unknown school key shows the preview before any data is
|
||||
added. Confirming creates the complete school; cancelling changes nothing.
|
||||
6. An exported school can be restored after the original school is deleted or
|
||||
the in-memory server state is lost.
|
||||
7. An existing school with the same name but a different key is neither replaced
|
||||
nor treated as the same school.
|
||||
|
||||
### Replacing a school
|
||||
|
||||
8. A valid file with an existing school key prompts the user to replace, merge or
|
||||
cancel and clearly identifies the existing school.
|
||||
9. Confirming replacement replaces the complete configuration. Objects and
|
||||
relationships present only in the previous configuration are not retained as
|
||||
part of the replaced school.
|
||||
10. Other schools remain unchanged by replacement.
|
||||
11. Selecting merge displays that merging is not yet supported and changes
|
||||
nothing. Cancelling also changes nothing.
|
||||
|
||||
### Validation and errors
|
||||
|
||||
12. Malformed JSON, unsupported format versions, unknown fields, missing required
|
||||
data, invalid field values and unresolved relationships cause the entire
|
||||
import to fail.
|
||||
13. Each failed import displays **"Import niet gelukt"** and a concrete cause.
|
||||
14. A failed new-school import adds nothing. A failed replacement preserves the
|
||||
entire existing school. Other schools are unaffected in either case.
|
||||
15. After a failure, the user can select a corrected file and retry.
|
||||
|
||||
### Round-trip integrity
|
||||
|
||||
16. Exporting and importing a school preserves every configured field and
|
||||
relationship, including a dancer's membership in multiple groups, shows and
|
||||
their day parts, and any existing coaches or day-part group assignments.
|
||||
17. Exporting the restored school again preserves its unique school key and
|
||||
equivalent configuration, even if internal numeric IDs changed.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
This specification records agreed behavior. Backend endpoints, the detailed JSON
|
||||
schema and frontend implementation remain implementation work; this review does
|
||||
not implement the feature.
|
||||
Reference in New Issue
Block a user