As a template author, I want a well-defined manifest schema (v2) so that I can use computed variables, transforms, and advanced prompt validation with clear documentation.
Design
Schema Version
Add explicit schema version for forward compatibility:
schemaVersion:2
Full Manifest v2 Schema
schemaVersion:2id:qqq-web-apiname:QQQ Web APIversion:1.0.0description:Web API application with Javalin middlewareminimumQctlVersion:0.2.0prompts:- name:packageNamemessage:"Java package"type:stringdefault:"com.example.myapp"required:truevalidation:pattern:"^[a-z][a-z0-9]*(\\.[a-z][a-z0-9]*)*$"message:"Must be a valid Java package name"- name:appNamemessage:"Application name"type:stringdefault:"myApp"required:true- name:includeDockermessage:"Include Dockerfile?"type:booleandefault:truecomputed:packagePath:"${packageName.replace('.', '/')}"appClassName:"${str.pascal($appName)}App"transforms:- type:movefrom:"src/main/java/com/example/template"to:"src/main/java/${packagePath}"conditionals:- condition:"${includeDocker}"include:- "Dockerfile"- "docker-compose.yml"postGen:- name:buildcommand:"mvn clean compile -DskipTests"workDir:"."optional:falsephase:build- name:formatcommand:"mvn spotless:apply"phase:formatignore:- ".git"- "*.bak"- "template.yaml"
New Fields
Field
Type
Description
schemaVersion
int
Manifest schema version (2)
minimumQctlVersion
string
Minimum qctl version required
prompts[].required
boolean
Whether prompt is required
prompts[].validation
object
Validation rules
computed
map
Computed variable definitions
transforms
list
Directory/file transformation rules
conditionals
list
Conditional file inclusion
postGen[].phase
string
Execution phase (build, format, test)
Files to Create/Modify
File
Action
Description
TemplateManifest.java
Modify
Add all v2 fields
ManifestValidator.java
Create
Validates manifest against schema
PromptValidation.java
Create
Validation rule record
Conditional.java
Create
Conditional inclusion record
docs/template-manifest-v2.md
Create
Schema documentation
Implementation Tasks
Add schemaVersion field with default value handling
Add minimumQctlVersion field and version check
Add required and validation fields to Prompt record
Create PromptValidation record with pattern and message
Add computed field (Map<String, String>)
Add transforms field (List)
Create Conditional record with condition and include/exclude
Add conditionals field
Add phase field to PostGenHook
Create ManifestValidator for schema validation
Handle schema version migration (v1 -> v2)
Write comprehensive schema documentation
Add unit tests for all new fields
Add integration test with full v2 manifest
Acceptance Criteria
v1 manifests continue to work (backward compatible)
v2 manifests parse all new fields correctly
Schema validation catches invalid manifests
minimumQctlVersion enforced with clear error
Documentation covers all fields with examples
JSON Schema generated for IDE support (optional)
Part of #12
## User Story
As a **template author**, I want a well-defined manifest schema (v2) so that I can use computed variables, transforms, and advanced prompt validation with clear documentation.
## Design
### Schema Version
Add explicit schema version for forward compatibility:
```yaml
schemaVersion: 2
```
### Full Manifest v2 Schema
```yaml
schemaVersion: 2
id: qqq-web-api
name: QQQ Web API
version: 1.0.0
description: Web API application with Javalin middleware
minimumQctlVersion: 0.2.0
prompts:
- name: packageName
message: "Java package"
type: string
default: "com.example.myapp"
required: true
validation:
pattern: "^[a-z][a-z0-9]*(\\.[a-z][a-z0-9]*)*$"
message: "Must be a valid Java package name"
- name: appName
message: "Application name"
type: string
default: "myApp"
required: true
- name: includeDocker
message: "Include Dockerfile?"
type: boolean
default: true
computed:
packagePath: "${packageName.replace('.', '/')}"
appClassName: "${str.pascal($appName)}App"
transforms:
- type: move
from: "src/main/java/com/example/template"
to: "src/main/java/${packagePath}"
conditionals:
- condition: "${includeDocker}"
include:
- "Dockerfile"
- "docker-compose.yml"
postGen:
- name: build
command: "mvn clean compile -DskipTests"
workDir: "."
optional: false
phase: build
- name: format
command: "mvn spotless:apply"
phase: format
ignore:
- ".git"
- "*.bak"
- "template.yaml"
```
### New Fields
| Field | Type | Description |
|-------|------|-------------|
| `schemaVersion` | int | Manifest schema version (2) |
| `minimumQctlVersion` | string | Minimum qctl version required |
| `prompts[].required` | boolean | Whether prompt is required |
| `prompts[].validation` | object | Validation rules |
| `computed` | map | Computed variable definitions |
| `transforms` | list | Directory/file transformation rules |
| `conditionals` | list | Conditional file inclusion |
| `postGen[].phase` | string | Execution phase (build, format, test) |
## Files to Create/Modify
| File | Action | Description |
|------|--------|-------------|
| `TemplateManifest.java` | Modify | Add all v2 fields |
| `ManifestValidator.java` | Create | Validates manifest against schema |
| `PromptValidation.java` | Create | Validation rule record |
| `Conditional.java` | Create | Conditional inclusion record |
| `docs/template-manifest-v2.md` | Create | Schema documentation |
## Implementation Tasks
- [ ] Add `schemaVersion` field with default value handling
- [ ] Add `minimumQctlVersion` field and version check
- [ ] Add `required` and `validation` fields to `Prompt` record
- [ ] Create `PromptValidation` record with `pattern` and `message`
- [ ] Add `computed` field (Map<String, String>)
- [ ] Add `transforms` field (List<Transform>)
- [ ] Create `Conditional` record with `condition` and `include`/`exclude`
- [ ] Add `conditionals` field
- [ ] Add `phase` field to `PostGenHook`
- [ ] Create `ManifestValidator` for schema validation
- [ ] Handle schema version migration (v1 -> v2)
- [ ] Write comprehensive schema documentation
- [ ] Add unit tests for all new fields
- [ ] Add integration test with full v2 manifest
## Acceptance Criteria
- [ ] v1 manifests continue to work (backward compatible)
- [ ] v2 manifests parse all new fields correctly
- [ ] Schema validation catches invalid manifests
- [ ] `minimumQctlVersion` enforced with clear error
- [ ] Documentation covers all fields with examples
- [ ] JSON Schema generated for IDE support (optional)
conditionals → Future story (new feature complexity)
Files to Modify
TemplateManifest.java - Add new fields
TemplatesHub.java - Add fields to TemplateEntry
InitCommand.java - Add version check logic
## Implementation Approach
Simplified scope focusing on schema housekeeping:
### In Scope
1. `schemaVersion` field with v1 backward compatibility
2. `minimumQctlVersion` with version check at init time
3. `prompts[].required` field
4. `postGen[].phase` field
### Deferred
- `prompts[].validation` → #24 (Add prompt validation)
- `conditionals` → Future story (new feature complexity)
### Files to Modify
- `TemplateManifest.java` - Add new fields
- `TemplatesHub.java` - Add fields to TemplateEntry
- `InitCommand.java` - Add version check logic
## Implementation Complete
Story #21 has been implemented with simplified scope:
### Changes Made
- Added `schemaVersion` field (Integer) to TemplateManifest and TemplateEntry
- Added `minimumQctlVersion` field with version check in InitCommand
- Added `required` field (Boolean) to Prompt record
- Added `phase` field (String) to PostGenHook record
- Added `getEffectiveSchemaVersion()` helper method (defaults to 1 for backward compat)
- Added `isVersionSatisfied()` and `parseVersion()` helpers in InitCommand
### Deferred to Other Stories
- `prompts[].validation` → Story #24 (Add prompt validation)
- Conditional fields → Future story
### Files Modified
- `TemplateManifest.java` - Added schema v2 fields
- `TemplatesHub.java` - Updated TemplateEntry record
- `InitCommand.java` - Added version check logic
- `TemplateEngineTest.java` - Updated constructor calls
All tests pass.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of #12
User Story
As a template author, I want a well-defined manifest schema (v2) so that I can use computed variables, transforms, and advanced prompt validation with clear documentation.
Design
Schema Version
Add explicit schema version for forward compatibility:
Full Manifest v2 Schema
New Fields
schemaVersionminimumQctlVersionprompts[].requiredprompts[].validationcomputedtransformsconditionalspostGen[].phaseFiles to Create/Modify
TemplateManifest.javaManifestValidator.javaPromptValidation.javaConditional.javadocs/template-manifest-v2.mdImplementation Tasks
schemaVersionfield with default value handlingminimumQctlVersionfield and version checkrequiredandvalidationfields toPromptrecordPromptValidationrecord withpatternandmessagecomputedfield (Map<String, String>)transformsfield (List)Conditionalrecord withconditionandinclude/excludeconditionalsfieldphasefield toPostGenHookManifestValidatorfor schema validationAcceptance Criteria
minimumQctlVersionenforced with clear errorImplementation Approach
Simplified scope focusing on schema housekeeping:
In Scope
schemaVersionfield with v1 backward compatibilityminimumQctlVersionwith version check at init timeprompts[].requiredfieldpostGen[].phasefieldDeferred
prompts[].validation→ #24 (Add prompt validation)conditionals→ Future story (new feature complexity)Files to Modify
TemplateManifest.java- Add new fieldsTemplatesHub.java- Add fields to TemplateEntryInitCommand.java- Add version check logicImplementation Complete
Story #21 has been implemented with simplified scope:
Changes Made
schemaVersionfield (Integer) to TemplateManifest and TemplateEntryminimumQctlVersionfield with version check in InitCommandrequiredfield (Boolean) to Prompt recordphasefield (String) to PostGenHook recordgetEffectiveSchemaVersion()helper method (defaults to 1 for backward compat)isVersionSatisfied()andparseVersion()helpers in InitCommandDeferred to Other Stories
prompts[].validation→ Story #24 (Add prompt validation)Files Modified
TemplateManifest.java- Added schema v2 fieldsTemplatesHub.java- Updated TemplateEntry recordInitCommand.java- Added version check logicTemplateEngineTest.java- Updated constructor callsAll tests pass.