shikumi-devdoc 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- shikumi_devdoc-0.1.0/.gitignore +18 -0
- shikumi_devdoc-0.1.0/CHANGELOG.md +36 -0
- shikumi_devdoc-0.1.0/LICENSE +21 -0
- shikumi_devdoc-0.1.0/PKG-INFO +442 -0
- shikumi_devdoc-0.1.0/README.md +425 -0
- shikumi_devdoc-0.1.0/pyproject.toml +49 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/__init__.py +23 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/_placeholder_syntax.py +124 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/cli.py +278 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/context.py +97 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/norms/__init__.py +19 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/norms/changelog.py +624 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/norms/common.py +147 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/norms/document.py +263 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/norms/vocabulary.py +350 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/realizers/__init__.py +23 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/realizers/_header_comment.py +13 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/realizers/_placeholders.py +87 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/realizers/changelog_markdown.py +131 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/realizers/document_markdown.py +267 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/realizers/glossary_markdown.py +92 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/realizers/translation_source.py +149 -0
- shikumi_devdoc-0.1.0/src/shikumi_devdoc/realizers/vocabulary_reference_python.py +128 -0
- shikumi_devdoc-0.1.0/tests/__init__.py +0 -0
- shikumi_devdoc-0.1.0/tests/fixtures/__init__.py +0 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_invalid_semantics.py +34 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_partition_invalid/__init__.py +1 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_partition_invalid/canonical.py +7 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_partition_invalid/part_a.py +21 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_partition_invalid/part_b.py +21 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_partitioned/__init__.py +1 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_partitioned/a_legacy.py +13 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_partitioned/canonical.py +16 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_partitioned/z_recent.py +13 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_reference_mismatch.py +18 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_semantics.py +36 -0
- shikumi_devdoc-0.1.0/tests/fixtures/changelog_source.py +19 -0
- shikumi_devdoc-0.1.0/tests/fixtures/document_anchor_invalid.py +21 -0
- shikumi_devdoc-0.1.0/tests/fixtures/document_anchor_source.py +15 -0
- shikumi_devdoc-0.1.0/tests/fixtures/document_anchor_title_invalid.py +13 -0
- shikumi_devdoc-0.1.0/tests/fixtures/document_anchor_unknown.py +7 -0
- shikumi_devdoc-0.1.0/tests/fixtures/document_literal_placeholders.py +15 -0
- shikumi_devdoc-0.1.0/tests/fixtures/document_raw_heading.py +7 -0
- shikumi_devdoc-0.1.0/tests/fixtures/document_reference_mismatch.py +16 -0
- shikumi_devdoc-0.1.0/tests/fixtures/document_repeated_term.py +11 -0
- shikumi_devdoc-0.1.0/tests/fixtures/document_source.py +15 -0
- shikumi_devdoc-0.1.0/tests/fixtures/document_structural_markdown.py +38 -0
- shikumi_devdoc-0.1.0/tests/fixtures/plain_document_source.py +7 -0
- shikumi_devdoc-0.1.0/tests/fixtures/vocabulary_invalid_lifecycle.py +25 -0
- shikumi_devdoc-0.1.0/tests/fixtures/vocabulary_lifecycle.py +29 -0
- shikumi_devdoc-0.1.0/tests/fixtures/vocabulary_source.py +17 -0
- shikumi_devdoc-0.1.0/tests/fixtures/vocabulary_terms.py +38 -0
- shikumi_devdoc-0.1.0/tests/test_changelog.py +98 -0
- shikumi_devdoc-0.1.0/tests/test_cli.py +185 -0
- shikumi_devdoc-0.1.0/tests/test_context.py +40 -0
- shikumi_devdoc-0.1.0/tests/test_document.py +167 -0
- shikumi_devdoc-0.1.0/tests/test_glossary.py +64 -0
- shikumi_devdoc-0.1.0/tests/test_placeholders.py +28 -0
- shikumi_devdoc-0.1.0/tests/test_public_api.py +22 -0
- shikumi_devdoc-0.1.0/tests/test_repository_notice_settings.py +45 -0
- shikumi_devdoc-0.1.0/tests/test_translation_source.py +59 -0
- shikumi_devdoc-0.1.0/tests/test_vocabulary_reference_python.py +77 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# shikumi-devdoc Changelog
|
|
2
|
+
|
|
3
|
+
Changes included in public releases of `shikumi-devdoc` are recorded here.
|
|
4
|
+
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
Changes planned for the next public release.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Added repeatable Vocabulary `alias` metadata together with `deprecated` and `replacement`, allowing alternate names and deprecation relationships to be validated and rendered as semantic information.
|
|
12
|
+
- Added changelog `unreleased` and `breaking` semantics. An unreleased section is unique, leading, and undated; breaking entries retain their normal change category while being explicitly marked in Markdown.
|
|
13
|
+
- Added physical changelog partitioning with `@changelog_part(order=...)`, allowing release history to span multiple modules while remaining one logically ordered, globally validated changelog.
|
|
14
|
+
|
|
15
|
+
## 0.1.0 - 2026-09-13
|
|
16
|
+
|
|
17
|
+
First public release. It establishes the core facilities for describing, validating, and realizing developer documentation from Shikumi semantic information.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Added regulations for general documents, vocabularies, and changelogs, together with standard Markdown realizers for each.
|
|
22
|
+
- Added external information supplied to realizers, with reference markers in document text for project names, versions, and other values that have another canonical source.
|
|
23
|
+
- Added a CLI for generating term reference modules from a Vocabulary, allowing IDE navigation from `TERM_N` identifiers to human-readable term names and definitions.
|
|
24
|
+
- Added entity-local vocabulary references and validation that requires `TERM_N` markers in each entity to match that entity's own `vocabulary_refs` exactly.
|
|
25
|
+
- Added explicit canonical-source declaration with `@canonical` and support for caller-provided header comments in Markdown realizers.
|
|
26
|
+
- Added a dogfooding workflow that generates Japanese intermediate documents from canonical Python sources and publishes their English translations at the repository root.
|
|
27
|
+
- Added `TranslationSourceRealizer` and `render --translation-source` so translation-oriented intermediate Markdown can retain machine-readable metadata for `preserve_spelling` terms.
|
|
28
|
+
- Added stable document anchors with `anchor @= "..."` and semantic section references through `{{#anchor}}`. References are extracted automatically into `SectionReference` information, and validation rejects unknown references, duplicate anchors, and invalid anchor names.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- Renamed the vocabulary translation-policy information from `untranslatable` to `preserve_spelling` to clarify that it means keeping a term's spelling unchanged across translations, not that the term is inherently untranslatable.
|
|
33
|
+
- Consolidated the generation notice and LLM publication instructions into a single repository-local `notice.toml` value. Intermediate documents include it only when `render --notice` is specified explicitly; the CLI performs no implicit notice-file discovery. Removed the repository-specific `build_docs.py` and moved term-reference and intermediate-document generation to direct CLI commands.
|
|
34
|
+
- Changed `render --context` from external-context file inputs to one JSON object string representing the values at realization time. This separates comparatively stable operational text in `notice.toml` from variable snapshot data, and `_internal/document_source/README.md` now records the repository-local generation procedure.
|
|
35
|
+
- Unified placeholder lexing, added `\{{...}}` as an explicit literal escape, preserved `${{...}}` host-language syntax, and made vocabulary-reference validation use the same lexical rules.
|
|
36
|
+
- Improved CLI diagnostics with severity, diagnostic code, Python source location, and semantic subject, and added Markdown structural checks for raw body headings and heading depth beyond six levels.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 minoru_jp
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: shikumi-devdoc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Reusable Shikumi regulations and Markdown realizers for developer-facing project documents.
|
|
5
|
+
Author: minoru_jp
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: changelog,developer-documentation,docs-as-code,documentation-generation,llm
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Requires-Python: >=3.11
|
|
15
|
+
Requires-Dist: shikumi>=0.1.0
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# shikumi-devdoc
|
|
19
|
+
|
|
20
|
+
`shikumi-devdoc` is a Python library that uses [Shikumi](https://pypi.org/project/shikumi/) to provide regulations and realizers for describing, validating, and realizing public project documentation from semantic information.
|
|
21
|
+
|
|
22
|
+
Documents, vocabulary, and changelogs can be described with Python as their canonical source and realized as Markdown. Values that already have another canonical source, such as a project name or version, are supplied externally instead of being duplicated in document source code.
|
|
23
|
+
|
|
24
|
+
The current version is `0.1.0`. Python `>=3.11` is required.
|
|
25
|
+
|
|
26
|
+
## Purpose
|
|
27
|
+
|
|
28
|
+
`shikumi-devdoc` works with the semantic structure behind completed Markdown rather than treating the Markdown itself as the primary source.
|
|
29
|
+
|
|
30
|
+
The basic flow is:
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
Python description body
|
|
34
|
+
↓ interpretation and validation by Shikumi
|
|
35
|
+
SemanticView
|
|
36
|
+
↓ shikumi-devdoc realizer
|
|
37
|
+
Japanese Markdown
|
|
38
|
+
↓ translation when needed
|
|
39
|
+
Public documentation
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Keeping the canonical source in Python makes hierarchy, vocabulary references, change categories, and similar constraints mechanically verifiable. At the same time, generated Japanese Markdown can be committed as an intermediate document that people can inspect directly.
|
|
43
|
+
|
|
44
|
+
## Regulations and realizers
|
|
45
|
+
|
|
46
|
+
The initial release provides three documentation systems:
|
|
47
|
+
|
|
48
|
+
- **Documents**: general developer documentation with heading hierarchy and body text.
|
|
49
|
+
- **Vocabulary**: vocabulary sources with term names and definitions, with selective realization into a public glossary.
|
|
50
|
+
- **Changelogs**: structured release histories containing releases and change entries.
|
|
51
|
+
|
|
52
|
+
Standard Markdown realizers are provided for all three. Vocabulary can also be realized as a Python term-reference module so that developers can inspect the meaning of `TERM_N` identifiers through IDE navigation.
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
Install from PyPI with:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install shikumi-devdoc
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`shikumi-devdoc` depends on `shikumi`. Shikumi provides the semantic interpretation and validation foundation; this library builds developer-documentation regulations and realizers on top of it.
|
|
63
|
+
|
|
64
|
+
## Documents
|
|
65
|
+
|
|
66
|
+
A general document is described as a hierarchy of `TITLE_N` classes. The outermost entity is decorated with `@canonical` to state explicitly that the description body is the canonical source of the artifact.
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from shikumi_devdoc.norms.document import canonical, title
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@canonical
|
|
73
|
+
@title("Example")
|
|
74
|
+
class TITLE_1:
|
|
75
|
+
r'''Project overview.'''
|
|
76
|
+
|
|
77
|
+
@title("Install")
|
|
78
|
+
class TITLE_2:
|
|
79
|
+
r'''Installation instructions.'''
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The value passed to `@title(...)` becomes the heading, and the class docstring becomes the body. Nested `TITLE_N` classes are realized as nested Markdown headings. When a section link must survive heading renames, use [stable section references](#document-anchors).
|
|
83
|
+
|
|
84
|
+
### Validation and realization
|
|
85
|
+
|
|
86
|
+
Validate a description body with the `document` regulation, then realize it with `DocumentMarkdownRealizer` or `document_markdown.MarkdownRealizer`.
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from shikumi_devdoc.norms.document import document
|
|
90
|
+
from shikumi_devdoc.realizers import DocumentMarkdownRealizer
|
|
91
|
+
|
|
92
|
+
result = document.validate(document_source, placement=())
|
|
93
|
+
if not result.is_valid:
|
|
94
|
+
raise RuntimeError(result.diagnostics)
|
|
95
|
+
|
|
96
|
+
realizer = DocumentMarkdownRealizer()
|
|
97
|
+
check = realizer.check(result.view)
|
|
98
|
+
if not check.is_realizable:
|
|
99
|
+
raise RuntimeError(check.diagnostics)
|
|
100
|
+
|
|
101
|
+
markdown = realizer.realize(result.view)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Validation checks heading structure, canonical-source declaration, information cardinality, vocabulary-reference consistency, and related semantic constraints. The realizer's `check()` method verifies realization concerns such as unresolved reference markers. Raw ATX headings written directly in a body are reported as warnings because they bypass the semantic hierarchy, while heading depth beyond six levels is an error because Markdown cannot represent it as an ATX heading. The CLI renders diagnostics with severity, diagnostic code, source location, and semantic subject when available.
|
|
105
|
+
|
|
106
|
+
<a id="document-anchors"></a>
|
|
107
|
+
|
|
108
|
+
### Stable section references
|
|
109
|
+
|
|
110
|
+
To refer to a heading semantically, attach `anchor @= "..."` to the target. The anchor is independent of the displayed heading text, so renaming the heading does not change the reference identity.
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from shikumi_devdoc.norms.document import anchor, canonical, title
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@canonical
|
|
117
|
+
@title("Guide")
|
|
118
|
+
class TITLE_1:
|
|
119
|
+
r'''See {{#installation}}.'''
|
|
120
|
+
|
|
121
|
+
@title("Installation")
|
|
122
|
+
class TITLE_2:
|
|
123
|
+
r'''Installation instructions.'''
|
|
124
|
+
anchor @= "installation"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`{{#installation}}` in a body is realized as a Markdown link to the `Installation` heading. The referring entity does not need a separate declaration such as `section_refs`; `@title` extracts references from the body automatically and stores them in the semantic view as `SectionReference` information. Validation rejects unknown references, duplicate anchors, and invalid anchor names.
|
|
128
|
+
|
|
129
|
+
The Markdown realizer emits an explicit HTML `id` for each anchor instead of relying on platform-specific heading slugs. Section-reference markers are body-only and are not allowed in heading titles.
|
|
130
|
+
|
|
131
|
+
## External information
|
|
132
|
+
|
|
133
|
+
Project names, versions, repository data, and other values that already have another canonical source are supplied to the realizer as external information rather than duplicated in document source code.
|
|
134
|
+
|
|
135
|
+
Documents refer to those values with reference markers. For example, `{{PROJECT.name}}` and `{{PROJECT.version}}` use dotted paths to address values.
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from shikumi_devdoc.realizers import DocumentMarkdownRealizer
|
|
139
|
+
|
|
140
|
+
realizer = DocumentMarkdownRealizer(
|
|
141
|
+
{
|
|
142
|
+
"PROJECT": {
|
|
143
|
+
"name": "example",
|
|
144
|
+
"version": "0.1.0",
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
To construct the same context directly from a JSON string, use `from_json()`:
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
realizer = DocumentMarkdownRealizer.from_json(
|
|
154
|
+
'{"PROJECT":{"name":"example","version":"0.1.0"}}'
|
|
155
|
+
)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Unknown references are reported by `check()` instead of being silently replaced with empty text. Values may be strings or other JSON-compatible arrays and objects.
|
|
159
|
+
|
|
160
|
+
Use `\{{...}}` in the Python source when literal double braces are required. The backslash is removed during realization without resolving the marker. `${{...}}` is also treated as literal host-language syntax, so GitHub Actions expressions can appear in developer documentation without colliding with devdoc placeholders.
|
|
161
|
+
|
|
162
|
+
## Vocabulary
|
|
163
|
+
|
|
164
|
+
A vocabulary uses `VOCABULARY` as its outermost class and places `TERM_N` classes directly beneath it. The value passed to `@term(...)` is the human-readable term name, while the docstring is its definition.
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from shikumi_devdoc.norms.vocabulary import (
|
|
168
|
+
alias,
|
|
169
|
+
canonical,
|
|
170
|
+
deprecated,
|
|
171
|
+
glossary,
|
|
172
|
+
preserve_spelling,
|
|
173
|
+
replacement,
|
|
174
|
+
term,
|
|
175
|
+
title,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@canonical
|
|
180
|
+
@title("Example Glossary")
|
|
181
|
+
class VOCABULARY:
|
|
182
|
+
r'''Terms used by Example.'''
|
|
183
|
+
|
|
184
|
+
@term("Widget")
|
|
185
|
+
class TERM_1:
|
|
186
|
+
r'''A reusable component.'''
|
|
187
|
+
glossary @= True
|
|
188
|
+
alias @= "Component"
|
|
189
|
+
alias @= "UI Widget"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Only terms with `glossary @= True` are emitted by the standard glossary Markdown realizer. Internal vocabulary can therefore remain in the canonical vocabulary source without appearing in the public glossary.
|
|
193
|
+
|
|
194
|
+
Use **preserve spelling** when a term name must keep exactly the same spelling after translation.
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
@term("Shikumi")
|
|
198
|
+
class TERM_2:
|
|
199
|
+
r'''The name of the Shikumi concept.'''
|
|
200
|
+
preserve_spelling @= True
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
`preserve_spelling @= True` does not mean that the term is impossible to translate. It records that the term name itself must remain unchanged when the surrounding document is translated. The standard glossary Markdown realizer does not act on this value directly. For translation sources, wrap the Markdown realizer with `TranslationSourceRealizer`, or use `shikumi-devdoc render --translation-source`; preserve-spelling terms are then embedded as machine-readable translation metadata in the intermediate Markdown.
|
|
204
|
+
|
|
205
|
+
A term may declare multiple alternate names with `alias @= "..."`. Aliases must not collide with canonical term names or other aliases in the same Vocabulary. A term retained for compatibility can be marked with `deprecated @= True`; when a preferred successor exists, `replacement @= "NewTerm"` names another canonical term in the same Vocabulary.
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
@term("Widget")
|
|
209
|
+
class TERM_1:
|
|
210
|
+
r'''The current term.'''
|
|
211
|
+
glossary @= True
|
|
212
|
+
|
|
213
|
+
@term("OldWidget")
|
|
214
|
+
class TERM_2:
|
|
215
|
+
r'''The former term.'''
|
|
216
|
+
glossary @= True
|
|
217
|
+
deprecated @= True
|
|
218
|
+
replacement @= "Widget"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`replacement` requires `deprecated @= True`. Unknown targets, self-replacement, and alias-only targets are rejected. The standard glossary realizer displays aliases and marks deprecated public terms together with their replacement when one is present.
|
|
222
|
+
|
|
223
|
+
### Term reference modules
|
|
224
|
+
|
|
225
|
+
A canonical vocabulary can keep stable, semantically neutral identifiers such as `TERM_1` and `TERM_2`. That is useful for the canonical source, but those identifiers alone are difficult for a person to interpret when referenced from another document source.
|
|
226
|
+
|
|
227
|
+
`shikumi-devdoc` can therefore generate a Python term-reference module from the vocabulary's `SemanticView`. Each generated `TERM_N` class contains the term name and definition in its docstring, allowing IDE definition navigation and hover information to reveal the meaning immediately.
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
shikumi-devdoc terms my_project.docs.vocabulary.canonical \
|
|
231
|
+
-o my_project/docs/vocabulary/terms.py
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The output module name and location are chosen by the consuming project. If the generated file is named `terms.py`, a document can use it like this:
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
from my_project.docs.vocabulary import terms
|
|
238
|
+
from shikumi_devdoc.norms.document import (
|
|
239
|
+
canonical,
|
|
240
|
+
title,
|
|
241
|
+
vocabulary,
|
|
242
|
+
vocabulary_refs,
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@canonical
|
|
247
|
+
@vocabulary(terms)
|
|
248
|
+
@title("API Reference")
|
|
249
|
+
class TITLE_1:
|
|
250
|
+
r'''The public API exposes {{TERM_1}}.'''
|
|
251
|
+
|
|
252
|
+
vocabulary_refs @= (terms.TERM_1,)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
`@vocabulary(terms)` follows the generated module back to the canonical Vocabulary and uses it to resolve `TERM_N` markers during realization. Proxy classes passed through `vocabulary_refs` are likewise resolved back to their canonical `VOCABULARY.TERM_N` classes, preserving semantic identity.
|
|
256
|
+
|
|
257
|
+
### Local vocabulary references
|
|
258
|
+
|
|
259
|
+
`vocabulary_refs` should not be collected at the document root. Place each reference on the entity that actually uses the term.
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
@title("Section")
|
|
263
|
+
class TITLE_2:
|
|
264
|
+
r'''This section uses {{TERM_1}}.'''
|
|
265
|
+
|
|
266
|
+
vocabulary_refs @= (terms.TERM_1,)
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
For every entity, the validator requires the set of `TERM_N` markers appearing in that entity's title and body to match exactly the set in that entity's own `vocabulary_refs`. References are not inherited between parent and child entities. Repeating the same `TERM_N` in the text still requires only one entry in `vocabulary_refs`.
|
|
270
|
+
|
|
271
|
+
This redundancy is intentional. `TERM_N` reference markers are used by the machine during realization, while `vocabulary_refs` gives a human a direct IDE path to the canonical term definition. The validator guarantees that the two stay synchronized.
|
|
272
|
+
|
|
273
|
+
## Changelogs
|
|
274
|
+
|
|
275
|
+
A changelog is described in three levels: `CHANGELOG`, `RELEASE_N`, and `CHANGE_N`. Change categories are `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, and `Security`.
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
from shikumi_devdoc.norms.changelog import (
|
|
279
|
+
ADDED,
|
|
280
|
+
CHANGED,
|
|
281
|
+
breaking,
|
|
282
|
+
canonical,
|
|
283
|
+
change,
|
|
284
|
+
changelog,
|
|
285
|
+
release,
|
|
286
|
+
released_on,
|
|
287
|
+
unreleased,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
@canonical
|
|
292
|
+
@changelog("Example Changelog")
|
|
293
|
+
class CHANGELOG:
|
|
294
|
+
r'''Release history for Example.'''
|
|
295
|
+
|
|
296
|
+
@release()
|
|
297
|
+
class RELEASE_1:
|
|
298
|
+
r'''Changes planned for the next release.'''
|
|
299
|
+
unreleased @= True
|
|
300
|
+
|
|
301
|
+
@change(CHANGED)
|
|
302
|
+
class CHANGE_1:
|
|
303
|
+
r'''Changed the wire format.'''
|
|
304
|
+
breaking @= True
|
|
305
|
+
|
|
306
|
+
@release("0.1.0")
|
|
307
|
+
class RELEASE_2:
|
|
308
|
+
r'''First public release.'''
|
|
309
|
+
released_on @= "2026-09-13"
|
|
310
|
+
|
|
311
|
+
@change(ADDED)
|
|
312
|
+
class CHANGE_1:
|
|
313
|
+
r'''Added the initial document system.'''
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
The Markdown realizer groups change entries by category within each release. As with documents, a changelog may use `@vocabulary(terms)` and `vocabulary_refs`; vocabulary references are validated locally on the release or change entity where they are used.
|
|
317
|
+
|
|
318
|
+
Pending changes can be represented by one leading `@release()` entry with `unreleased @= True`. It must be the first release entry and must not have `released_on`. Individual `CHANGE_N` entries can use `breaking @= True`; the Markdown realizer keeps the normal change category and marks that bullet as breaking.
|
|
319
|
+
|
|
320
|
+
A changelog can grow indefinitely in a healthy long-lived project, so its canonical source may be physically split across modules without splitting the logical changelog. Releases directly under `CHANGELOG` remain first. Releases stored elsewhere go under a top-level `CHANGELOG_PART` decorated with `@changelog_part(order=...)`.
|
|
321
|
+
|
|
322
|
+
```python
|
|
323
|
+
# released.py
|
|
324
|
+
from shikumi_devdoc.norms.changelog import (
|
|
325
|
+
ADDED,
|
|
326
|
+
change,
|
|
327
|
+
changelog_part,
|
|
328
|
+
release,
|
|
329
|
+
released_on,
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
@changelog_part(order=10)
|
|
334
|
+
class CHANGELOG_PART:
|
|
335
|
+
@release("1.0.0")
|
|
336
|
+
class RELEASE_1:
|
|
337
|
+
r'''First stable release.'''
|
|
338
|
+
released_on @= "2026-01-01"
|
|
339
|
+
|
|
340
|
+
@change(ADDED)
|
|
341
|
+
class CHANGE_1:
|
|
342
|
+
r'''Added the initial feature set.'''
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Validate or render the changelog package rather than an individual module. The logical order is: releases directly under `CHANGELOG`, then `CHANGELOG_PART` containers by ascending `order`, then source order within each part. Filenames do not affect release order. Duplicate part orders, duplicate release labels, and multiple `Unreleased` sections are checked across the whole package. The original single-module form remains valid.
|
|
346
|
+
|
|
347
|
+
## Canonical sources and generated artifacts
|
|
348
|
+
|
|
349
|
+
The outermost entity of a document, vocabulary, or changelog is decorated with `@canonical`. This declaration remains explicit even when the location could be inferred, because making the canonical-source contract visible in source code is useful to a human reader.
|
|
350
|
+
|
|
351
|
+
Markdown realizers can place an arbitrary operational comment at the beginning of a generated artifact. The wording of that comment is not defined by `shikumi-devdoc` itself. A consuming project defines the content operationally and supplies it when rendering an intermediate document.
|
|
352
|
+
|
|
353
|
+
This repository keeps the generation notice and the LLM publication instructions together in `_internal/document_source/notice.toml` as a single `[notice].content` value. Passing that file explicitly with `shikumi-devdoc render --notice ...` causes the CLI to replace `{canonical_source}` with the canonical source path and pass the complete content to the Markdown realizer as its leading comment. The CLI does not search for a notice file automatically.
|
|
354
|
+
|
|
355
|
+
This keeps project-specific operational language out of the library implementation while allowing each project to carry the instructions required by its own generation and publication workflow directly in its intermediate documents.
|
|
356
|
+
|
|
357
|
+
## Recommended documentation workflow
|
|
358
|
+
|
|
359
|
+
When Japanese is the source language and English is the public language, the recommended workflow has three layers:
|
|
360
|
+
|
|
361
|
+
```text
|
|
362
|
+
_internal/document_source/.../canonical.py
|
|
363
|
+
↓ realization
|
|
364
|
+
_internal/document_build/ja/...md
|
|
365
|
+
↓ translation
|
|
366
|
+
README.md and other public English documents
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
`canonical.py` is the semantic canonical source, the Japanese Markdown is a human-readable intermediate artifact, and the top-level English Markdown is the published artifact.
|
|
370
|
+
|
|
371
|
+
The intermediate document may be committed to Git. It is not merely a temporary build file: it provides an inspection boundary for checking that the regulation was realized as intended and that the Japanese source text is correct before translation. It must not be edited directly.
|
|
372
|
+
|
|
373
|
+
Translation into public English documentation is treated as a publication step mediated by an LLM rather than as a mechanical build step. This repository stores generation and publication instructions in `notice.content` in `_internal/document_source/notice.toml`, supplied explicitly with `--notice`.
|
|
374
|
+
|
|
375
|
+
For translation-bound intermediates, `--translation-source` can additionally embed a `shikumi-devdoc:translation-metadata` HTML comment. That comment carries semantic policy such as the exact terms marked with `preserve_spelling @= True`, so the intermediate Markdown does not lose that information at realization time. Translation metadata and operational comments are not publication content and should be omitted from the public document.
|
|
376
|
+
|
|
377
|
+
## Repository dogfooding
|
|
378
|
+
|
|
379
|
+
`shikumi-devdoc` uses this same workflow to build its own README and CHANGELOG.
|
|
380
|
+
|
|
381
|
+
```text
|
|
382
|
+
_internal/
|
|
383
|
+
├── document_source/
|
|
384
|
+
│ ├── README.md
|
|
385
|
+
│ ├── notice.toml
|
|
386
|
+
│ ├── readme/
|
|
387
|
+
│ │ └── canonical.py
|
|
388
|
+
│ ├── changelog/
|
|
389
|
+
│ │ ├── canonical.py
|
|
390
|
+
│ │ └── released.py
|
|
391
|
+
│ └── vocabulary/
|
|
392
|
+
│ ├── canonical.py
|
|
393
|
+
│ └── terms.py
|
|
394
|
+
└── document_build/
|
|
395
|
+
└── ja/
|
|
396
|
+
├── README.md
|
|
397
|
+
└── CHANGELOG.md
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
`_internal/document_source/README.md` briefly explains the files in this directory and the local intermediate-document workflow. `notice.toml` contains operational text that changes rarely.
|
|
401
|
+
|
|
402
|
+
Project name, version, and other values that represent the current rendering snapshot are not stored as another context file. Instead, the caller assembles the required values into one JSON object and passes that JSON string with `--context`. For example:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
CONTEXT='{"project":{"name":"shikumi-devdoc","version":"0.1.0","requires-python":">=3.11"}}'
|
|
406
|
+
|
|
407
|
+
shikumi-devdoc terms \
|
|
408
|
+
_internal.document_source.vocabulary.canonical \
|
|
409
|
+
-o _internal/document_source/vocabulary/terms.py
|
|
410
|
+
|
|
411
|
+
shikumi-devdoc render document \
|
|
412
|
+
_internal.document_source.readme.canonical \
|
|
413
|
+
-o _internal/document_build/ja/README.md \
|
|
414
|
+
--context "$CONTEXT" \
|
|
415
|
+
--notice _internal/document_source/notice.toml \
|
|
416
|
+
--translation-source
|
|
417
|
+
|
|
418
|
+
shikumi-devdoc render changelog \
|
|
419
|
+
_internal.document_source.changelog \
|
|
420
|
+
-o _internal/document_build/ja/CHANGELOG.md \
|
|
421
|
+
--context "$CONTEXT" \
|
|
422
|
+
--notice _internal/document_source/notice.toml \
|
|
423
|
+
--translation-source
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
`--notice` explicitly names a file containing comparatively stable operational text, and no notice file is discovered implicitly. `--context` accepts one JSON object string representing the external-information snapshot for that realization. `--translation-source` preserves translation-relevant semantic policy in the intermediate artifact. How the caller obtains context values is deliberately outside `shikumi-devdoc`. The top-level `README.md` and `CHANGELOG.md` are then produced by translating the Japanese intermediates with an LLM according to the embedded instructions and metadata; public versions omit those comments.
|
|
427
|
+
|
|
428
|
+
## Design boundaries
|
|
429
|
+
|
|
430
|
+
`shikumi-devdoc` is not intended to become a general-purpose template engine.
|
|
431
|
+
|
|
432
|
+
- It does not provide a template language with conditionals or loops.
|
|
433
|
+
- Reference markers explicitly bring vocabulary or external-information values into a document.
|
|
434
|
+
- Semantic structure is validated through Shikumi regulations.
|
|
435
|
+
- Markdown realizers focus on converting a `SemanticView` into a concrete document format.
|
|
436
|
+
- Project-specific document sources and translation workflows remain in the consuming project.
|
|
437
|
+
|
|
438
|
+
These boundaries keep canonical sources, semantic information, realization rules, and published artifacts separate.
|
|
439
|
+
|
|
440
|
+
## License
|
|
441
|
+
|
|
442
|
+
`shikumi-devdoc` is released under the MIT License. See the top-level `LICENSE` file for details.
|