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.
- package/LICENSE +21 -0
- package/README.md +247 -0
- package/bin/cli.mjs +143 -0
- package/forge/docs/.gitkeep +0 -0
- package/forge/rules/definitions.md +57 -0
- package/forge/rules/exported-concepts.md +39 -0
- package/forge/rules/func-specs.md +72 -0
- package/forge/rules/impl-reqs.md +50 -0
- package/forge/rules/import-modules.md +51 -0
- package/forge/rules/required-concepts.md +45 -0
- package/forge/rules/requires-modules.md +59 -0
- package/forge/rules/test-reqs.md +47 -0
- package/forge/skills/add-acceptance-test/SKILL.md +98 -0
- package/forge/skills/add-concept/SKILL.md +67 -0
- package/forge/skills/add-feature/SKILL.md +136 -0
- package/forge/skills/add-functional-spec/SKILL.md +81 -0
- package/forge/skills/add-functional-specs/SKILL.md +115 -0
- package/forge/skills/add-implementation-requirement/SKILL.md +73 -0
- package/forge/skills/add-resource/SKILL.md +108 -0
- package/forge/skills/add-template/SKILL.md +65 -0
- package/forge/skills/add-test-requirement/SKILL.md +68 -0
- package/forge/skills/analyze-2-func-specs/SKILL.md +102 -0
- package/forge/skills/analyze-func-specs/SKILL.md +124 -0
- package/forge/skills/analyze-if-func-spec-too-complex/SKILL.md +152 -0
- package/forge/skills/break-down-func-spec/SKILL.md +156 -0
- package/forge/skills/check-plain-env/SKILL.md +288 -0
- package/forge/skills/consolidate-concepts/SKILL.md +193 -0
- package/forge/skills/create-import-module/SKILL.md +98 -0
- package/forge/skills/create-requires-module/SKILL.md +104 -0
- package/forge/skills/debug-specs/SKILL.md +189 -0
- package/forge/skills/forge-integration/SKILL.md +443 -0
- package/forge/skills/forge-plain/SKILL.md +333 -0
- package/forge/skills/implement-conformance-testing-script/SKILL.md +247 -0
- package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_cypress.ps1 +324 -0
- package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_golang.ps1 +100 -0
- package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_java.sh +102 -0
- package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.ps1 +92 -0
- package/forge/skills/implement-conformance-testing-script/assets/run_conformance_tests_python.sh +100 -0
- package/forge/skills/implement-prepare-environment-script/SKILL.md +242 -0
- package/forge/skills/implement-prepare-environment-script/assets/prepare_environment_java.sh +42 -0
- package/forge/skills/implement-prepare-environment-script/assets/prepare_environment_python.sh +81 -0
- package/forge/skills/implement-unit-testing-script/SKILL.md +133 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_flutter.ps1 +82 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_golang.ps1 +68 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_java.sh +45 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_python.ps1 +76 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_python.sh +90 -0
- package/forge/skills/implement-unit-testing-script/assets/run_unittests_react.ps1 +83 -0
- package/forge/skills/init-config-file/SKILL.md +261 -0
- package/forge/skills/init-plain-project/SKILL.md +124 -0
- package/forge/skills/load-plain-reference/SKILL.md +646 -0
- package/forge/skills/plain-healthcheck/SKILL.md +132 -0
- package/forge/skills/refactor-module/SKILL.md +197 -0
- package/forge/skills/resolve-spec-conflict/SKILL.md +88 -0
- package/forge/skills/run-codeplain/SKILL.md +540 -0
- 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.
|