
Add Functional Spec
- 38 installs
- 54 repo stars
- Updated July 22, 2026
- codeplain-ai/plain-forge
Add a single functional spec to a ***plain spec file, enforcing the complexity limit and checking for conflicts with existing specs.
About
Adds a single functional spec to the ***functional specs*** section of a ***plain spec file with complexity and conflict checks. A developer uses it whenever exactly one new functional spec must be authored.
- Adds one functional spec, checking the 200-LOC complexity limit
- Runs conflict analysis against all existing specs before appending
Add Functional Spec by the numbers
- 38 all-time installs (skills.sh)
- Ranked #376 of 782 Skill Development skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/codeplain-ai/plain-forge --skill add-functional-specAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 38 |
|---|---|
| repo stars | ★ 54 |
| Last updated | July 22, 2026 |
| Repository | codeplain-ai/plain-forge ↗ |
What it does
Add a single functional spec to a ***plain spec file, enforcing the complexity limit and checking for conflicts with existing specs.
Files
Add Functional Spec
Always use the skill load-plain-reference to retrieve the ***plain syntax rules — but only if you haven't done so yet.
Workflow
1. Identify the target `.plain` file. If ambiguous, ask the user. 2. Read the entire file to understand existing definitions, implementation reqs, and all current functional specs (including those in requires modules). 3. Draft the functional spec following the rules below. 4. Analyze complexity — use the analyze-if-func-spec-too-complex skill to verify the drafted spec implies ≤ 200 LOC. If too complex, use the break-down-func-spec skill to split it, then repeat from step 3 for each resulting spec. 5. Check for conflicts with every existing functional spec — this is critical. Run analyze-func-specs once with the new spec plus all existing specs (in the file and in any requires chain) as a single batch. The batched analyzer returns every conflicting pair in one call — do not invoke a pair-by-pair analyzer. For each conflicting pair it reports, run resolve-spec-conflict on that pair; re-run analyze-func-specs over the touched set after each resolution until the verdict is COMPATIBLE. 6. Append the spec to the end of the ***functional specs*** section (specs are chronological; new ones go last). 7. Read the file again to confirm correct placement and syntax.
Rules
Complexity Limit
Each functional spec must imply a maximum of 200 changed lines of code. If the requirement is too large, use the break-down-func-spec skill to split it into multiple smaller, independent specs. Do not include LOC estimates in the spec text.
Chronological Ordering
Specs are rendered incrementally, top to bottom. The renderer has no knowledge of future specs — only previously rendered specs are in context. This means:
- A new spec can reference behavior defined by earlier specs.
- A new spec cannot assume anything about specs that come after it.
- Place the new spec at the correct position if it must come before a future spec; otherwise append at the end.
Language Agnosticism
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***.
No Conflicts
The new spec must not contradict any existing functional spec. Conflicting specs are the most costly outcome. Before adding, review all existing specs and verify the new one is compatible. Use analyze-func-specs to check the new spec against every existing spec in one batched call — it lists every conflicting pair, so a pair-by-pair analyzer is not needed. 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.
Disambiguation
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.
- :User: should be able to send a :Message: to a :Conversation:.
- A :Message: must have non-empty content.
- The :Message: is appended to the end of the :Conversation:.
- All :Participant: members of the :Conversation: can see the new :Message:.Line syntax (hard rule)
Every line inside `functional specs` must be its own list item starting with `- `. *plain has no concept of bare continuation lines — indented prose without a leading `- ` is invalid syntax** and the renderer will reject it.
- Hard limit: 120 characters per line. If a sentence is too long, split it at a natural clause boundary into nested `- ` bullets — never wrap onto an unprefixed line.
- Nested clarifications are also
-items, indented under the parent. The indentation alone is not enough; the leading-is required.
BAD — bare continuation lines (invalid ***plain syntax, will not render):
- :GatewayWebhook: should hand off :StripeRequest: to :StripeIntegration:.handle(),
which returns a list of :EventEnvelope: dicts conforming to the gateway's
contract.GOOD — every line starts with - :
- :GatewayWebhook: should hand off :StripeRequest: to :StripeIntegration:.handle().
- The method returns a list of :EventEnvelope: dicts.
- The dicts must conform to the gateway's :EventEnvelope: contract.Deterministic Interface
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.
Encapsulation
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.
Acceptance Tests
If the functional spec needs verification, use the add-acceptance-test skill to add acceptance tests after inserting the spec.
Validation Checklist
- [ ] Spec implies ≤ 200 lines of code changes
- [ ] No conflict with any existing functional spec
- [ ] Written in language-agnostic terms (no language/framework specifics)
- [ ] All external interfaces are explicit (endpoint paths, methods, CLI args, formats, etc.)
- [ ] All referenced
:Concepts:are defined in***definitions*** - [ ] Sentences are short, clear, and unambiguous
- [ ] No redundancy with existing specs
- [ ] Placed in correct chronological position (usually at the end)