Foreign template engines would split validation and documentation across ecosystems.
Design model
Platform spec article
Design model
Spec standingStandard
-
Use beskid.template.v1 only
Context
Decision
The platform must use
beskid.template.v1only. Foreign engine schemas are forbidden in spec, CLI, and pckg.Consequences
Single parser and validator in tooling; template docs stay in-repo.
Verification anchors
CI grep excluding foreign schema identifiers under
compiler/and platform-spec tooling tree. -
Use {{symbolId}} delimiters in template text
Context
Template authors need delimiter syntax distinct from Beskid source.
Decision
Text files must use
{{symbolName}}placeholders; optionalsourceNamerewriting applies to paths and identifiers.Consequences
Editors can highlight unmatched braces; substitution tests stay deterministic.
Verification anchors
Golden substitution tests under planned
beskid_teststemplate fixtures. -
Validation runs on instantiation output only, not template project build.
Context
Requiring
beskid buildon template sources slows authoring and blocks non-host template layouts.Decision
Template packages need not compile at the template project root. Tooling must validate via instantiation output builds.
Consequences
Faster template iteration; CI runs instantiate-then-build on consumer output.
Verification anchors
beskid.templates.*CI pipeline; plannedbeskid_teststemplate fixtures. -
Implicit corelib
Context
Hosts need standard library.
Decision
Inject corelib; forbid noCorelib flags.
Consequences
Simpler manifests.
Verification anchors
E18xx linter.
-
Three template kinds
Context
Workspace, project, item flows.
Decision
Support all three via tags.type.
Consequences
One engine.
Verification anchors
Three beskid_tests fixtures.
-
Path and git sources
Context
Local workflows.
Decision
Resolve registry, path, and git.
Consequences
beskid new flags.
Verification anchors
Git/path integration tests.
-
No constraints
Context
DSL delay.
Decision
No constraint blocks in schema.
Consequences
Simpler v1.
Verification anchors
Reject constraints key.
-
Post-actions
Context
Extensibility.
Decision
Documented action ids, no v1 whitelist.
Consequences
Operator sandbox policy.
Verification anchors
Action registry docs.
-
Update on use
Context
Stale cache.
Decision
Compare cache on every use when online.
Consequences
Update prompts.
Verification anchors
Mock HTTP test.
-
Yanked warning
Context
Yank policy.
Decision
Warn on yanked; optional continue flag.
Consequences
Registry alignment.
Verification anchors
Yank API test.
- Contracts and edge cases Normative MUST/SHOULD rules for template instantiation, updates, yanked packages, and post-actions.
- Decisions record (legacy index) Migration index pointing to per-decision ADR files under adr/.
- Design model `beskid.template.v1` schema, symbols, sources, placeholders, GUIDs, and corelib policy.
- Examples Sample `beskid.template.v1` manifests and first-party `beskid.templates.*` packages.
- FAQ and troubleshooting Common questions about Beskid templates and `beskid new`.
- Flow and algorithm End-to-end lifecycle for install, update check, and instantiate.
- Verification and traceability Tests, CI, and registry checks for template conformance.
0 revisions (git unavailable at build; counts may be empty)
No commits recorded for this path.
| Section id | Required | Found |
|---|---|---|
what-this-feature-specifies | yes | yes |
implementation-anchors | yes | yes |
Full tree: run pnpm verify:platform-spec-layout (writes src/generated/platform-spec-layout-report.json).
Purpose and scope
Section titled “Purpose and scope”This article defines the normative data model for Beskid templates: manifest file location, beskid.template.v1 top-level keys, symbol types, content manipulation, and corelib behavior on instantiated projects.
Manifest location
Section titled “Manifest location”| Context | Path |
|---|---|
| Template package or git/path tree | .beskid/template.json at the template root |
Optional author metadata in Project.proj | project.template { shortName, identity } when type: Template |
The engine must read .beskid/template.json as authoritative. project.template keys are hints for discovery and packaging; if both exist, template.json wins on conflict.
Top-level beskid.template.v1 keys
Section titled “Top-level beskid.template.v1 keys”| Key | Required | Meaning |
|---|---|---|
schema | yes | Literal beskid.template.v1 |
identity | yes | Stable id: packageId::version or path/git fingerprint |
name | yes | Display name in beskid new list |
shortName | yes | CLI selector: beskid new <shortName> |
author | no | Author string |
description | no | Short summary |
classifications | no | Search tags |
tags | no | Object; type must be one of: project, workspace, item |
sourceName | no | Default token replaced in paths and file bodies (in addition to {{ }}) |
symbols | no | Parameter definitions |
sources | no | File copy rules; default single mapping ./ → output |
guids | no | GUIDs to regenerate in output |
forms | no | Value transforms (see below) |
postActions | no | Ordered post-instantiation actions |
preferInteractive | no | When true, prompt for symbols without CLI values before using defaults |
Forbidden in v1: constraints, foreign schema imports, or alternate placeholder delimiters.
Tags.type semantics
Section titled “Tags.type semantics”tags.type | Output |
|---|---|
project | Creates a directory tree with Project.proj (and Src/ or template-defined layout) |
workspace | Creates Workspace.proj plus member project trees |
item | Adds or overwrites files inside an existing project directory; must not emit a new root Project.proj unless sources explicitly includes one and the CLI passed --allow-project-manifest |
Symbols
Section titled “Symbols”Each symbol is an object keyed by symbol id (used in {{symbolId}}):
| Field | Required | Meaning |
|---|---|---|
type | yes | string, choice, bool, integer |
description | no | Prompt text |
defaultValue | no | Used when non-interactive and flag omitted |
choices | for choice | Allowed values |
isRequired | no | Default false; when true, interactive mode must collect a value |
CLI mapping: --symbol <id>=<value> and short forms documented in beskid new.
Placeholders
Section titled “Placeholders”{{symbolId}}— replaced in all processed text files afterformsare applied.sourceName— when set at template level, every occurrence of thesourceNamestring in paths and file contents is replaced with the primary name symbol (default symbol idnameunlessnameSymbolspecifies another).
Hosts must fail if any {{...}} remains after substitution.
forms define named transforms applied to symbol values before substitution (for example lowerCase, safeName, namespace). Built-in form ids are listed in contracts and edge cases.
Sources
Section titled “Sources”Each source entry:
| Field | Default | Meaning |
|---|---|---|
source | ./ | Path inside template root |
target | ./ | Relative to user output directory |
include | ["**/*"] | Glob includes |
exclude | build artifacts, .beskid/template.json copy to wrong place | Glob excludes |
copyOnly | [] | Copy without text processing |
rename | {} | Explicit renames after symbol resolution |
condition | true | When false, skip this source block |
modifiers | [] | Conditional patches to include/exclude |
.beskid/template.json must not appear in generated output unless a source block intentionally copies it to a documentation path.
The guids array lists GUID strings appearing in template sources. For each entry, the engine must generate a new GUID and replace all occurrences in output, preserving format and casing of each occurrence (same rules as common template GUID rewriting: match N, D, B, P, X representations independently).
corelib policy
Section titled “corelib policy”| Rule | Normative statement |
|---|---|
| Implicit dependency | Every instantiated project with project.type absent or Host must treat corelib as an implicit registry dependency resolved by the toolchain—equivalent to today’s std/corelib discovery path. |
| Manifest surface | Project.proj emitted by templates must not declare a noCorelib, useCorelib: false, or any flag that disables corelib. |
| Template author docs | Templates may omit an explicit dependency "corelib" block from generated manifests; the first beskid lock / fetch must materialize corelib anyway. |
| Mod / workspace | Mod projects in template output follow mod resolution rules; corelib policy applies to host members that execute Beskid user code. |
If the compiler today requires an explicit dependency for some workflows, tooling must inject the dependency during instantiation or in post-action addCorelib—without exposing a user-facing opt-out.
Authoring: project.type = Template
Section titled “Authoring: project.type = Template”project { name = "beskid-templates-console" version = "0.0.0" type = Template template { shortName = "console" identity = "beskid.templates.console" }}Template projects must not be selected as compile targets for beskid build at the template package root; only their packaged .beskid/template.json is consumed by consumers.
Diagram
Section titled “Diagram”flowchart TB TJ[.beskid/template.json] SYM[symbols] SRC[sources] PH["{{ }} + sourceName"] GD[guids] OUT[Output tree] TJ --> SYM --> PH TJ --> SRC --> PH TJ --> GD --> OUT PH --> OUTCode anchors
Section titled “Code anchors”- Planned:
compiler/crates/beskid_cli/src/template/(engine) - Manifest parse: extend
compiler/crates/beskid_analysis/src/projects/model.rswithProjectKind::Template - Registry:
pckgtemplate package profile