individualization.json
individualization.json controls advanced processing behavior for variable replacement, solution deletion, warnings, file handling, artifact processors, and compatibility variation settings.
This file is optional. If it is missing, Divekit falls back to built-in defaults.
Minimal Example
{
"variables": {
"variableDelimiter": "$"
}
}
Common Example
{
"variables": {
"variableDelimiter": "$",
"values": {
"semester": "SS2026"
}
},
"solutionDeletion": {
"enabled": true,
"files": ["src/main/java/Solution.java"]
},
"warnings": {
"enabled": true,
"ignore": ["*.tmp"],
"variationResidues": {
"typeWhiteList": ["java", "md"],
"ignoreList": ["UUID"],
"matchMode": "word",
"ignoreRules": [
{
"paths": ["src/test/java/**"],
"values": ["Dish"]
},
{
"values": ["Dish|Meal"],
"matchMode": "regex"
}
]
}
},
"processors": {
"uml": {
"mode": "both",
"imageFormat": "jpg"
},
"tableHash": {
"solutionTableFileName": "${id}.solution.md",
"hashedSolutionTableFileName": "${id}.hashed.md",
"tableConfigFileName": "${id}.config.json"
}
}
}
Top-Level Keys
| Key | Type | Notes |
|---|---|---|
variables | object | Token delimiters and fixed values. |
solutionDeletion | object | Files, directories, and markers used to remove solution content. |
warnings | object | Validation and unresolved-token warning behavior. |
fileManipulation | object | Target-specific file naming conventions such as _workrepo. |
processors | object | Built-in artifact processors such as UML source/image generation. |
relations | object | Object-relation metadata. |
variableExtensions | object | Prefix, suffix, and transformation maps. |
variations | object | Unified compatibility container for variation data. |
objectVariations | array | Legacy flattened object variations. |
relationVariations | array | Legacy flattened relation variations. |
logicVariations | array | Legacy flattened logic variations. |
variables
This section controls token delimiters and fixed token values.
| Key | Type | Notes |
|---|---|---|
variables.variableDelimiter | string | Opening delimiter for tokens. Default: $. With the default, a token looks like $Vehicle$. |
variables.variableDelimiterEnd | string | Optional closing delimiter when start and end should differ. For example, "{%" and "%}". |
variables.values | object | Fixed token values that are available during individualization, independent of selected variations. |
solutionDeletion
This section removes solution-only content before repositories are distributed.
| Key | Type | Notes |
|---|---|---|
solutionDeletion.enabled | boolean | Enables solution deletion. Default: false. |
solutionDeletion.files | array of strings | Repository-relative files to remove completely. When deletion is enabled, configure at least one entry in files or directories. |
solutionDeletion.directories | array of strings | Repository-relative directories to remove completely. When deletion is enabled, configure at least one entry in files or directories. |
solutionDeletion.deleteFileKey | string | Marker that removes a whole file when found in its content. Default: // DELETEFILE. |
solutionDeletion.deleteParagraphKey | string | Marker used for paragraph-level solution removal. Default: DELETE. |
solutionDeletion.replaceMap | object | Literal replacement map applied during solution deletion. |
warnings
This section controls warnings for unresolved tokens and leftover variation values.
| Key | Type | Notes |
|---|---|---|
warnings.enabled | boolean | Enables warning checks. Default: false. |
warnings.ignore | array of strings | Ignore patterns for warning checks. Required when warnings are enabled. |
warnings.variationResidues | object | Optional rules for leftover variation-value warnings. |
warnings.variationResidues.typeWhiteList | array of strings | File extensions to inspect, without leading dots. When set, include every extension that should still be scanned. |
warnings.variationResidues.ignoreList | array of strings | Global residue values or surrounding fragments to suppress. |
warnings.variationResidues.matchMode | string | Matching mode for residue detection: substring, word, or identifierPart. Default: substring. |
warnings.variationResidues.ignoreRules | array | Path-specific or mode-specific suppression rules. |
warnings.variationResidues.ignoreRules[].paths | array of strings | Optional repository-relative path patterns where the rule applies. Omit for a global rule. |
warnings.variationResidues.ignoreRules[].values | array of strings | Residue values to suppress for this rule. Must not be empty. |
warnings.variationResidues.ignoreRules[].matchMode | string | Matching mode for this rule. Supports substring, word, identifierPart, and regex. |
fileManipulation
This section controls target-specific file and directory markers.
| Key | Type | Notes |
|---|---|---|
fileManipulation.filePreIdentifier | string | Prefix used when building target markers. Default: _. |
fileManipulation.filePostIdentifier | string | Suffix used when building target markers. Default: repo. |
fileManipulation.noRepoIdentifier | string | Middle part used for the exclude-from-all marker. Default: no. |
With the default values
{
"filePreIdentifier": "_",
"filePostIdentifier": "repo",
"noRepoIdentifier": "no"
}
these built-in defaults produce the markers below. You only need to write
fileManipulation when you want to override them.
the resulting markers are:
_workrepo: include only for targetwork_evalrepo: include only for targeteval_norepo: exclude from all generated repositories
The marker is removed from the final exported path.
Examples:
src/tests_evalrepo/HiddenTests.java -> src/tests/HiddenTests.java (eval only)
docs/teacher_workrepo.md -> docs/teacher.md (work only)
assets/_norepo/logo.svg -> excluded everywhere
Legacy compatibility:
_mainrepoand_coderepoare still accepted and map towork_testrepois still accepted and maps toeval- older
sandboxterminology may still appear in existing repositories, butevalis the canonical target name
processors
This section configures built-in artifact processors that run during individualization.
| Key | Type | Notes |
|---|---|---|
processors.uml | object | UML source/image processor configuration. |
processors.uml.mode | string | off, source, image, or both. Default: both. |
processors.uml.imageFormat | string | Output format for rendered UML images. Default: jpg. |
processors.tableHash | object | Optional naming patterns for hashed solution table artifacts. |
processors.tableHash.solutionTableFileName | string | Eval solution table filename pattern. Default: ${id}.solution.md. |
processors.tableHash.hashedSolutionTableFileName | string | Work hashed table filename pattern. Default: ${id}.hashed.md. |
processors.tableHash.tableConfigFileName | string | Table config filename pattern. Default: ${id}.config.json. |
Currently supported:
{
"processors": {
"uml": {
"mode": "both",
"imageFormat": "jpg"
},
"tableHash": {
"solutionTableFileName": "${id}.solution.md",
"hashedSolutionTableFileName": "${id}.hashed.md",
"tableConfigFileName": "${id}.config.json"
}
}
}
processors.uml
UML processing applies to .uxf and .uml files.
Default behavior:
- the individualized source UML file is kept
- an additional rendered image is emitted
- the default image format is
jpg
Supported keys:
| Key | Type | Notes |
|---|---|---|
processors.uml.mode | string | off, source, image, or both. Default: both. |
processors.uml.imageFormat | string | Output format for rendered images. Default: jpg. |
Supported modes:
off: disables UML-specific artifact generation; the individualized source file remainssource: keeps only the individualized UML source fileimage: emits only the rendered image artifactboth: keeps the individualized UML source file and emits the rendered image artifact
Target markers from fileManipulation also apply to UML files. After marker
removal, Divekit uses the cleaned path for every emitted UML artifact.
Examples with default settings:
docs/test1_evalrepo.uxf -> eval only: docs/test1.uxf + docs/test1.jpg
docs/test2_workrepo.uxf -> work only: docs/test2.uxf + docs/test2.jpg
docs/test3.uxf -> both targets: docs/test3.uxf + docs/test3.jpg
Rendering modes image and both require UMLet to be available on the
machine running Divekit.
processors.tableHash
Table hashing generates work-repository hash artifacts from eval-repository solution tables. It is useful when students fill Markdown table cells and tests should compare hashed expected values.
With the default naming convention, author these files:
src/main/resources/E1.md
src/test/resources/E1.solution_evalrepo.md
src/test/resources/E1.config.json
After target markers are resolved, Divekit reads E1.solution.md from the eval
target, reads E1.config.json, and writes E1.hashed.md to the work target.
This happens during divekit distribute and during file patches that affect the
related work/eval repositories.
The ${id} placeholder is captured from the solution table file name and reused
for the hashed output and config file names. Configure this section only when
the default dot-suffix convention does not match your project:
{
"processors": {
"tableHash": {
"solutionTableFileName": "E${id}-solution_testrepo.md",
"hashedSolutionTableFileName": "E${id}-hashed-solution.md",
"tableConfigFileName": "E${id}-config.json"
}
}
}
Table config files are separate from individualization.json and are resolved
next to the solution table by default:
{
"tableType": "ROWS_AND_COLUMNS",
"explanationDimensions": ["Question"],
"validRowValues": [],
"validColumnValues": ["Question", "Answer"],
"validCellValues": [],
"hashedColumns": [false, true],
"showRowHints": true,
"showColumnHints": true
}
| Key | Type | Notes |
|---|---|---|
tableType | string | Optional legacy table mode. Use ROWS_AND_COLUMNS for question/answer tables where the first Markdown column identifies the row. |
explanationDimensions | array of strings | Row or column names whose cell values are explanatory and are not checked against validCellValues. |
validRowValues | array of strings | Optional case-insensitive allow-list for row labels. An empty list accepts all rows. |
validColumnValues | array of strings | Optional case-insensitive allow-list for column labels. An empty list accepts all columns. |
validCellValues | array of strings | Optional case-insensitive allow-list for comma-separated cell values. An empty list accepts all values. |
hashedColumns | array of booleans | Marks columns whose cell values are replaced with SHA-256 hashes. |
caseSensitiveColumns | array of booleans | Preserves case before hashing for marked columns. Missing entries default to false, so hashed values are lowercased by default. |
caseInsensitiveColumns | array of booleans | Compatibility alias for explicitly lowercasing marked columns when caseSensitiveColumns is not set. Prefer caseSensitiveColumns for Java test-library compatibility. |
trimCells | boolean | Trims leading and trailing cell whitespace before hashing. Default: true. |
showRowHints | boolean | Legacy test-library hint setting. Stored for compatibility with existing configs. |
showColumnHints | boolean | Legacy test-library hint setting. Stored for compatibility with existing configs. |
Columns are zero-based by position in the Markdown table. For
ROWS_AND_COLUMNS, index 0 is the row-label column and the first answer
column is index 1, matching the legacy Java table config. Unlisted positions
are treated as false.
Before hashing, Divekit trims each comma-separated cell value, removes empty
values, sorts the remaining values case-insensitively, joins them with commas,
and lowercases the joined value unless caseSensitiveColumns marks that column
as true.
relations
This section stores explicit object-relation metadata.
| Key | Type | Notes |
|---|---|---|
relations.objectRelations | array | Relation entries between configured objects. |
relations.objectRelations[].sourceType | string | Type of the source object. |
relations.objectRelations[].sourceName | string | Name of the source object. |
relations.objectRelations[].targetType | string | Type of the target object. |
relations.objectRelations[].targetName | string | Name of the target object. |
relations.objectRelations[].type | string | Relation type. |
variableExtensions
This section customizes generated token names and transformation behavior.
| Key | Type | Notes |
|---|---|---|
variableExtensions.prefixes | object | Maps token names or variation fields to prefixes. |
variableExtensions.suffixes | object | Maps token names or variation fields to suffixes. |
variableExtensions.transformations | object | Maps token names or variation fields to named transformations. |
variations
This section is the unified compatibility container for variation definitions.
New standalone variation definitions usually belong in variation.json; keep
inline variations only when you need compatibility with an existing setup.
| Key | Type | Notes |
|---|---|---|
variations.objects | array | Object-level choices. |
variations.objects[].id | string | Canonical object ID used to build tokens. |
variations.objects[].aliases | array of strings | Additional object IDs accepted as aliases. |
variations.objects[].kinds | array | Canonical list of object variations. |
variations.objects[].ids | string | Legacy comma-separated object IDs. The first value becomes id; remaining values become aliases. |
variations.objects[].objectVariations | array | Legacy name for kinds. Still accepted on read. |
variations.objects[].kinds[].id | string | Variation option ID. |
variations.objects[].kinds[].type | string | Object type, for example class or method. |
variations.objects[].kinds[].name | string | Human-readable object name. |
variations.objects[].kinds[].properties | object | Optional object properties that can vary. |
variations.objects[].kinds[].variables | object | Token values contributed when this variation is selected. |
variations.relations | array | Relation-level choices. |
variations.relations[].id | string | Relation variation ID. |
variations.relations[].type | string | Relation type. |
variations.relations[].source | string | Source object ID. |
variations.relations[].target | string | Target object ID. |
variations.relations[].options | array of strings | Selectable relation options. |
variations.relations[].variables | object | Token values contributed by the relation variation. |
variations.logic | array | Logic-level choices. |
variations.logic[].id | string | Logic variation ID. |
variations.logic[].type | string | Logic type, for example algorithm or condition. |
variations.logic[].location | string | Location where the logic variation applies. |
variations.logic[].options | array | Selectable logic options. Options may be strings or objects with an id and custom fields. |
variations.logic[].variables | object | Token values contributed by the logic variation. |
Validation Notes
variables.variableDelimitermust not be empty.- If
solutionDeletion.enabledistrue, at least one file or directory must be configured. - If
warnings.enabledistrue,warnings.ignoremust be present. warnings.variationResidues.ignoreRules[].valuesmust not be empty.warnings.variationResidues.matchModemust besubstring,word, oridentifierPart.warnings.variationResidues.ignoreRules[].matchModemay additionally beregex.processors.uml.modemust beoff,source,image, orboth.processors.uml.imageFormatmust not be empty when image output is enabled.
warnings.variationResidues
Use this block to suppress leftover variation values that still appear after
sample individualization, and to control the matching rules that also help
divekit dev avoid related unresolved-token false positives.
Matching modes:
substring: matches anywhere, including inside larger identifiersword: matches only whole wordsidentifierPart: matches identifier parts such asDishinsideovenDish
typeWhiteList should contain the complete set of file types you want Divekit
to inspect. If you set it explicitly, include every extension you still want to
scan, for example ["java", "md", "json"].
ignoreList is global. Entries may suppress either the residue value itself
(for example Dish) or the surrounding word, identifier, or path fragment
that produced the match (for example Feedback or coffee for a Fee
residue hit).
ignoreRules can be path-specific, or global when paths is omitted. Each
rule must list the values it suppresses.
Example:
{
"warnings": {
"variationResidues": {
"ignoreList": ["Dish", "Feedback", "coffee"],
"ignoreRules": [
{
"paths": ["src/generated/**"],
"values": ["GeneratedDish"]
}
]
}
}
}
Legacy compatibility:
variationResiduesis the canonical keyvariationResidueWarningsis still accepted on readvariableValueWarningsis deprecated and still accepted on read for backwards compatibility
Resolution Order
Divekit resolves unified individualization.json in this order:
.divekit/distributions/<distribution>/individualization.json.divekit/individualization.json~/.divekit/individualization.json- built-in defaults
Variation definitions use a more detailed fallback because legacy
variation.json files are still supported:
- distribution
individualization.json - distribution
variation.json - project
.divekit/individualization.json - project
.divekit/variation.json - user
~/.divekit/individualization.json - built-in defaults with no variations
If variations is omitted, Divekit continues to the next source. Set it to an
empty object to disable variations and stop fallback resolution:
{
"version": "2.0",
"variations": {}
}
Legacy Compatibility
Divekit still contains compatibility loading for these older files:
originRepositoryConfig.jsonvariationsConfig.jsonrelationsConfig.jsonvariableExtensionsConfig.json
For new setups, prefer a single individualization.json.
Scripting Clarification
Lua, shell, Python, Node, Deno, Java, and Kotlin execution belong to scripting and extensions, not to dedicated individualization.json keys.
Related pages: