plain-forge 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +247 -0
  3. package/bin/cli.mjs +143 -0
  4. package/forge/docs/.gitkeep +0 -0
  5. package/forge/rules/definitions.md +57 -0
  6. package/forge/rules/exported-concepts.md +39 -0
  7. package/forge/rules/func-specs.md +72 -0
  8. package/forge/rules/impl-reqs.md +50 -0
  9. package/forge/rules/import-modules.md +51 -0
  10. package/forge/rules/required-concepts.md +45 -0
  11. package/forge/rules/requires-modules.md +59 -0
  12. package/forge/rules/test-reqs.md +47 -0
  13. package/forge/skills/add-acceptance-test/SKILL.md +98 -0
  14. package/forge/skills/add-concept/SKILL.md +67 -0
  15. package/forge/skills/add-feature/SKILL.md +136 -0
  16. package/forge/skills/add-functional-spec/SKILL.md +81 -0
  17. package/forge/skills/add-functional-specs/SKILL.md +115 -0
  18. package/forge/skills/add-implementation-requirement/SKILL.md +73 -0
  19. package/forge/skills/add-resource/SKILL.md +108 -0
  20. package/forge/skills/add-template/SKILL.md +65 -0
  21. package/forge/skills/add-test-requirement/SKILL.md +68 -0
  22. package/forge/skills/analyze-2-func-specs/SKILL.md +102 -0
  23. package/forge/skills/analyze-func-specs/SKILL.md +124 -0
  24. package/forge/skills/analyze-if-func-spec-too-complex/SKILL.md +152 -0
  25. package/forge/skills/break-down-func-spec/SKILL.md +156 -0
  26. package/forge/skills/check-plain-env/SKILL.md +288 -0
  27. package/forge/skills/consolidate-concepts/SKILL.md +193 -0
  28. package/forge/skills/create-import-module/SKILL.md +98 -0
  29. package/forge/skills/create-requires-module/SKILL.md +104 -0
  30. package/forge/skills/debug-specs/SKILL.md +189 -0
  31. package/forge/skills/forge-integration/SKILL.md +443 -0
  32. package/forge/skills/forge-plain/SKILL.md +333 -0
  33. package/forge/skills/implement-conformance-testing-script/SKILL.md +247 -0
  34. package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_cypress.ps1 +324 -0
  35. package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_golang.ps1 +100 -0
  36. package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +102 -0
  37. package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.ps1 +92 -0
  38. package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +100 -0
  39. package/forge/skills/implement-prepare-environment-script/SKILL.md +242 -0
  40. package/forge/skills/implement-prepare-environment-script/assets/prepare_environment_java.sh +42 -0
  41. package/forge/skills/implement-prepare-environment-script/assets/prepare_environment_python.sh +81 -0
  42. package/forge/skills/implement-unit-testing-script/SKILL.md +133 -0
  43. package/forge/skills/implement-unit-testing-script/assets/run_unittests_flutter.ps1 +82 -0
  44. package/forge/skills/implement-unit-testing-script/assets/run_unittests_golang.ps1 +68 -0
  45. package/forge/skills/implement-unit-testing-script/assets/run_unittests_java.sh +45 -0
  46. package/forge/skills/implement-unit-testing-script/assets/run_unittests_python.ps1 +76 -0
  47. package/forge/skills/implement-unit-testing-script/assets/run_unittests_python.sh +90 -0
  48. package/forge/skills/implement-unit-testing-script/assets/run_unittests_react.ps1 +83 -0
  49. package/forge/skills/init-config-file/SKILL.md +261 -0
  50. package/forge/skills/init-plain-project/SKILL.md +124 -0
  51. package/forge/skills/load-plain-reference/SKILL.md +646 -0
  52. package/forge/skills/plain-healthcheck/SKILL.md +132 -0
  53. package/forge/skills/refactor-module/SKILL.md +197 -0
  54. package/forge/skills/resolve-spec-conflict/SKILL.md +88 -0
  55. package/forge/skills/run-codeplain/SKILL.md +540 -0
  56. package/package.json +42 -0
@@ -0,0 +1,115 @@
1
+ ---
2
+ name: add-functional-specs
3
+ description: >-
4
+ Add multiple functional specs to the ***functional specs*** section of a
5
+ ***plain spec file in a single batch. Use whenever more than one new
6
+ functional spec is being added — whether the user explicitly asks, or
7
+ another skill/workflow (e.g. forge-plain, add-feature) needs to author
8
+ several specs in one pass. Bulk-writing or hand-authoring functional
9
+ specs without invoking this skill is forbidden; for adding a single spec,
10
+ use add-functional-spec instead.
11
+ ---
12
+
13
+ # Add Functional Specs
14
+
15
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
16
+
17
+ ## When to Use
18
+
19
+ - The user asks for several functional specs to be added in one go (e.g. "add these three specs", "spec out this feature in a few bullets").
20
+ - A higher-level skill or workflow (`forge-plain`, `add-feature`, `debug-specs`) needs to author a tight group of related specs.
21
+ - Anywhere you would otherwise be tempted to write more than one functional spec without running per-spec analysis.
22
+
23
+ If you only need to add a single spec, use the `add-functional-spec` skill instead. Either way, **never** edit the `***functional specs***` section by hand — every new entry must go through one of these two skills so the complexity and conflict checks actually run.
24
+
25
+ ## Workflow
26
+
27
+ This skill is `add-functional-spec` applied **one spec at a time, in order**, with no shortcuts. The batch never escapes per-spec rigor.
28
+
29
+ 1. **Identify the target `.plain` file.** If ambiguous, ask the user.
30
+ 2. **Read the entire file** to understand existing definitions, implementation reqs, and all current functional specs (including those reachable via `import` / `requires`).
31
+ 3. **Draft all the specs you intend to add**, in the chronological order they should appear. Keep the drafts in a working list — nothing is inserted yet.
32
+ 4. **For each drafted spec, in order:**
33
+ 1. **Analyze complexity.** Run `analyze-if-func-spec-too-complex` on the spec. If the verdict is `TOO COMPLEX`, run `break-down-func-spec`, replace the entry in the working list with the resulting smaller specs (preserving order), and restart this step on the first of the replacements.
34
+ 2. **Check for conflicts.** Run `analyze-func-specs` **once** with this single input set:
35
+ - the new spec, plus
36
+ - every existing functional spec in the file and its `requires` chain, plus
37
+ - every spec from this batch that has already been inserted.
38
+
39
+ The batched analyzer returns every conflicting pair in one call — do **not** loop over pairs invoking a per-pair analyzer. For each conflicting pair it reports, run `resolve-spec-conflict`. Apply the resolution — which may revise the new spec, an existing spec, or both — then re-run `analyze-func-specs` once over the touched set until the verdict is `COMPATIBLE`.
40
+ 3. **Append the spec** to the `***functional specs***` section. Specs are chronological; the new entry goes at the end (unless an earlier existing spec must come *after* it — in that rare case, insert at the correct position).
41
+ 5. **Read the file again** to confirm correct placement, ordering, and syntax for the full batch.
42
+
43
+ Order matters: each new spec is inserted only after its complexity and conflict checks pass, so subsequent specs in the batch are always checked against an already-validated file.
44
+
45
+ ## Rules
46
+
47
+ All the rules from `add-functional-spec` apply per individual spec. They are restated here so this skill is self-contained.
48
+
49
+ ### Complexity Limit (per spec)
50
+
51
+ Each functional spec must imply a **maximum of 200 changed lines of code**. If a spec is too large, use `break-down-func-spec` to split it into multiple smaller, independent specs. Do not include LOC estimates in the spec text.
52
+
53
+ ### Chronological Ordering
54
+
55
+ Specs are rendered incrementally, top to bottom. The renderer has **no knowledge of future specs** — only previously rendered specs are in context.
56
+ - A new spec can reference behavior defined by earlier specs.
57
+ - A new spec **cannot** assume anything about specs that come after it.
58
+ - Order the batch so that each spec only depends on specs that precede it. If two new specs would otherwise reference each other, the dependent one comes second.
59
+
60
+ ### Language Agnosticism
61
+
62
+ Write in terms of behavior, concepts, and domain logic — not implementation constructs. Avoid language-specific types, generics syntax, framework annotations, or other constructs tied to a particular language or framework. General technical terms (null values, JSON types, HTTP status codes) are fine. Language-specific guidance belongs in `***implementation reqs***`.
63
+
64
+ ### No Conflicts (full coverage via one batched call per spec)
65
+
66
+ The new specs must not contradict each other **and** must not contradict any existing functional spec. Conflicting specs are the most costly outcome. The conflict check must cover:
67
+ - every (new × existing) pair, and
68
+ - every (new × new) pair within the batch.
69
+
70
+ That coverage is achieved by running `analyze-func-specs` **once per spec being inserted**, with the new spec plus every existing spec plus every already-inserted spec from this batch passed in as a single set. The batched analyzer lists every conflicting pair in one call — do not invoke a pair-by-pair analyzer. If ambiguity exists, add explicit detail to eliminate any conflicting interpretation. For each conflicting pair the batched analyzer reports, use the `resolve-spec-conflict` skill to diagnose and fix it before proceeding.
71
+
72
+ ### Disambiguation (per spec)
73
+
74
+ Each functional spec must be unambiguous — the renderer should have only one reasonable interpretation. If a single line is not enough to fully disambiguate the behavior, use **nested sub-bullets** to add detail. Nested lines clarify the parent spec; they do not introduce separate functionality. Even with nested detail, the spec must still imply ≤ 200 LOC.
75
+
76
+ ```plain
77
+ - :User: should be able to send a :Message: to a :Conversation:.
78
+ - A :Message: must have non-empty content.
79
+ - The :Message: is appended to the end of the :Conversation:.
80
+ - All :Participant: members of the :Conversation: can see the new :Message:.
81
+ ```
82
+
83
+ ### Deterministic Interface
84
+
85
+ Specs must be detailed enough that a developer can use the built software without reading the generated code. All external interfaces must be explicit — REST endpoint paths and HTTP methods, CLI command names and arguments, file formats, message schemas, etc. Never leave interface details up to the renderer's discretion.
86
+
87
+ ### Encapsulation
88
+
89
+ Functionality must be self-contained in the spec text. `requires` modules only import functional specs, so do not rely on implementation reqs to convey behavior — they won't be visible in downstream modules.
90
+
91
+ ## Acceptance Tests
92
+
93
+ If any of the newly added functional specs need verification, use the `add-acceptance-test` skill to add acceptance tests after the batch has been inserted. Do this per spec, not as part of the bulk pass.
94
+
95
+ ## Anti-Patterns
96
+
97
+ - **Don't skip per-spec checks because the batch "feels" small.** Even two specs require two complexity checks and a batched conflict check that includes both new specs.
98
+ - **Don't fall back to pair-by-pair conflict analysis.** Use `analyze-func-specs` with the full relevant set once per inserted spec — not `analyze-2-func-specs` across every pair.
99
+ - **Don't run all complexity checks first and all conflict checks last.** Interleave them per spec, as described in the Workflow — a failed complexity check earlier would otherwise waste later conflict checks.
100
+ - **Don't insert every spec first and then analyze.** A bad spec already in the file pollutes subsequent conflict analyses.
101
+ - **Don't fall back to hand-authoring** because there are "a lot" of specs to add. The right answer is more analyzer calls, not fewer.
102
+ - **Don't use this skill for a single spec.** Use `add-functional-spec` — it's the same checks without the bulk bookkeeping.
103
+
104
+ ## Validation Checklist
105
+
106
+ - [ ] Every spec in the batch implies ≤ 200 lines of code changes (verified via `analyze-if-func-spec-too-complex`)
107
+ - [ ] No conflict between any new spec and any existing spec (verified via batched `analyze-func-specs` calls)
108
+ - [ ] No conflict between any two new specs in the batch (covered by the same batched `analyze-func-specs` calls)
109
+ - [ ] Every conflicting pair the batched analyzer reported was resolved via `resolve-spec-conflict` before the batch completed
110
+ - [ ] All specs written in language-agnostic terms (no language/framework specifics)
111
+ - [ ] All external interfaces explicit (endpoint paths, methods, CLI args, formats, etc.)
112
+ - [ ] All referenced `:Concepts:` are defined in `***definitions***`
113
+ - [ ] Sentences are short, clear, and unambiguous
114
+ - [ ] No redundancy with existing specs or within the batch
115
+ - [ ] Specs placed in correct chronological positions
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: add-implementation-requirement
3
+ description: >-
4
+ Add an implementation requirement to the ***implementation reqs*** section of
5
+ a ***plain spec file. Use when the user wants to add non-functional
6
+ requirements like technology choices, architectural constraints, coding
7
+ standards, data formats, error handling strategies, or any HOW-to-build
8
+ guidance to a .plain file.
9
+ ---
10
+
11
+ # Add Implementation Requirement
12
+
13
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
14
+
15
+ ## Workflow
16
+
17
+ 1. **Identify the target `.plain` file.** If ambiguous, ask the user.
18
+ 2. **Read the file** to understand existing implementation reqs, definitions, and functional specs.
19
+ 3. **Determine if this belongs in implementation reqs** — it must describe HOW to build, not WHAT to build (that goes in `***functional specs***`).
20
+ 4. **Draft the requirement** following the rules below.
21
+ 5. **Insert it** into the `***implementation reqs***` section.
22
+ 6. **Read the file again** to confirm correct placement and syntax.
23
+
24
+ ## What Belongs Here
25
+
26
+ Implementation reqs are free-form instructions that steer code generation. Common contents:
27
+
28
+ - **Technology choices**: language, framework, runtime version
29
+ - **Architectural constraints**: patterns, layering, dependency rules
30
+ - **Coding standards**: naming conventions, style guidelines
31
+ - **Data formats**: serialization, encoding, transformation rules
32
+ - **Error handling**: strategies, retry logic, exception hierarchies
33
+ - **Algorithm descriptions**: specific approaches when behavior alone is insufficient
34
+ - **Performance guidance**: memory constraints, streaming requirements, batching strategies
35
+ - **Language-specific constructs**: generics, annotations, framework-specific types and idioms
36
+
37
+ ## What Does NOT Belong Here
38
+
39
+ - **Behavior and features** — those go in `***functional specs***`
40
+ - **Concept definitions** — those go in `***definitions***`
41
+ - **Test instructions** — those go in `***test reqs***`
42
+
43
+ ## Key Principle: HOW vs WHAT
44
+
45
+ `***implementation reqs***` describe HOW the software should be built.
46
+ `***functional specs***` describe WHAT the software should do.
47
+
48
+ If the requirement describes observable behavior (endpoints, business rules, user-facing features), it belongs in functional specs. If it describes internal structure, technology, or coding guidance, it belongs here.
49
+
50
+ ## Format
51
+
52
+ Implementation reqs are bullet points in the `***implementation reqs***` section:
53
+
54
+ ```plain
55
+ ***implementation reqs***
56
+ - :Implementation: should be in Python 3.12.
57
+ - :Implementation: should use pip for dependency management.
58
+ - When writing CSV files, :Implementation: should use streaming writes to avoid holding large datasets in memory.
59
+ ```
60
+
61
+ Reference defined `:Concepts:` where they add clarity. Implementation reqs in non-leaf sections apply to all subsections.
62
+
63
+ ## Encapsulation Warning
64
+
65
+ `requires` modules only receive functional specs from their dependencies — not implementation reqs. If downstream modules need certain behavior to be visible, that behavior must be expressed in functional specs, not here.
66
+
67
+ ## Validation Checklist
68
+
69
+ - [ ] Describes HOW to build, not WHAT to build
70
+ - [ ] All referenced `:Concepts:` are defined in `***definitions***`
71
+ - [ ] Does not duplicate guidance already present in the file or its imports
72
+ - [ ] Placed inside a `***implementation reqs***` section
73
+ - [ ] No behavioral requirements that should be in `***functional specs***`
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: add-resource
3
+ description: >-
4
+ Add a linked resource (external file reference) to a ***plain spec. Use when
5
+ the user wants to reference a JSON schema, API spec, data file, or other
6
+ external file from within a functional spec, definition, or implementation
7
+ requirement.
8
+ ---
9
+
10
+ # Add Resource
11
+
12
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
13
+
14
+ Linked resources are external files referenced from within a `.plain` spec using markdown link syntax. The file contents are passed to the renderer alongside the spec, providing additional context for code generation.
15
+
16
+ ## Workflow
17
+
18
+ 1. **Identify or create the resource file.** It should be in the `resources/` directory or in the same folder (or a subfolder) as the `.plain` file.
19
+ 2. **Add the markdown link** at the appropriate place in the spec.
20
+ 3. **Verify the file path** is relative to the `.plain` file location.
21
+ 4. **Read the file back** to confirm correct link syntax and path.
22
+
23
+ ## Format
24
+
25
+ Use standard markdown link syntax inside any spec section:
26
+
27
+ ```plain
28
+ ***definitions***
29
+ - :AuthData: is the authentication data structure. Its format is defined
30
+ in the [auth schema](resources/auth_schema.json).
31
+
32
+ ***implementation reqs***
33
+ - When transforming :BackupData:, use the JOLT transform defined in
34
+ [backup_transform.jolt](resources/backup_transform.jolt).
35
+
36
+ ***functional specs***
37
+
38
+ - The system should expose an API conforming to the
39
+ [API specification](resources/api_spec.yaml).
40
+ ```
41
+
42
+ ## Path Rules
43
+
44
+ - Paths are resolved **relative to the `.plain` file location**.
45
+ - Only files in the same folder or subfolders are supported.
46
+ - No absolute paths.
47
+ - **No external URLs** — only local file references.
48
+ - **No folder paths** — only local file references.
49
+ - Only text-based files are supported.
50
+
51
+ ### A linked resource MUST be a single, text-based file that exists on disk
52
+
53
+ A linked resource is **always** a single file that exists on disk at the path you reference, **and** that file's content must be text-based. The renderer reads the linked file's bytes and feeds them into the model alongside the spec; a directory, a remote URL, or a binary blob breaks that contract and is one of the most disruptive mistakes you can make when authoring a `.plain` file — the spec looks valid but the renderer either silently ignores the link, fails to read it, or wastes the model's context window on bytes it cannot interpret.
54
+
55
+ Three things a linked resource **must not** be:
56
+
57
+ 1. **A folder / directory.** `[integrations](src/integrations/)`, `[schemas](resources/schemas/)`, `[host project](../host_project/)` are all invalid — the renderer cannot ingest a directory. If a whole directory's worth of content is relevant, pick the single most representative **file** inside it (a `README.md`, an exemplar source file, a manifest at the directory root) and link **that**.
58
+ 2. **A URL / external location.** `[Stripe docs](https://stripe.com/docs/api)`, `[OpenAPI spec](https://example.com/openapi.json)`, any `http://` / `https://` / `ftp://` / `git://` / `s3://` / `gs://` target. Linked resources are local-file only. If a URL's content is essential to the spec, fetch it once, save the response to a text file under `resources/` (e.g. `resources/stripe-docs-snapshot.md`, `resources/example-openapi.yaml`), and link **that file**.
59
+ 3. **A binary file.** PNG, JPG, JPEG, GIF, BMP, TIFF, WebP, ICO, PDF, DOCX, XLSX, PPTX, ZIP, TAR, GZ, MP3, MP4, WAV, compiled binaries (`.exe`, `.so`, `.dylib`, `.class`, `.wasm`), and anything else that isn't human-readable text in its raw form. Binary content cannot be meaningfully consumed by the renderer; linking a screenshot, a PDF spec, or a packaged artifact accomplishes nothing except bloating the context. If the information in a binary asset is essential, transcribe it into a text-based form first — a UI screenshot becomes a Markdown description or a structured YAML wireframe under `resources/`; a PDF spec becomes a Markdown extract or the underlying JSON Schema / OpenAPI; an architecture diagram becomes a Mermaid block inside a Markdown file.
60
+
61
+ If the markdown-link target ends with `/`, contains `://`, points at a path that resolves to a directory, or points at a file with a binary extension (see the list above), **stop** — it cannot be a linked resource. Convert it to a text file under `resources/` first, then link the converted file.
62
+
63
+ ### Do not mention URLs or folder paths in `.plain` content at all
64
+
65
+ The constraint above is **not** just about markdown link syntax. URLs (any `http://`, `https://`, `ftp://`, `git://`, `s3://`, … string) and folder paths (`src/integrations/`, `../host_project/`, anything ending with `/`, anything that resolves to a directory) **must not appear anywhere in `.plain` content** — not as link targets, not in concept body prose, not in functional-spec text, not in implementation-reqs. Mentioning a URL or a folder in prose is a critical and common mistake because:
66
+
67
+ - The renderer cannot follow URLs or open folders. A URL or folder reference in prose is a *ghost* dependency: it looks meaningful to a human reader, but it contributes nothing to code generation. Worse, downstream readers (and future you) assume the renderer used the referenced content, so the spec drifts from reality.
68
+ - The fix is always the same: if external content matters, fetch it (or pick one canonical file out of the directory), save it as a text file under `resources/`, and refer to it through a normal linked resource. The concept or spec then names the content through the linked file, not through a URL or folder path string.
69
+
70
+ The **only** exceptions are URLs and paths that are *values the produced software itself uses at runtime* (e.g. the base URL the integration calls, a database connection path, a CLI argument value). Those are configuration values, not external references, and they belong in the spec because the generated code needs them. A useful litmus test: "Would the renderer benefit from reading the bytes at this URL / folder?" If yes, save it to a text file and link the file. If no (it's a runtime value), it can stay as plain text in the spec.
71
+
72
+ ### What a linked resource CAN be
73
+
74
+ - A single file in the same folder as the `.plain` file, or in any subfolder of it (`resources/` is the conventional home).
75
+ - A **text-based** file the renderer can read end-to-end: JSON, YAML, XML, HTML, Markdown, plain text, CSV, TSV, source code in any language (`.py`, `.js`, `.ts`, `.go`, `.java`, `.rb`, `.rs`, `.kt`, `.swift`, `.c`, `.cpp`, `.cs`, …), shell scripts, SQL, JSON Schema, OpenAPI, AsyncAPI, Protobuf `.proto`, GraphQL SDL, `.jolt`, `.env.example`, `.toml`, `.ini`, `.proto`, `Dockerfile`, etc.
76
+
77
+ ## Common Resource Types
78
+
79
+ | Type | Typical location | Use case |
80
+ |------|-----------------|----------|
81
+ | JSON Schema | `resources/*.json` | Defining data structure contracts |
82
+ | OpenAPI / Swagger spec | `resources/*.yaml` | API endpoint definitions |
83
+ | Data transforms | `resources/*.jolt` | Data transformation rules |
84
+ | Test fixtures | `resources/*.json`, `resources/*.csv` | Sample data for tests |
85
+ | Configuration examples | `resources/*.yaml` | Reference configurations |
86
+
87
+ ## When to Use Resources
88
+
89
+ - The information is too detailed or structured to express inline in the spec (e.g., a full JSON schema).
90
+ - The same data is referenced by multiple specs or sections.
91
+ - The resource is an industry-standard format (OpenAPI, JSON Schema) that the renderer can interpret directly.
92
+
93
+ ## When NOT to Use Resources
94
+
95
+ - The information is short enough to include inline in the spec text.
96
+ - The file is generated code (those belong in `plain_modules/`, not `resources/`).
97
+
98
+ ## Validation Checklist
99
+
100
+ - [ ] Resource file exists at the specified path
101
+ - [ ] **Target is a file on disk, not a directory** (the path does not end in `/` and does not resolve to a folder)
102
+ - [ ] **Target is a local path, not a URL** (no `://` anywhere in the target: no `http://`, `https://`, `ftp://`, `git://`, `s3://`, `gs://`, etc.)
103
+ - [ ] **Target is a text-based file** (no binary extensions: `.png`, `.jpg`, `.jpeg`, `.gif`, `.bmp`, `.tiff`, `.webp`, `.ico`, `.pdf`, `.docx`, `.xlsx`, `.pptx`, `.zip`, `.tar`, `.gz`, `.mp3`, `.mp4`, `.wav`, `.exe`, `.so`, `.dylib`, `.class`, `.wasm`, …)
104
+ - [ ] **No URLs or folder paths anywhere in the surrounding `.plain` content** (not as link targets, not in body prose), with the sole exception of URLs / paths that are runtime values the generated software itself uses
105
+ - [ ] Path is relative to the `.plain` file, not absolute
106
+ - [ ] File is in the same folder or a subfolder (no `../` references)
107
+ - [ ] Markdown link syntax is correct: `[display text](relative/path)`
108
+ - [ ] Resource content is relevant and adds value beyond what the spec text says
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: add-template
3
+ description: >-
4
+ Create or include a Liquid template in a ***plain spec file using
5
+ {% include %} syntax. Use when the same spec content needs to be reused
6
+ across multiple .plain files with different parameters.
7
+ ---
8
+
9
+ # Add Template
10
+
11
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
12
+
13
+ Templates use Liquid syntax (`{% include %}`) to reuse the same spec content across multiple `.plain` files. Each inclusion can pass different parameters, producing tailored output from a single source. This is distinct from `import` and `requires` — templates are about textual reuse with parameterization, not module dependencies.
14
+
15
+ ## When to Use Templates
16
+
17
+ - The **exact same spec structure** is needed in more than one `.plain` file.
18
+ - The reused content differs only in specific values (names, paths, config) that can be parameterized.
19
+ - You want a single source of truth for a pattern that appears in multiple modules.
20
+
21
+ ## Format
22
+
23
+ ### Including a Template
24
+
25
+ Use `{% include %}` with the template path and parameters:
26
+
27
+ ```plain
28
+ {% include "console_app_template.plain", main_file_name: "app.py", app_name: "MyApp" %}
29
+ ```
30
+
31
+ Parameters are passed as key-value pairs after the template path. Inside the template, parameters are accessed using Liquid variable syntax (`{{ main_file_name }}`).
32
+
33
+ ### Writing a Template
34
+
35
+ Templates live in the `template/` directory. Only **variables** (`{{ variable_name }}`) are supported — conditionals, loops, and other Liquid features are not available:
36
+
37
+ ```plain
38
+ ***definitions***
39
+ - :{{ app_name }}MainFile: is the entry point file for :{{ app_name }}:.
40
+
41
+ ***implementation reqs***
42
+ - :{{ app_name }}MainFile: should be called "{{ main_file_name }}".
43
+ ```
44
+
45
+ ## Workflow: Including an Existing Template
46
+
47
+ 1. **Check the `template/` directory** to see what templates are available.
48
+ 2. **Read the template** to understand what parameters it expects and what content it produces.
49
+ 3. **Add the `{% include %}` statement** to the target `.plain` file with the correct parameters.
50
+ 4. **Verify** that the expanded content does not introduce concept name collisions or duplicate sections.
51
+
52
+ ## Workflow: Creating a New Template
53
+
54
+ 1. **Identify the repeated pattern** — find spec content that is duplicated (or will be duplicated) across multiple `.plain` files.
55
+ 2. **Extract the common content** into a new `.plain` file in the `template/` directory.
56
+ 3. **Parameterize the differences** — replace the varying parts with Liquid variables.
57
+ 4. **Update the original files** to use `{% include %}` instead of the duplicated content.
58
+
59
+ ## Validation Checklist
60
+
61
+ - [ ] Template file is in the `template/` directory
62
+ - [ ] All varying parts are parameterized with Liquid variables
63
+ - [ ] All required parameters are passed at each `{% include %}` call site
64
+ - [ ] Expanded content does not introduce concept name collisions
65
+ - [ ] Template is used by more than one `.plain` file (otherwise, inline the content)
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: add-test-requirement
3
+ description: >-
4
+ Add a test requirement to the ***test reqs*** section of a ***plain spec
5
+ file. Use when the user wants to specify conformance testing instructions
6
+ like test frameworks, execution methods, or testing constraints in a .plain
7
+ file.
8
+ ---
9
+
10
+ # Add Test Requirement
11
+
12
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
13
+
14
+ ## Workflow
15
+
16
+ 1. **Identify the target `.plain` file.** If ambiguous, ask the user.
17
+ 2. **Read the file** to understand existing test reqs and the overall spec structure.
18
+ 3. **Confirm this is a conformance test concern** — unit test guidance goes in `***implementation reqs***`, not here.
19
+ 4. **Draft the requirement** following the rules below.
20
+ 5. **Insert it** into the `***test reqs***` section.
21
+ 6. **Read the file again** to confirm correct placement and syntax.
22
+
23
+ ## What Belongs Here
24
+
25
+ Test reqs specify how **conformance tests** should be written and run. Common contents:
26
+
27
+ - **Test framework**: which framework to use (e.g., pytest, Unittest, xUnit)
28
+ - **Execution method**: the command to run the tests
29
+ - **Testing constraints**: what must or must not be done in tests (e.g., no skipping tests, mock requirements)
30
+ - **Test data**: how test fixtures or mock data should be structured
31
+ - **Environment setup**: any prerequisites for running conformance tests
32
+
33
+ ## What Does NOT Belong Here
34
+
35
+ - **Unit test guidance** — that goes in `***implementation reqs***`
36
+ - **Acceptance tests** — those are nested under individual functional specs in `***functional specs***`
37
+ - **Behavioral requirements** — those go in `***functional specs***`
38
+ - **Technology choices for the implementation** — those go in `***implementation reqs***`
39
+
40
+ ## Conformance Tests vs Other Tests
41
+
42
+ | Test Type | Where to Specify | Purpose |
43
+ |-----------|-----------------|---------|
44
+ | Unit tests | `***implementation reqs***` | Test individual functionalities in isolation |
45
+ | Conformance tests | `***test reqs***` | Verify implementation conforms to the full spec |
46
+ | Acceptance tests | `***acceptance tests***` under a functional spec | Verify a specific functional spec |
47
+
48
+ ## Format
49
+
50
+ Test reqs are bullet points in the `***test reqs***` section:
51
+
52
+ ```plain
53
+ ***test reqs***
54
+ - :ConformanceTests: should be implemented using pytest framework.
55
+ - :ConformanceTests: will be run using "pytest" command.
56
+ - :ConformanceTests: must be implemented and executed - do not skip tests.
57
+ - :ConformanceTests: should mock all external HTTP calls.
58
+ ```
59
+
60
+ Reference predefined concepts like `:ConformanceTests:` and any defined `:Concepts:` where they add clarity.
61
+
62
+ ## Validation Checklist
63
+
64
+ - [ ] Describes conformance testing concerns, not unit tests or behavior
65
+ - [ ] All referenced `:Concepts:` are defined (or are predefined like `:ConformanceTests:`)
66
+ - [ ] Does not duplicate guidance already present in the file or its imports
67
+ - [ ] Placed inside a `***test reqs***` section
68
+ - [ ] No behavioral requirements that should be in `***functional specs***`
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: analyze-2-func-specs
3
+ description: >-
4
+ Analyze two functional specs from a ***plain spec file to determine if they
5
+ conflict. Use when the user wants to check whether two specific functional
6
+ requirements are compatible, or when debugging a suspected conflict between
7
+ two specs.
8
+ ---
9
+
10
+ # Analyze Two Functional Specs
11
+
12
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
13
+
14
+ ## Input
15
+
16
+ Two functional specs from a `.plain` file (or across `requires` modules). The user provides them directly or points to them by location in a file.
17
+
18
+ ## Workflow
19
+
20
+ 1. **Read both functional specs** and the `***definitions***` section so all referenced `:Concepts:` are understood.
21
+ 2. **Determine chronological order** — which spec comes first? The earlier spec was rendered first and the later spec was rendered with the earlier one in context.
22
+ 3. **Run the conflict analysis** using the checklist below.
23
+ 4. **Output the verdict and nothing else** — either `COMPATIBLE` or `CONFLICTING`. No reasoning, no category labels, no resolution suggestions.
24
+
25
+ ## Conflict Analysis Checklist
26
+
27
+ Work through each question. If any answer is "yes", the specs likely conflict.
28
+
29
+ ### 1. Direct Contradiction
30
+
31
+ Do the two specs make mutually exclusive assertions about the same behavior?
32
+
33
+ ```
34
+ Spec A: The system should return :Resource: items sorted by name in ascending order.
35
+ Spec B: The system should return :Resource: items sorted by creation date in descending order.
36
+
37
+ Verdict: CONFLICTING — both define the sort order for the same response,
38
+ but specify different fields and directions. A single implementation cannot
39
+ satisfy both unless scoped to different contexts.
40
+ ```
41
+
42
+ ### 2. State or Data Conflict
43
+
44
+ Does one spec set a state or value that the other spec assumes is different?
45
+
46
+ ```
47
+ Spec A: :TaskList: should initially be empty.
48
+ Spec B: :TaskList: should contain a default "Welcome" :Task: on first load.
49
+
50
+ Verdict: CONFLICTING — both define the initial state of :TaskList: differently.
51
+ ```
52
+
53
+ ### 3. Behavioral Override
54
+
55
+ Does the later spec silently replace behavior established by the earlier spec without acknowledging it?
56
+
57
+ ```
58
+ Spec A: The system should validate :User: credentials using an API key.
59
+ Spec B: The system should validate :User: credentials using OAuth 2.0.
60
+
61
+ Verdict: CONFLICTING — both define the authentication mechanism but pick
62
+ different approaches. The later spec overrides the earlier one.
63
+ ```
64
+
65
+ ### 4. Scope Ambiguity
66
+
67
+ Are the two specs ambiguous enough that a renderer could interpret them as conflicting, even if the user intends them to be complementary?
68
+
69
+ ```
70
+ Spec A: The system should return all :Resource: items.
71
+ Spec B: The system should return only active :Resource: items.
72
+
73
+ Verdict: CONFLICTING (ambiguous) — "all" vs "only active" appear contradictory.
74
+ Could be resolved by scoping each to different conditions (e.g., filtered vs unfiltered).
75
+ ```
76
+
77
+ ### 5. Shared Concept, Different Constraints
78
+
79
+ Do both specs impose constraints on the same `:Concept:` that cannot coexist?
80
+
81
+ ```
82
+ Spec A: :BatchSize: should be 100 items.
83
+ Spec B: :BatchSize: should be 50 items for :Resource: types with attachments.
84
+
85
+ Verdict: COMPATIBLE — Spec B adds a conditional refinement, not a contradiction.
86
+ ```
87
+
88
+ ## Output Format
89
+
90
+ The skill emits exactly one of these two strings, with no surrounding text, explanation, category label, or resolution suggestion:
91
+
92
+ ```
93
+ COMPATIBLE
94
+ ```
95
+
96
+ or
97
+
98
+ ```
99
+ CONFLICTING
100
+ ```
101
+
102
+ The internal analysis (checklist, chronological reasoning) informs the verdict but must not appear in the output. The caller decides what to do with the result — typically: act on `COMPATIBLE` by proceeding, or invoke `resolve-spec-conflict` on `CONFLICTING` to produce the actual fix.
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: analyze-func-specs
3
+ description: >-
4
+ Analyze a batch of functional specs from a ***plain spec file to determine
5
+ which pairs conflict. Replaces the pair-by-pair `analyze-2-func-specs` flow
6
+ when a caller wants to check many specs at once (e.g. a new spec against
7
+ every existing spec, or a freshly inserted batch against itself).
8
+ ---
9
+
10
+ # Analyze Functional Specs
11
+
12
+ Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.
13
+
14
+ ## Input
15
+
16
+ A **set of two or more functional specs** to check against each other. Callers typically supply one of:
17
+
18
+ - A whole `***functional specs***` section to self-check.
19
+ - A new spec (or batch of new specs) **plus** the existing specs from the same file and any `requires` modules.
20
+ - An explicit list of spec snippets the user wants compared.
21
+
22
+ Each spec must be identifiable. If the caller didn't label them, assign **stable identifiers** in order of appearance: `S1`, `S2`, `S3`, …. Use those identifiers in the output. If the caller provided their own IDs or quoted snippets, use those instead and keep them verbatim.
23
+
24
+ The skill also needs the `***definitions***` section (and any imported definitions) so referenced `:Concepts:` can be resolved.
25
+
26
+ ## Workflow
27
+
28
+ 1. **Read all input specs and the relevant `***definitions***`** so every `:Concept:` is understood.
29
+ 2. **Establish chronological order** across the batch. Earlier specs are considered to have been rendered first; later specs are evaluated with the earlier ones in context. If the caller already provided an order, preserve it.
30
+ 3. **Generate the pair list.** Enumerate every unordered pair `(Sᵢ, Sⱼ)` with `i < j`. Skip pairs where the two specs share no `:Concept:` and no overlapping subject — they are trivially compatible and listing them adds noise.
31
+ 4. **Run the conflict analysis below on each remaining pair.** Use the same checklist that the legacy `analyze-2-func-specs` skill used, but apply it pair by pair across the batch in a single pass — do not require the caller to invoke the analyzer once per pair.
32
+ 5. **Record every CONFLICTING pair.** Compatible pairs are not listed individually; only the conflicts are emitted.
33
+ 6. **Output the verdict** in the format below. No reasoning, no category labels, no resolution suggestions.
34
+
35
+ ## Conflict Analysis Checklist (applied per pair)
36
+
37
+ Work through each question for the pair under inspection. If any answer is "yes", that pair is CONFLICTING.
38
+
39
+ ### 1. Direct Contradiction
40
+
41
+ Do the two specs make mutually exclusive assertions about the same behavior?
42
+
43
+ ```
44
+ Spec A: The system should return :Resource: items sorted by name in ascending order.
45
+ Spec B: The system should return :Resource: items sorted by creation date in descending order.
46
+
47
+ Verdict: CONFLICTING — both define the sort order for the same response,
48
+ but specify different fields and directions. A single implementation cannot
49
+ satisfy both unless scoped to different contexts.
50
+ ```
51
+
52
+ ### 2. State or Data Conflict
53
+
54
+ Does one spec set a state or value that the other spec assumes is different?
55
+
56
+ ```
57
+ Spec A: :TaskList: should initially be empty.
58
+ Spec B: :TaskList: should contain a default "Welcome" :Task: on first load.
59
+
60
+ Verdict: CONFLICTING — both define the initial state of :TaskList: differently.
61
+ ```
62
+
63
+ ### 3. Behavioral Override
64
+
65
+ Does the later spec silently replace behavior established by the earlier spec without acknowledging it?
66
+
67
+ ```
68
+ Spec A: The system should validate :User: credentials using an API key.
69
+ Spec B: The system should validate :User: credentials using OAuth 2.0.
70
+
71
+ Verdict: CONFLICTING — both define the authentication mechanism but pick
72
+ different approaches. The later spec overrides the earlier one.
73
+ ```
74
+
75
+ ### 4. Scope Ambiguity
76
+
77
+ Are the two specs ambiguous enough that a renderer could interpret them as conflicting, even if the user intends them to be complementary?
78
+
79
+ ```
80
+ Spec A: The system should return all :Resource: items.
81
+ Spec B: The system should return only active :Resource: items.
82
+
83
+ Verdict: CONFLICTING (ambiguous) — "all" vs "only active" appear contradictory.
84
+ Could be resolved by scoping each to different conditions (e.g., filtered vs unfiltered).
85
+ ```
86
+
87
+ ### 5. Shared Concept, Different Constraints
88
+
89
+ Do both specs impose constraints on the same `:Concept:` that cannot coexist?
90
+
91
+ ```
92
+ Spec A: :BatchSize: should be 100 items.
93
+ Spec B: :BatchSize: should be 50 items for :Resource: types with attachments.
94
+
95
+ Verdict: COMPATIBLE — Spec B adds a conditional refinement, not a contradiction.
96
+ ```
97
+
98
+ ## Output Format
99
+
100
+ Emit exactly one of the two shapes below, with no surrounding text, explanation, category label, or resolution suggestion.
101
+
102
+ If **no pair** is conflicting:
103
+
104
+ ```
105
+ COMPATIBLE
106
+ ```
107
+
108
+ If **one or more pairs** are conflicting, emit `CONFLICTING` followed by one line per conflicting pair, in `Sᵢ x Sⱼ` form (using the identifiers from the input, with `i < j`), sorted lexicographically:
109
+
110
+ ```
111
+ CONFLICTING
112
+ S1 x S4
113
+ S2 x S3
114
+ S3 x S5
115
+ ```
116
+
117
+ Rules for the output:
118
+
119
+ - Do **not** list compatible pairs.
120
+ - Do **not** include reasoning, checklist categories, or fixes — the caller decides what to do with each conflict (typically: invoke `resolve-spec-conflict` on each pair).
121
+ - If the input contained fewer than two specs, emit `COMPATIBLE` (nothing to compare).
122
+ - Identifiers must match exactly what the caller provided (or the `S1`, `S2`, … fallback assigned in step 1).
123
+
124
+ The internal pairwise analysis informs the verdict but must not appear in the output.