Vertical Creator
Core Rule
Keep verticals declarative. A vertical defines entity shape, template catalogs, scaffolds, defaults, and applicable presets. It must not require CLI core branches for a specific domain.
The CLI may provide only generic vertical infrastructure:
- Schema validation.
- Template catalog loading.
- Template materialization.
- Settings/dev-mode gating.
- Generic preset and profile selection.
Vertical-specific behavior belongs in vertical assets, template catalogs, preset manifests, and process scripts.
Workflow
- Name the domain and list its entity kinds using the entity declaration tuple.
- Decide which entities are lifecycle package entities and which are schema-only metadata entities.
- Define package scaffolds and repository roots for every lifecycle entity.
- Put template bodies in Markdown assets under
assets/<vertical>/templates/<slot>/<locale>.md. - Register those assets in
template-catalog/v2withbodyPath; do not use inlinebody. - Define required documents as
templateSelectionsthat point at catalog refs. - Choose the checker profile and projection schemas.
- Define applicable presets separately as
preset-manifest/v2; do not bury preset behavior in the vertical. - Run
ha vertical validate <path>before publishing the vertical. - Add validation tests for schema shape, materialized paths, catalog body paths, and default preset/profile behavior.
- Add integration tests only for real CLI/filesystem behavior.
Entity Declaration Tuple
Declare each entity with the v2 five-part contract:
identityTypepackageKindfor lifecycle entities orschemaReffor schema entitiescontractEntity- matching scaffold/root membership where required
Lifecycle entities must have both a packageScaffolds entry and a repositoryScaffold.entityRoots entry. Schema entities must not have package scaffolds or repository roots.
Vertical Definition Pattern
This minimal shape was validated with ha vertical validate vertical.json.
{
"schema": "vertical-definition/v1",
"id": "example/work",
"title": "Example Work",
"version": "1.0.0",
"entityFieldExtensions": [],
"entityKinds": [
{
"id": "task",
"entityType": "lifecycle",
"packageKind": "task-package/v2",
"contractEntity": true
},
{
"id": "fact",
"entityType": "schema",
"schemaRef": "schema://fact-record",
"contractEntity": true
}
],
"contractEntityKinds": ["task", "fact"],
"packageScaffolds": [
{
"entityKind": "task",
"templateSelections": []
}
],
"repositoryScaffold": {
"entityRoots": [
{
"entityKind": "task",
"path": "{{paths.tasksRoot}}",
"create": "init"
}
],
"dirs": [],
"seededDocs": []
},
"scripts": [],
"templateSelections": [],
"checkerProfile": "standard",
"projectionSchemas": []
}
Validate it:
ha vertical validate vertical.json
Template Catalog v2
A vertical package should keep bodies as Markdown assets and register them by bodyPath:
assets/software-coding/
vertical.json
template-catalog.json
templates/
task.plan/
en-US.md
zh-CN.md
presets/
standard-task/
preset.json
Catalog root:
{
"schema": "template-catalog/v2",
"package": {
"id": "software-coding-core",
"title": "Software Coding Core Templates",
"version": "1.0.0",
"owner": "harness-anything",
"locales": ["zh-CN", "en-US"]
},
"documents": [
{
"id": "planning/task-plan",
"version": "1",
"documentKind": "task-plan",
"slot": "task.plan",
"materializeAs": "task_plan.md",
"frontmatterSchema": "task-package/v2",
"requiredAnchors": ["## Goal", "## Verification"],
"fallbackLocale": "en-US",
"locales": [
{
"locale": "en-US",
"anchors": ["## Goal", "## Verification"],
"bodyPath": "templates/task.plan/en-US.md"
},
{
"locale": "zh-CN",
"anchors": ["## Goal", "## Verification"],
"bodyPath": "templates/task.plan/zh-CN.md"
}
]
}
]
}
templates/task.plan/en-US.md must contain all required anchors:
## Goal
Describe the target outcome.
## Verification
List the validation steps.
Preset overlays should reference the same catalog documents from preset-manifest/v2 profiles:
{
"id": "baseline",
"title": "Baseline",
"checkerProfile": "standard",
"completionGates": [],
"templateSelections": [
{
"slot": "task.plan",
"templateRef": "template://planning/task-plan@1",
"materializeAs": "task_plan.md",
"localePolicy": { "prefer": "project", "fallback": "en-US" }
}
]
}
Design Rules
- Use templates for document structure, not ad hoc file writes.
- Use presets for optional process or content overlays.
- Use
preset-manifest/v2for all new preset examples. - Use
template-catalog/v2withbodyPath; never teach inline templatebody. - Keep project/user overrides additive and fail closed on invalid active overrides.
- Do not promise unattended conversion when the system supports Legacy Intake plus explicit rebuild only.
- Keep private harness operating state out of public docs unless explicitly designing public product documentation.
Review Checklist
ha vertical validate <path>passes.- Entity kinds declare
entityTypeand exactly one ofpackageKindorschemaRef. - Every lifecycle entity has a package scaffold and repository root.
- Schema entities do not declare package scaffolds or repository roots.
- Template refs exist in
template-catalog/v2and use asset-backedbodyPath. - Required anchors match locale anchors and appear in each body asset.
- Presets shipped with the vertical use
preset-manifest/v2,profiles, anddefaultProfile; every v2 profile explicitly declarescompletionGates, even when empty (ADR-0027 D7). - Preset manifests pass
ha preset validate <manifest>. - The vertical works without CLI branches keyed by vertical id.
- Template refs exist in the catalog and materialize to stable paths.
- Default preset/profile behavior is explicit.
- Custom verticals remain gated by user dev mode and project settings.
- Tests are placed in the proper tier manifest when new test files are added.