The primary use of configlet is linting: checking if a track's configuration files are properly structured - both syntactically and semantically. Misconfigured tracks may not sync correctly, may look wrong on the website, or may present a suboptimal user experience, so configlet's guards play an important part in maintaining the integrity of Exercism.
The lint command can be used to lint a track.
configlet [global-options] lint [command-options]
Global options:
-h, --help Show this help message and exit
--version Show this tool's version information and exit
-t, --track-dir <dir> Specify a track directory to use instead of the current directory
-v, --verbosity <verbosity> The verbosity of output. Allowed values: q[uiet], n[ormal], d[etailed]
These are the linting rules being checked.
The linter should check if all the required files are present. The non-exercise specific files that must be present are:
config.jsondocs/ABOUT.mddocs/INSTALLATION.mddocs/LEARNING.mddocs/RESOURCES.mddocs/SNIPPET.txtdocs/TESTS.mdexercises/shared/.docs/help.mdexercises/shared/.docs/tests.md
The Concept Exercise specific files that must be present are:
exercises/concept/<slug>/.docs/hints.mdexercises/concept/<slug>/.docs/instructions.mdexercises/concept/<slug>/.docs/introduction.mdexercises/concept/<slug>/.meta/config.json
There will be a similar list for Practice Exercises, but we've not yet defined the spec for that.
Each concept listed in the config.json should have the following files:
concepts/<slug>/about.mdconcepts/<slug>/introduction.mdconcepts/<slug>/links.json
The config.json file should have the following checks:
- The file must be valid JSON
- The
"language"key is required - The
"language"value must be a non-blank string¹ with length <= 255 - The
"slug"key is required - The
"slug"value must be a kebab-case string² with length <= 255 - The
"active"key is required - The
"active"value must be a boolean - The
"blurb"key is required - The
"blurb"value must be a non-blank string¹ with length <= 400 - The
"version"key is required - The
"version"value must be the integer3 - The
"status.concept_exercises"key is required - The
"status.concept_exercises"value must be a boolean - The
"status.test_runner"key is required - The
"status.test_runner"value must be a boolean - The
"status.representer"key is required - The
"status.representer"value must be a boolean - The
"status.analyzer"key is required - The
"status.analyzer"value must be a boolean - The
"online_editor.indent_style"key is required - The
"online_editor.indent_style"value must be the stringspaceortab - The
"online_editor.indent_size"key is required - The
"online_editor.indent_size"value must be an integer >= 0 and <= 8 - The
"online_editor.highlightjs_language"key is optional - The
"online_editor.highlightjs_language"value must be a non-blank string¹ - The
"files"key is optional - The
"files"value must be an object - The
"files.solution"key is optional - The
"files.solution"value must be an array - The
"files.solution"values must be valid patterns⁵ - The
"files.solution"values must not have duplicates - The
"files.test"key is optional - The
"files.test"value must be an array - The
"files.test"values must be valid patterns⁵ - The
"files.test"values must not have duplicates - The
"files.example"key is optional - The
"files.example"value must be an array - The
"files.example"values must be valid patterns⁵ - The
"files.example"values must not have duplicates - The
"files.exemplar"key is optional - The
"files.exemplar"value must be an array - The
"files.exemplar"values must be valid patterns⁵ - The
"files.exemplar"values must not have duplicates - The
"files.editor"key is optional - The
"files.editor"value must be an array - The
"files.editor"values must be valid patterns⁵ - The
"files.editor"values must not have duplicates - The
"files.invalidator"key is optional - The
"files.invalidator"value must be an array - The
"files.invalidator"values must be valid patterns⁵ - The
"files.invalidator"values must not have duplicates - Patterns can only be listed in either the
"files.solution","files.test","files.example","files.exemplar","files.editor"or"files.invalidator"array (no overlap)- If the track is
dorplsql, the"files.solution"and"files.test"files can overlap - The
"files.exampleand"files.exemplar"files can overlap
- If the track is
- The
"test_runner.average_run_time"key is required if"status.test_runner"is equal totrue - The
"test_runner.average_run_time"value must be an integer > 0 - The
"approaches.snippet_extension"key is required if the track has one or more approaches - The
"approaches.snippet_extension"value must be a non-blank string¹ - The
"exercises"key is required - The
"exercises.concept"key is required - The
"exercises.concept"value must be an array - The
"exercises.concept[].slug"key is required - The
"exercises.concept[].slug"value must be a kebab-case string² with length <= 255 - The
"exercises.concept[].slug"value must be unique in"exercises.concept[].slug"and may not exist in"exercises.practice[].slug" - The
"exercises.concept[].name"key is required - The
"exercises.concept[].name"value must be a Title Case string³ with length <= 255 - The
"exercises.concept[].uuid"key is required - The
"exercises.concept[].uuid"value must be a unique version 4 UUID string⁶ - The
"exercises.concept[].uuid"value for each exercise must never change - The
"exercises.concept[].concepts"key is required - The
"exercises.concept[].concepts"value must be a non-empty array of strings if"exercises.concept[].status"is not equal todeprecated - The
"exercises.concept[].concepts"value must be an empty array if"exercises.concept[].status"is equal todeprecated - The
"exercises.concept[].concepts"values must be kebab-case strings² - The
"exercises.concept[].concepts"values must not have duplicates - The
"exercises.concept[].concepts"values must not be in any other concept exercise's"concepts"property - The
"exercises.concept[].concepts"values must match the"concepts.slug"property of one of the concepts - The
"exercises.concept[].prerequisites"key is required - The
"exercises.concept[].prerequisites"value must be a non-empty array of strings if"exercises.concept[].status"is not equal todeprecated, except for exactly one exercise which is allowed to have an empty array as its value - The
"exercises.concept[].prerequisites"value must be an empty array if"exercises.concept[].status"is equal todeprecated - The
"exercises.concept[].prerequisites"values must be kebab-case strings² - The
"exercises.concept[].prerequisites"values must not have duplicates - The
"exercises.concept[].prerequisites"values must match any other concept exercise's"concepts"property values - The
"exercises.concept[].prerequisites"values must not match any of the values in the exercise's"exercises.concept[].concepts"property - The
"exercises.concept[].prerequisites"values must match the"concepts.slug"property of one of the concepts - There must not be any cycles between
"exercises.concept[].concepts"and"exercises.concept[].prerequisites" - The
"exercises.concept[].status"key is optional - The
"exercises.concept[].status"value must be the stringwip,beta,activeordeprecated - The
"exercises.practice"key is required - The
"exercises.practice"value must be an array - The
"exercises.practice[].slug"key is required - The
"exercises.practice[].slug"value must be a kebab-case string² with length <= 255 - The
"exercises.practice[].slug"value must be unique in"exercises.practice[].slug"and may not exist in"exercises.concept[].slug" - There must be exactly one
"exercises.practice[].slug"value that is the stringhello-world - The
"exercises.practice[].name"key is required - The
"exercises.practice[].name"value must be a Title Case string³ with length <= 255 - The
"exercises.practice[].uuid"key is required - The
"exercises.practice[].uuid"value must be a unique version 4 UUID string⁶ - The
"exercises.practice[].uuid"value for each exercise must never change - The
"exercises.practice[].difficulty"key is required - The
"exercises.practice[].difficulty"value must be an integer >= 1 and <= 10 - The
"exercises.practice[].practices"key is required - The
"exercises.practice[].practices"value must be a non-empty array of strings if"exercises.practice[].status"is not equal todeprecated - The
"exercises.practice[].practices"value must be an empty array if"exercises.practice[].status"is equal todeprecated - The
"exercises.practice[].practices"values must be kebab-case strings² - The
"exercises.practice[].practices"values must not have duplicates - The
"exercises.practice[].practices"values must match the"concepts[].slug"property of one of the concepts - The
"exercises.practice[].practices"values must refer to an individual concept's slug at most 10 times (across all exercises) - The
"exercises.practice[].prerequisites"key is required - The
"exercises.practice[].prerequisites"value must be a non-empty array of strings if"exercises.practice[].status"is not equal todeprecated - The
"exercises.practice[].prerequisites"value must be an empty array if"exercises.practice[].status"is equal todeprecated - The
"exercises.practice[].prerequisites"value must be an empty array if"exercises.practice[].slug"is equal tohello-world - The
"exercises.practice[].prerequisites"values must be kebab-case strings² - The
"exercises.practice[].prerequisites"values must not have duplicates - The
"exercises.practice[].prerequisites"values must match any concept exercise's"exercises.concept[].concepts"values - The
"exercises.practice[].prerequisites"values must match the"concepts[].slug"property of one of the concepts - The
"exercises.practice[].status"key is optional - The
"exercises.practice[].status"value must be the stringwip,beta,activeordeprecated - The
"exercises.practice[].status"value must, if"exercises.practice[].slug"is equal tohello-world, be either omitted or the stringactive - The
"exercises.foregone"key is optional - The
"exercises.foregone"value must be an array - The
"exercises.foregone"values must be kebab-case strings² - The
"exercises.foregone"values must not have duplicates - The
"exercises.foregone"values must not match any of the concept or practice exercise slugs - The
"concepts"key is required - The
"concepts"value must be an array - The
"concepts[].uuid"key is required - The
"concepts[].uuid"value must be a unique version 4 UUID string⁶ - The
"concepts[].uuid"value for each concept must never change - The
"concepts[].slug"key is required - The
"concepts[].slug"value must be a kebab-case string² with length <= 255 - The
"concepts[].name"key is required - The
"concepts[].name"value must be a Title Case string³ with length <= 255 - The
"concepts[].tags"key is optional - The
"concepts[].tags.all"key is optional, unless"concepts[].tags.any"is empty - The
"concepts[].tags.all"value must be an array - The
"concepts[].tags.all"values must be non-blank tag⁷ strings with length <= 255 - The
"concepts[].tags.all"values must not have duplicates - The
"concepts[].tags.any"key is optional, unless"concepts[].tags.all"is empty - The
"concepts[].tags.any"value must be an array - The
"concepts[].tags.any"values must be non-blank tag⁷ strings with length <= 255 - The
"concepts[].tags.any"values must not have duplicates - The
"concepts[].tags.not"key is optional - The
"concepts[].tags.not"value must be an array - The
"concepts[].tags.not"values must be non-blank tag⁷ strings with length <= 255 - The
"concepts[].tags.not"values must not have duplicates - Each
"concepts"value must have aconcept/<concepts.slug>/about.mdfile. Linting rules for this file are specified below. - Each
"concepts"value must have aconcept/<concepts.slug>/introduction.mdfile. Linting rules for this file are specified below. - Each
"concepts"value must have aconcept/<concepts.slug>/links.jsonfile. Linting rules for this file are specified below. - The
"key_features"key is optional - The
"key_features"value must be an array with length = 6 - The
"key_features[].icon"key is required - The
"key_features[].icon"value must use one of the pre-defined icon values - The
"key_features[].title"key is required - The
"key_features[].title"value must be a Sentence Case string⁴ with length <= 25 - The
"key_features[].content"key is required - The
"key_features[].content"value must be a non-blank string¹ with length <= 100 - The
"tags"key is required - The
"tags"value must be an array of strings - The
"tags"values must not have duplicates - The
"tags"values must use one of the pre-defined tag values
- The file must be valid JSON
- The JSON root must be an object
- The
"blurb"key is required - The
"blurb"value must be a non-blank string¹ with length <= 350 - The
"source"key is optional - The
"source"value must be a non-blank string¹ - The
"source_url"key is optional - The
"source_url"value must be a URL - The
"authors"key is required - The
"authors"value must be a non-empty array - The
"authors"values must be non-blank strings¹ - The
"authors"values must not have duplicates - The
"authors"values are treated case-insensitively - The
"contributors"key is optional - The
"contributors"value must be an array - The
"contributors"values must be non-blank strings¹ - The
"contributors"values must not have duplicates - The
"contributors"values are treated case-insensitively - Users can only be listed in either the
"authors"or"contributors"array (no overlap) - The
"files.solution"key is required - The
"files.solution"value must be a non-empty array - The
"files.solution"values must not have duplicates - The
"files.test"key is required - The
"files.test"value must be a non-empty array - The
"files.test"values must not have duplicates - The
"files.exemplar"key is required - The
"files.exemplar"value must be a non-empty array - The
"files.exemplar"values must not have duplicates - The
"files.editor"key is optional - The
"files.editor"value must be an array - The
"files.editor"values must not have duplicates - The
"files.invalidator"key is optional - The
"files.invalidator"value must be an array - The
"files.invalidator"values must not have duplicates - The files listed in the
"files.solution"must exist - The files listed in the
"files.test"must exist - The files listed in the
"files.exemplar"must exist - The files listed in the
"files.editor"must exist - The files listed in the
"files.invalidator"must exist - Files can only be listed in either the
"files.solution","files.test","files.exemplar"or"files.invalidator"array (no overlap)- If the track is
dorplsql, the"files.solution"and"files.test"files can overlap
- If the track is
- The
"forked_from"key is optional - The
"forked_from"value must be an array - The
"forked_from"values must be strings formatted as<track-slug>/<exercise-slug>(e.g.fsharp/bird-watcher) - The
"forked_from"values must refer to actually implemented exercises - The
"forked_from"values must not have duplicates - The
"language_versions"key is optional - The
"language_versions"value must be a string - The
"representer.version"key is optional - The
"representer.version"value must be an integer >= 1 - The
"icon"key is optional - The
"icon"value must be a kebab-case string²
- The Markdown must conform to the Markdown standards
- All headings must be either
## Generalor## X. <task>whereXmatches the task number heading in theinstructions.md - All hints must be specified as Markdown list items
- Links must be absolute (relative links are not allowed)
- The Markdown must conform to the Markdown standards
- All tasks must start with a level two heading that starts with a number followed by a dot:
## 1. Do X - Links must be absolute (relative links are not allowed)
- Each concept placeholders's concept must match the
"concepts.slug"property of one of the concepts in the track'sconfig.json.
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The file must be valid JSON
- The JSON root must be an object
- The
"blurb"key is required - The
"blurb"value must be a non-blank string¹ with length <= 350 - The
"source"key is optional - The
"source"value must be a non-blank string¹ - The
"source_url"key is optional - The
"source_url"value must be a URL - The
"authors"key is optional - The
"authors"value must be an array - The
"authors"values must be non-blank strings¹ - The
"authors"values must not have duplicates - The
"authors"values are treated case-insensitively - The
"contributors"key is optional - The
"contributors"value must be an array - The
"contributors"values must be non-blank strings¹ - The
"contributors"values must not have duplicates - The
"contributors"values are treated case-insensitively - Users can only be listed in either the
"authors"or"contributors"array (no overlap) - The
"files.solution"key is required - The
"files.solution"value must be a non-empty array - The
"files.solution"values must not have duplicates - The
"files.test"key is required - The
"files.test"value must be a non-empty array - The
"files.test"values must not have duplicates - The
"files.example"key is required - The
"files.example"value must be a non-empty array - The
"files.example"values must not have duplicates - The
"files.editor"key is optional - The
"files.editor"value must be an array - The
"files.editor"values must not have duplicates - The
"files.invalidator"key is optional - The
"files.invalidator"value must be an array - The
"files.invalidator"values must not have duplicates - The files listed in the
"files.solution"must exist - The files listed in the
"files.test"must exist - The files listed in the
"files.example"must exist - The files listed in the
"files.editor"must exist - The files listed in the
"files.invalidator"must exist - Files can only be listed in either the
"files.solution","files.test","files.exampleor"files.invalidator"array (no overlap)- If the track is
dorplsql, the"files.solution"and"files.test"files can overlap
- If the track is
- The
"language_versions"key is optional - The
"language_versions"value must be a string - The
"test_runner"key is optional - The
"test_runner"value must be a boolean - The
"representer.version"key is optional - The
"representer.version"value must be an integer >= 1 - The
"icon"key is optional - The
"icon"value must be a kebab-case string²
- The file's presence is optional, unless there is a
introduction.mdor a sibling directory - The file must be valid JSON
- The JSON root must be an object
- The
"introduction.authors"key is optional - The
"introduction.authors"value must be an array - The
"introduction.authors"values must be non-blank strings¹ - The
"introduction.authors"values must not have duplicates - The
"introduction.authors"values are treated case-insensitively - If the
"introduction.authors"array is non-empty, there must be a non-emptyintroduction.mdfile - The
"introduction.contributors"key is optional - The
"introduction.contributors"value must be an array - The
"introduction.contributors"values must be non-blank strings¹ - The
"introduction.contributors"values must not have duplicates - The
"introduction.contributors"values are treated case-insensitively - If the
"introduction.contributors"array is non-empty, there must be a non-emptyintroduction.mdfile - Users can only be listed in either the
"introduction.authors"or"introduction.contributors"array (no overlap) - The
"approaches"key is optional, unless there is a sibling directory present (which contains the approach' files) - The
"approaches"value must be an array of objects - The
"approaches[].uuid"key is required - The
"approaches[].uuid"value must be a unique version 4 UUID string⁶ - The
"approaches[].uuid"value for each concept must never change - The
"approaches[].slug"key is required - The
"approaches[].slug"value must be a kebab-case string² with length <= 255 - The
"approaches[].slug"value must have a corresponding non-empty<slug>/content.mdfile - The
"approaches[].slug"value must have a corresponding non-empty<slug>/snippet.txtfile - The
"approaches[].title"key is required - The
"approaches[].title"value must be a Title Case string³ with length <= 255 - The
"approaches[].blurb"key is required - The
"approaches[].blurb"value must be a non-blank string¹ with length <= 350 - The
"approaches[].authors"key is required - The
"approaches[].authors"value must be a non-empty array - The
"approaches[].authors"values must be non-blank strings¹ - The
"approaches[].authors"values must not have duplicates - The
"approaches[].authors"values are treated case-insensitively - The
"approaches[].contributors"key is optional - The
"approaches[].contributors"value must be an array - The
"approaches[].contributors"values must be non-blank strings¹ - The
"approaches[].contributors"values must not have duplicates - The
"approaches[].contributors"values are treated case-insensitively - Users can only be listed in either the
"approaches[].authors"or"approaches[].contributors"array (no overlap) - The
"approaches[].tags"key is optional - The
"approaches[].tags.all"key is optional, unless"approaches[].tags.any"is empty - The
"approaches[].tags.all"value must be an array - The
"approaches[].tags.all"values must be non-blank tag⁷ strings with length <= 255 - The
"approaches[].tags.all"values must not have duplicates - The
"approaches[].tags.any"key is optional, unless"approaches[].tags.all"is empty - The
"approaches[].tags.any"value must be an array - The
"approaches[].tags.any"values must be non-blank tag⁷ strings with length <= 255 - The
"approaches[].tags.any"values must not have duplicates - The
"approaches[].tags.not"key is optional - The
"approaches[].tags.not"value must be an array - The
"approaches[].tags.not"values must be non-blank tag⁷ strings with length <= 255 - The
"approaches[].tags.not"values must not have duplicates
- The file's presence is required if a matching
"approaches[].slug"entry exists in the.approaches/config.jsonfile - The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
Rule: exercises/{concept|practice}/<slug>/.approaches/<approach-slug>/snippet.<snippet-extension> is valid
- The file's presence is required if a matching
"approaches[].slug"entry exists in the.approaches/config.jsonfile - The snippet must have at most 8 lines
- The snippet extension is taken from the
approaches.snippet_extensionvalue in the track'sconfig.jsonfile
- The file's presence is optional, unless there is a sibling directory
- The file must be valid JSON
- The JSON root must be an object
- The
"articles"key is optional, unless there is a sibling directory present (which contains the article' files) - The
"articles"value must be an array of objects - The
"articles[].uuid"key is required - The
"articles[].uuid"value must be a unique version 4 UUID string⁶ - The
"articles[].uuid"value for each concept must never change - The
"articles[].slug"key is required - The
"articles[].slug"value must be a kebab-case string² with length <= 255 - The
"articles[].slug"value must have a corresponding non-empty<slug>/content.mdfile - The
"articles[].slug"value must have a corresponding non-empty<slug>/snippet.mdfile - The
"articles[].title"key is required - The
"articles[].title"value must be a Title Case string³ with length <= 255 - The
"articles[].blurb"key is required - The
"articles[].blurb"value must be a non-blank string¹ with length <= 350 - The
"articles[].authors"key is required - The
"articles[].authors"value must be a non-empty array - The
"articles[].authors"values must be non-blank strings¹ - The
"articles[].authors"values must not have duplicates - The
"articles[].authors"values are treated case-insensitively - The
"articles[].contributors"key is optional - The
"articles[].contributors"value must be an array - The
"articles[].contributors"values must be non-blank strings¹ - The
"articles[].contributors"values must not have duplicates - The
"articles[].contributors"values are treated case-insensitively - Users can only be listed in either the
"articles[].authors"or"articles[].contributors"array (no overlap)
- The file's presence is required if a matching
"articles[].slug"entry exists in the.articles/config.jsonfile - The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The file's presence is required if a matching
"articles[].slug"entry exists in the.articles/config.jsonfile - The Markdown must conform to the Markdown standards
- The snippet must have at most 8 lines (leading and trailing code fence markers are ignored)
- The file's presence is optional
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The file's presence is required
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The file's presence is required
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The file must be valid JSON
- The JSON root must be an array
- The
"[].url"property is required - The
"[].url"value must be an URL - The
"[].description"property is required - The
"[].description"value must be a non-blank string¹ - The
"[].icon_url"property is optional - The
"[].icon_url"value must be an URL
- The file must be valid JSON
- The JSON root must be an object
- The
"blurb"key is required - The
"blurb"value must be a non-blank string¹ with length <= 350 - The
"authors"key is required - The
"authors"value must be an array - The
"authors"values must be non-blank strings¹ - The
"authors"values must not have duplicates - The
"authors"values are treated case-insensitively - The
"contributors"key is optional - The
"contributors"value must be an array - The
"contributors"values must be non-blank strings¹ - The
"contributors"values must not have duplicates - The
"contributors"values are treated case-insensitively - Users can only be listed in either the
"authors"or"contributors"array (no overlap)
- The file's presence is required
- The file's contents must be non-blank
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The file's presence is required
- The file's contents must be non-blank
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The file's presence is required
- The file's contents must be non-blank
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The file's presence is required
- The file's contents must be non-blank
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
- The file's presence is required
- The file's contents must be non-blank
- The file's presence is required
- The file's contents must be non-blank
- The Markdown must conform to the Markdown standards
- Links must be absolute (relative links are not allowed)
-
Non-blank string: a string that contains at least one non-whitespace character.
-
kebab-case string: a string that contains only characters in the range
[a-z0-9], optionally separated by dashes (e.g. "two-fer"). It must match the regular expression:^[a-z0-9]+(-[a-z0-9]+)*$ -
Title Case string: a non-blank string that follows the below guidelines from the Chicago Manual of Style:
- Capitalize the first and last words of titles and subtitles.
- Capitalize "major" words (nouns, pronouns, verbs, adjectives, adverbs, and some conjunctions).
- Lowercase the conjunctions and, but, for, or, and nor.
- Lowercase the articles the, a, and an.
- Lowercase prepositions, regardless of length, except when they are stressed, are used adverbially or adjectivally, or are used as conjunctions.
- Lowercase the words to and as.
- Lowercase the second part of Latin species names.
-
Sentence Case string: a non-blank string that follows the below guidelines:
- Capitalize the first word of the sentence, as well as proper nouns and other words as required by a more specific rule.
-
Valid
filespattern: A non-blank string¹ that specifies a location of a file used in an exercise, relative to the exercise's directory. A pattern may use one of the following placeholders:%{kebab_slug}: thekebab-caseexercise slug (e.g.bit-manipulation)%{snake_slug}: thesnake_caseexercise slug (e.g.bit_manipulation)%{camel_slug}: thecamelCaseexercise slug (e.g.bitManipulation)%{pascal_slug}: thePascalCaseexercise slug (e.g.BitManipulation)
-
Unique version 4 UUID string: A string that satisfies all of these conditions:
- It only exists once in the track-level
config.jsonfile of a given Exercism track - It does not exist in the track-level
config.jsonfile of any other Exercism track - It does not exist in any
canonical-data.jsonfile in https://github.com/exercism/problem-specifications - It does not exist anywhere else on Exercism
- It matches the regular expression:
^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$For example, the below UUID has the correct form:
d334ffe3-657e-4725-a950-290b284b6d9fYou can run
configlet uuidto generate a suitable UUID. - It only exists once in the track-level
-
Valid analyzer
tag: A non-blank string¹ that is formatted as<category>:<thing>. The<category>value must be one of:
paradigm(e.g.paradigm:functional)technique(e.g.technique:recursion)construct(e.g.construct:bitwise-and)uses(e.g.uses:DateTime.add_seconds)
The <thing> value must a non-blank string¹.