armarium 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.
- armarium-0.1.0/.gitignore +10 -0
- armarium-0.1.0/AGENTS.md +17 -0
- armarium-0.1.0/CHANGELOG.md +15 -0
- armarium-0.1.0/LICENSE +21 -0
- armarium-0.1.0/PKG-INFO +98 -0
- armarium-0.1.0/README.md +73 -0
- armarium-0.1.0/docs/add.md +170 -0
- armarium-0.1.0/docs/campaign.md +46 -0
- armarium-0.1.0/docs/init.md +22 -0
- armarium-0.1.0/docs/record.md +73 -0
- armarium-0.1.0/docs/releases.md +20 -0
- armarium-0.1.0/docs/schemas.md +52 -0
- armarium-0.1.0/docs/type.md +245 -0
- armarium-0.1.0/docs/validate.md +103 -0
- armarium-0.1.0/docs/vault.md +86 -0
- armarium-0.1.0/pyproject.toml +66 -0
- armarium-0.1.0/ruff.toml +4 -0
- armarium-0.1.0/src/armarium/__init__.py +1 -0
- armarium-0.1.0/src/armarium/add.py +304 -0
- armarium-0.1.0/src/armarium/cli.py +232 -0
- armarium-0.1.0/src/armarium/clue.py +97 -0
- armarium-0.1.0/src/armarium/content.py +126 -0
- armarium-0.1.0/src/armarium/index.py +195 -0
- armarium-0.1.0/src/armarium/init.py +79 -0
- armarium-0.1.0/src/armarium/lib.py +518 -0
- armarium-0.1.0/src/armarium/logging.py +40 -0
- armarium-0.1.0/src/armarium/note.py +46 -0
- armarium-0.1.0/src/armarium/parse.py +599 -0
- armarium-0.1.0/src/armarium/player.py +45 -0
- armarium-0.1.0/src/armarium/schemas.py +178 -0
- armarium-0.1.0/src/armarium/session.py +52 -0
- armarium-0.1.0/src/armarium/transcript.py +83 -0
- armarium-0.1.0/src/armarium/validate.py +1359 -0
- armarium-0.1.0/tests/schemas/.gitignore +1 -0
- armarium-0.1.0/tests/schemas/__init__.py +1 -0
- armarium-0.1.0/tests/schemas/fixtures/clue.json +228 -0
- armarium-0.1.0/tests/schemas/fixtures/content.json +165 -0
- armarium-0.1.0/tests/schemas/fixtures/note.json +28 -0
- armarium-0.1.0/tests/schemas/fixtures/player.json +72 -0
- armarium-0.1.0/tests/schemas/fixtures/reference.json +28 -0
- armarium-0.1.0/tests/schemas/fixtures/session.json +405 -0
- armarium-0.1.0/tests/schemas/fixtures/status.json +102 -0
- armarium-0.1.0/tests/schemas/fixtures/transcript.json +65 -0
- armarium-0.1.0/tests/schemas/fixtures/type.json +181 -0
- armarium-0.1.0/tests/schemas/requirements.txt +3 -0
- armarium-0.1.0/tests/schemas/test_schemas.py +283 -0
- armarium-0.1.0/tests/schemas/test_views.py +145 -0
- armarium-0.1.0/tests/test_add.py +463 -0
- armarium-0.1.0/tests/test_cli.py +1190 -0
- armarium-0.1.0/tests/test_clue.py +352 -0
- armarium-0.1.0/tests/test_content.py +385 -0
- armarium-0.1.0/tests/test_diagnostics.py +60 -0
- armarium-0.1.0/tests/test_docs.py +187 -0
- armarium-0.1.0/tests/test_index.py +258 -0
- armarium-0.1.0/tests/test_init.py +196 -0
- armarium-0.1.0/tests/test_lib.py +672 -0
- armarium-0.1.0/tests/test_logging.py +68 -0
- armarium-0.1.0/tests/test_note.py +343 -0
- armarium-0.1.0/tests/test_parse.py +842 -0
- armarium-0.1.0/tests/test_player.py +332 -0
- armarium-0.1.0/tests/test_pyproject.py +956 -0
- armarium-0.1.0/tests/test_schemas.py +491 -0
- armarium-0.1.0/tests/test_session.py +242 -0
- armarium-0.1.0/tests/test_transcript.py +358 -0
- armarium-0.1.0/tests/test_validate.py +3081 -0
- armarium-0.1.0/tests/test_vaults.py +56 -0
- armarium-0.1.0/vaults/example/.gitignore +8 -0
- armarium-0.1.0/vaults/example/.obsidian/app.json +3 -0
- armarium-0.1.0/vaults/example/.obsidian/appearance.json +5 -0
- armarium-0.1.0/vaults/example/.obsidian/snippets/armarium-prose.css +27 -0
- armarium-0.1.0/vaults/example/.scratch/.gitkeep +0 -0
- armarium-0.1.0/vaults/example/assets/harbor-pass.txt +7 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/clues/C-1-0001.md +11 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/clues/C-1-0002.md +11 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/clues/C-1-0003.md +11 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/clues/C-1-0004.md +11 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/content/Blue Signal Flare.md +21 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/content/Brass Harbor Seal.md +23 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/content/Esme Calder.md +23 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/content/Glass Petrel Crew.md +23 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/content/Glass Petrel.md +28 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/content/Quay Nine.md +23 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/content/Shoal Chart.md +22 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/content/Talia Venn.md +29 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/notes/Prep for the hearing.md +14 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/reference/Campaign.md +13 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/reference/indexes/Clues.md +21 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/reference/players/Ellis.md +4 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/reference/players/Rowan.md +4 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/sessions/S-1-001.md +73 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/sessions/S-1-002.md +74 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/sessions/S-1-003.md +68 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/sessions/transcripts/S-1-001 Transcript.md +29 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_1/sessions/transcripts/S-1-002 Transcript.md +23 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/clues/C-2-0001.md +12 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/clues/C-2-0002.md +12 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/clues/C-2-0003.md +12 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/clues/C-2-0004.md +12 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/content/Bram Kest.md +31 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/content/Copper Finch.md +26 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/content/Darian Holt.md +31 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/content/Oren Vale.md +25 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/content/Silas Rook.md +25 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/content/Tern Salvage Company.md +26 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/content/Tern.md +23 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/notes/Storm timing.md +13 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/reference/Campaign.md +15 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/reference/indexes/Clues.md +21 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/reference/players/Martin.md +6 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/reference/players/Peter.md +6 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/sessions/S-2-001.md +94 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/sessions/S-2-002.md +77 -0
- armarium-0.1.0/vaults/example/campaigns/campaign_2/sessions/transcripts/S-2-001 Transcript.md +24 -0
- armarium-0.1.0/vaults/example/content/Captain Mara Vey.md +23 -0
- armarium-0.1.0/vaults/example/content/Free Pilots Assembly.md +26 -0
- armarium-0.1.0/vaults/example/content/Orlan Countinghouse.md +28 -0
- armarium-0.1.0/vaults/example/content/Port Briselle.md +27 -0
- armarium-0.1.0/vaults/example/content/The Bell Accord.md +22 -0
- armarium-0.1.0/vaults/example/content/The Crownless Coast.md +28 -0
- armarium-0.1.0/vaults/example/content/The Red Teeth.md +27 -0
- armarium-0.1.0/vaults/example/content/Wake-lark.md +22 -0
- armarium-0.1.0/vaults/example/notes/Coast design notes.md +13 -0
- armarium-0.1.0/vaults/example/reference/.gitkeep +0 -0
- armarium-0.1.0/vaults/example/reference/schemas/clue.schema.json +142 -0
- armarium-0.1.0/vaults/example/reference/schemas/content.schema.json +360 -0
- armarium-0.1.0/vaults/example/reference/schemas/note.schema.json +28 -0
- armarium-0.1.0/vaults/example/reference/schemas/player.schema.json +42 -0
- armarium-0.1.0/vaults/example/reference/schemas/reference.schema.json +28 -0
- armarium-0.1.0/vaults/example/reference/schemas/session.schema.json +143 -0
- armarium-0.1.0/vaults/example/reference/schemas/status.schema.json +34 -0
- armarium-0.1.0/vaults/example/reference/schemas/transcript.schema.json +41 -0
- armarium-0.1.0/vaults/example/reference/schemas/type.schema.json +50 -0
- armarium-0.1.0/vaults/example/reference/statuses/Abandoned.md +5 -0
- armarium-0.1.0/vaults/example/reference/statuses/Dormant.md +5 -0
- armarium-0.1.0/vaults/example/reference/statuses/Hinted.md +5 -0
- armarium-0.1.0/vaults/example/reference/statuses/Pending.md +5 -0
- armarium-0.1.0/vaults/example/reference/statuses/Revealed.md +5 -0
- armarium-0.1.0/vaults/example/reference/statuses/Superseded.md +5 -0
- armarium-0.1.0/vaults/example/reference/templates/Campaign.md +4 -0
- armarium-0.1.0/vaults/example/reference/templates/Clue.md +10 -0
- armarium-0.1.0/vaults/example/reference/templates/Clues.md +21 -0
- armarium-0.1.0/vaults/example/reference/templates/Content.md +15 -0
- armarium-0.1.0/vaults/example/reference/templates/Note.md +3 -0
- armarium-0.1.0/vaults/example/reference/templates/Player.md +4 -0
- armarium-0.1.0/vaults/example/reference/templates/Session.md +46 -0
- armarium-0.1.0/vaults/example/reference/templates/Transcript.md +7 -0
- armarium-0.1.0/vaults/example/reference/types/Clue.md +32 -0
- armarium-0.1.0/vaults/example/reference/types/Content.md +66 -0
- armarium-0.1.0/vaults/example/reference/types/Note.md +18 -0
- armarium-0.1.0/vaults/example/reference/types/Player.md +16 -0
- armarium-0.1.0/vaults/example/reference/types/Reference.md +15 -0
- armarium-0.1.0/vaults/example/reference/types/Session.md +38 -0
- armarium-0.1.0/vaults/example/reference/types/Status.md +26 -0
- armarium-0.1.0/vaults/example/reference/types/Transcript.md +41 -0
- armarium-0.1.0/vaults/example/reference/types/Type.md +29 -0
- armarium-0.1.0/vaults/example/reference/views/clue-index.base +33 -0
- armarium-0.1.0/vaults/example/reference/views/clue-sessions.base +23 -0
- armarium-0.1.0/vaults/example/reference/views/content-clues.base +23 -0
- armarium-0.1.0/vaults/example/reference/views/prepared-clues.base +22 -0
- armarium-0.1.0/vaults/example/reference/views/prepared-locations.base +23 -0
- armarium-0.1.0/vaults/example/reference/views/prepared-npcs.base +23 -0
- armarium-0.1.0/vaults/starter/.gitignore +8 -0
- armarium-0.1.0/vaults/starter/.obsidian/app.json +3 -0
- armarium-0.1.0/vaults/starter/.obsidian/appearance.json +5 -0
- armarium-0.1.0/vaults/starter/.obsidian/snippets/armarium-prose.css +27 -0
- armarium-0.1.0/vaults/starter/.scratch/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/assets/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/campaigns/campaign_1/clues/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/campaigns/campaign_1/content/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/campaigns/campaign_1/notes/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/campaigns/campaign_1/reference/Campaign.md +4 -0
- armarium-0.1.0/vaults/starter/campaigns/campaign_1/reference/indexes/Clues.md +21 -0
- armarium-0.1.0/vaults/starter/campaigns/campaign_1/reference/players/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/campaigns/campaign_1/sessions/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/campaigns/campaign_1/sessions/transcripts/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/content/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/notes/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/reference/.gitkeep +0 -0
- armarium-0.1.0/vaults/starter/reference/schemas/clue.schema.json +142 -0
- armarium-0.1.0/vaults/starter/reference/schemas/content.schema.json +360 -0
- armarium-0.1.0/vaults/starter/reference/schemas/note.schema.json +28 -0
- armarium-0.1.0/vaults/starter/reference/schemas/player.schema.json +42 -0
- armarium-0.1.0/vaults/starter/reference/schemas/reference.schema.json +28 -0
- armarium-0.1.0/vaults/starter/reference/schemas/session.schema.json +143 -0
- armarium-0.1.0/vaults/starter/reference/schemas/status.schema.json +34 -0
- armarium-0.1.0/vaults/starter/reference/schemas/transcript.schema.json +41 -0
- armarium-0.1.0/vaults/starter/reference/schemas/type.schema.json +50 -0
- armarium-0.1.0/vaults/starter/reference/statuses/Abandoned.md +5 -0
- armarium-0.1.0/vaults/starter/reference/statuses/Dormant.md +5 -0
- armarium-0.1.0/vaults/starter/reference/statuses/Hinted.md +5 -0
- armarium-0.1.0/vaults/starter/reference/statuses/Pending.md +5 -0
- armarium-0.1.0/vaults/starter/reference/statuses/Revealed.md +5 -0
- armarium-0.1.0/vaults/starter/reference/statuses/Superseded.md +5 -0
- armarium-0.1.0/vaults/starter/reference/templates/Campaign.md +4 -0
- armarium-0.1.0/vaults/starter/reference/templates/Clue.md +10 -0
- armarium-0.1.0/vaults/starter/reference/templates/Clues.md +21 -0
- armarium-0.1.0/vaults/starter/reference/templates/Content.md +15 -0
- armarium-0.1.0/vaults/starter/reference/templates/Note.md +3 -0
- armarium-0.1.0/vaults/starter/reference/templates/Player.md +4 -0
- armarium-0.1.0/vaults/starter/reference/templates/Session.md +46 -0
- armarium-0.1.0/vaults/starter/reference/templates/Transcript.md +7 -0
- armarium-0.1.0/vaults/starter/reference/types/Clue.md +32 -0
- armarium-0.1.0/vaults/starter/reference/types/Content.md +66 -0
- armarium-0.1.0/vaults/starter/reference/types/Note.md +18 -0
- armarium-0.1.0/vaults/starter/reference/types/Player.md +16 -0
- armarium-0.1.0/vaults/starter/reference/types/Reference.md +15 -0
- armarium-0.1.0/vaults/starter/reference/types/Session.md +38 -0
- armarium-0.1.0/vaults/starter/reference/types/Status.md +26 -0
- armarium-0.1.0/vaults/starter/reference/types/Transcript.md +41 -0
- armarium-0.1.0/vaults/starter/reference/types/Type.md +29 -0
- armarium-0.1.0/vaults/starter/reference/views/clue-index.base +33 -0
- armarium-0.1.0/vaults/starter/reference/views/clue-sessions.base +23 -0
- armarium-0.1.0/vaults/starter/reference/views/content-clues.base +23 -0
- armarium-0.1.0/vaults/starter/reference/views/prepared-clues.base +22 -0
- armarium-0.1.0/vaults/starter/reference/views/prepared-locations.base +23 -0
- armarium-0.1.0/vaults/starter/reference/views/prepared-npcs.base +23 -0
armarium-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Repository workflow
|
|
2
|
+
|
|
3
|
+
- Never commit or push directly to `main`.
|
|
4
|
+
- Make all changes, including planning and documentation, on a working branch
|
|
5
|
+
and submit them through a pull request.
|
|
6
|
+
- The user reviews and merges pull requests; do not merge them on the user's behalf
|
|
7
|
+
without explicit instruction.
|
|
8
|
+
|
|
9
|
+
# Testing conventions
|
|
10
|
+
|
|
11
|
+
- Tests for a source module `X.py` belong in `test_X.py`.
|
|
12
|
+
- Cover every class, function, and method with dedicated tests, including private
|
|
13
|
+
helpers and properties.
|
|
14
|
+
- Organize tests into classes named for the class, function, or method under test
|
|
15
|
+
(for example, `TestParseWikilink` or `TestResultFailed`).
|
|
16
|
+
- Minimize redundant test code aggressively with `pytest.mark.parametrize`; share
|
|
17
|
+
a test body when cases exercise the same behavior with different inputs.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.1.0 (2026-09-30)
|
|
6
|
+
|
|
7
|
+
- Add `armarium init` for creating standalone vaults.
|
|
8
|
+
- Add `armarium add` subcommands for campaigns, Content, Clues, Sessions, Players,
|
|
9
|
+
Notes, and Transcripts, using vault-local templates and conventions.
|
|
10
|
+
- Add `armarium validate` for records, directories, and vaults, with checks for
|
|
11
|
+
schemas, Markdown structure, wikilinks, and relationships between records.
|
|
12
|
+
- Add shared setting content and campaign-specific records, with Obsidian Bases
|
|
13
|
+
views for clues and session preparation.
|
|
14
|
+
- Add a starter vault and a two-campaign example vault.
|
|
15
|
+
- Add the MIT license and changelog-driven release automation.
|
armarium-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 William J. Bradshaw
|
|
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.
|
armarium-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: armarium
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Create and validate Armarium Markdown vaults
|
|
5
|
+
Project-URL: Homepage, https://github.com/willbradshaw/armarium
|
|
6
|
+
Project-URL: Repository, https://github.com/willbradshaw/armarium
|
|
7
|
+
Project-URL: Issues, https://github.com/willbradshaw/armarium/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/willbradshaw/armarium/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Will Bradshaw
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Python: >=3.14
|
|
13
|
+
Requires-Dist: jsonschema[format]<5,>=4.23
|
|
14
|
+
Requires-Dist: markdown-it-py<4,>=3
|
|
15
|
+
Requires-Dist: pyyaml<7,>=6
|
|
16
|
+
Requires-Dist: referencing<1,>=0.35
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: build<2,>=1; extra == 'dev'
|
|
19
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
21
|
+
Requires-Dist: ruff==0.16.8; extra == 'dev'
|
|
22
|
+
Requires-Dist: types-jsonschema; extra == 'dev'
|
|
23
|
+
Requires-Dist: types-pyyaml; extra == 'dev'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# Armarium
|
|
27
|
+
|
|
28
|
+
A system-general starter for tabletop roleplaying knowledge bases in Obsidian.
|
|
29
|
+
|
|
30
|
+
See [vaults/example](vaults/example) for a fleshed-out toy vault that follows and
|
|
31
|
+
demonstrates this repository's conventions.
|
|
32
|
+
|
|
33
|
+
## Create a vault
|
|
34
|
+
|
|
35
|
+
With Python 3.14+ and [uv](https://docs.astral.sh/uv/guides/tools/), install
|
|
36
|
+
Armarium from this checkout and create a vault:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
uv tool install .
|
|
40
|
+
armarium init ../my-vault
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
If `armarium` is not on your PATH, run `uv tool update-shell` and restart your
|
|
44
|
+
terminal. To reinstall after updating this checkout, use
|
|
45
|
+
`uv tool install --reinstall-package armarium .`.
|
|
46
|
+
|
|
47
|
+
Open the new folder in Obsidian and edit
|
|
48
|
+
`campaigns/campaign_1/reference/Campaign.md`. See [Creating a vault](docs/init.md)
|
|
49
|
+
for details.
|
|
50
|
+
|
|
51
|
+
Add campaigns and records with `armarium add`; see
|
|
52
|
+
[Adding to a vault](docs/add.md).
|
|
53
|
+
|
|
54
|
+
Requires Obsidian **1.13.7+** with **Bases** and
|
|
55
|
+
[Frontmatter Markdown Links](https://github.com/mnaoumov/obsidian-frontmatter-markdown-links)
|
|
56
|
+
enabled.
|
|
57
|
+
|
|
58
|
+
## Layout
|
|
59
|
+
|
|
60
|
+
| Folder | Purpose |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| `content/` | Shared setting content. |
|
|
63
|
+
| `campaigns/campaign_1/` | Campaign content, clues, sessions, and reference material. |
|
|
64
|
+
| `reference/` | Templates, type descriptions, schemas, statuses, and shared reference material. |
|
|
65
|
+
| `assets/` | Maps, images, and handouts. |
|
|
66
|
+
|
|
67
|
+
Use [`armarium add`](docs/add.md#adding-a-record) or copy a file from
|
|
68
|
+
`reference/templates/` to create a record. [Records](docs/record.md)
|
|
69
|
+
describes what every record shares and [Types](docs/type.md) the fields, body
|
|
70
|
+
and rules of each type.
|
|
71
|
+
|
|
72
|
+
The starter is preconfigured for a single campaign. The example includes two
|
|
73
|
+
campaigns sharing setting Content, with independent campaign state and combined
|
|
74
|
+
Clue and appearance lists. [Vault layout](docs/vault.md) states the full required
|
|
75
|
+
skeleton and where each record type lives.
|
|
76
|
+
|
|
77
|
+
`.obsidian/` holds the settings the records rely on and is part of the vault;
|
|
78
|
+
only Obsidian's workspace files are ignored. `.scratch/` is ignored working
|
|
79
|
+
space; `.gitkeep` files preserve empty directories in Git. The copied vault can
|
|
80
|
+
be its own Git repository.
|
|
81
|
+
|
|
82
|
+
For schema integration and testing, see [Schema development](docs/schemas.md).
|
|
83
|
+
|
|
84
|
+
Planned work is tracked in the [issues](https://github.com/willbradshaw/armarium/issues).
|
|
85
|
+
|
|
86
|
+
MIT licensed. See the [changelog](CHANGELOG.md) and [release process](docs/releases.md).
|
|
87
|
+
|
|
88
|
+
## Validate records
|
|
89
|
+
|
|
90
|
+
Validate a record or a whole vault:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
armarium validate path/to/record.md
|
|
94
|
+
armarium validate ../my-vault
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
See [Validation](docs/validate.md) for the command's options, what is checked
|
|
98
|
+
and how findings are reported.
|
armarium-0.1.0/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Armarium
|
|
2
|
+
|
|
3
|
+
A system-general starter for tabletop roleplaying knowledge bases in Obsidian.
|
|
4
|
+
|
|
5
|
+
See [vaults/example](vaults/example) for a fleshed-out toy vault that follows and
|
|
6
|
+
demonstrates this repository's conventions.
|
|
7
|
+
|
|
8
|
+
## Create a vault
|
|
9
|
+
|
|
10
|
+
With Python 3.14+ and [uv](https://docs.astral.sh/uv/guides/tools/), install
|
|
11
|
+
Armarium from this checkout and create a vault:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
uv tool install .
|
|
15
|
+
armarium init ../my-vault
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
If `armarium` is not on your PATH, run `uv tool update-shell` and restart your
|
|
19
|
+
terminal. To reinstall after updating this checkout, use
|
|
20
|
+
`uv tool install --reinstall-package armarium .`.
|
|
21
|
+
|
|
22
|
+
Open the new folder in Obsidian and edit
|
|
23
|
+
`campaigns/campaign_1/reference/Campaign.md`. See [Creating a vault](docs/init.md)
|
|
24
|
+
for details.
|
|
25
|
+
|
|
26
|
+
Add campaigns and records with `armarium add`; see
|
|
27
|
+
[Adding to a vault](docs/add.md).
|
|
28
|
+
|
|
29
|
+
Requires Obsidian **1.13.7+** with **Bases** and
|
|
30
|
+
[Frontmatter Markdown Links](https://github.com/mnaoumov/obsidian-frontmatter-markdown-links)
|
|
31
|
+
enabled.
|
|
32
|
+
|
|
33
|
+
## Layout
|
|
34
|
+
|
|
35
|
+
| Folder | Purpose |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `content/` | Shared setting content. |
|
|
38
|
+
| `campaigns/campaign_1/` | Campaign content, clues, sessions, and reference material. |
|
|
39
|
+
| `reference/` | Templates, type descriptions, schemas, statuses, and shared reference material. |
|
|
40
|
+
| `assets/` | Maps, images, and handouts. |
|
|
41
|
+
|
|
42
|
+
Use [`armarium add`](docs/add.md#adding-a-record) or copy a file from
|
|
43
|
+
`reference/templates/` to create a record. [Records](docs/record.md)
|
|
44
|
+
describes what every record shares and [Types](docs/type.md) the fields, body
|
|
45
|
+
and rules of each type.
|
|
46
|
+
|
|
47
|
+
The starter is preconfigured for a single campaign. The example includes two
|
|
48
|
+
campaigns sharing setting Content, with independent campaign state and combined
|
|
49
|
+
Clue and appearance lists. [Vault layout](docs/vault.md) states the full required
|
|
50
|
+
skeleton and where each record type lives.
|
|
51
|
+
|
|
52
|
+
`.obsidian/` holds the settings the records rely on and is part of the vault;
|
|
53
|
+
only Obsidian's workspace files are ignored. `.scratch/` is ignored working
|
|
54
|
+
space; `.gitkeep` files preserve empty directories in Git. The copied vault can
|
|
55
|
+
be its own Git repository.
|
|
56
|
+
|
|
57
|
+
For schema integration and testing, see [Schema development](docs/schemas.md).
|
|
58
|
+
|
|
59
|
+
Planned work is tracked in the [issues](https://github.com/willbradshaw/armarium/issues).
|
|
60
|
+
|
|
61
|
+
MIT licensed. See the [changelog](CHANGELOG.md) and [release process](docs/releases.md).
|
|
62
|
+
|
|
63
|
+
## Validate records
|
|
64
|
+
|
|
65
|
+
Validate a record or a whole vault:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
armarium validate path/to/record.md
|
|
69
|
+
armarium validate ../my-vault
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
See [Validation](docs/validate.md) for the command's options, what is checked
|
|
73
|
+
and how findings are reported.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Adding to a vault
|
|
2
|
+
|
|
3
|
+
`armarium add` creates [campaigns](#adding-a-campaign) and [records](#adding-a-record)
|
|
4
|
+
in an existing [vault](vault.md) using its local templates and conventions, then
|
|
5
|
+
[validates the result](#templates-and-validation). For example:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
armarium add campaign --vault ../my-vault
|
|
9
|
+
armarium add content "Port Briselle" --subtype Location --vault ../my-vault
|
|
10
|
+
armarium add session --campaign 1 --vault ../my-vault
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
For a new vault, start with [`armarium init`](init.md).
|
|
14
|
+
|
|
15
|
+
## Shared behavior
|
|
16
|
+
|
|
17
|
+
All commands share rules for [vault selection](#choosing-a-vault-and-destination),
|
|
18
|
+
[campaign selection](#choosing-a-campaign) and [templates and
|
|
19
|
+
validation](#templates-and-validation).
|
|
20
|
+
|
|
21
|
+
### Choosing a vault and destination
|
|
22
|
+
|
|
23
|
+
Pass `--vault PATH` to select a vault's root directory, using an absolute path or a path
|
|
24
|
+
relative to your current directory. Omit it to discover the vault from your current
|
|
25
|
+
directory when running anywhere inside it.
|
|
26
|
+
|
|
27
|
+
Records go in the selected vault's [declared directory](vault.md#where-records-live) for
|
|
28
|
+
their type and [campaign scope](#choosing-a-campaign), rather than directly in the
|
|
29
|
+
current directory. Existing records and campaigns are never overwritten.
|
|
30
|
+
|
|
31
|
+
### Choosing a campaign
|
|
32
|
+
|
|
33
|
+
While inside a [campaign directory](campaign.md#directory) or any descendants, new
|
|
34
|
+
records created with `armarium add` are added to that campaign. Use `--campaign N` to
|
|
35
|
+
select another existing campaign. Selecting a different vault does not inherit the
|
|
36
|
+
current campaign.
|
|
37
|
+
|
|
38
|
+
Outside a campaign directory, [Content](#content) and [Notes](#notes) default to shared
|
|
39
|
+
scope; [Players](#players), [Sessions](#sessions) and [Clues](#clues) require
|
|
40
|
+
`--campaign`. [Transcripts](#transcripts) always take their campaign from the selected
|
|
41
|
+
Session. [`add campaign`](#adding-a-campaign) creates a new campaign.
|
|
42
|
+
|
|
43
|
+
### Templates and validation
|
|
44
|
+
|
|
45
|
+
Initial values come from the vault's local [templates](record.md#anatomy), and validation
|
|
46
|
+
uses its [schemas](record.md#types-statuses-and-schemas). Edit a template to change
|
|
47
|
+
defaults, or edit the new record afterward.
|
|
48
|
+
|
|
49
|
+
A new [record](record.md) must pass [schema, link and contextual
|
|
50
|
+
checks](validate.md#checks). Failed writes, interruptions and record-validation failures
|
|
51
|
+
remove the new record. Each command then [validates the whole vault](validate.md#scope);
|
|
52
|
+
failure exits with status 1 and retains the valid new record for inspection. Campaign
|
|
53
|
+
creation removes partial campaigns on write failure, but retains them on validation
|
|
54
|
+
failure.
|
|
55
|
+
|
|
56
|
+
## Adding a campaign
|
|
57
|
+
|
|
58
|
+
Add a [campaign](campaign.md):
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
armarium add campaign --vault ../my-vault
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The new number is one greater than the largest existing campaign number; `--number N`
|
|
65
|
+
chooses an unused positive number explicitly.
|
|
66
|
+
|
|
67
|
+
Campaign and Clues templates supply the initial records. Their `campaign_1` and `C-1-`
|
|
68
|
+
clue ID placeholders are updated to the new number; other text is preserved. Players,
|
|
69
|
+
sessions and content are not copied from existing campaigns.
|
|
70
|
+
|
|
71
|
+
## Adding a record
|
|
72
|
+
|
|
73
|
+
[Content](#content), [Players](#players) and [Notes](#notes) take a name, which becomes
|
|
74
|
+
the filename. Names may contain spaces; omit `.md`.
|
|
75
|
+
|
|
76
|
+
[Sessions](#sessions) and [Clues](#clues) use numbered filenames. By default, the number
|
|
77
|
+
is one greater than the largest existing number of that type in the campaign, including
|
|
78
|
+
archives. Use `--number N` to choose an unused number within the type's range.
|
|
79
|
+
|
|
80
|
+
[References to existing records](record.md#links) must resolve uniquely; use
|
|
81
|
+
vault-relative paths when names are ambiguous.
|
|
82
|
+
|
|
83
|
+
### Content
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
armarium add content "Port Briselle" --subtype Location --vault ../my-vault
|
|
87
|
+
armarium add content "Mira" --subtype PC --campaign 1 --player Alex --vault ../my-vault
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Use `--subtype NPC|PC|Location|Faction|Object|Lore` to select the [Content
|
|
91
|
+
subtype](type.md#content). Required nullable subtype fields start empty unless set in
|
|
92
|
+
the template. PCs need an existing [Player](#players), supplied with `--player` or in
|
|
93
|
+
the template.
|
|
94
|
+
|
|
95
|
+
Shared records start without [campaign state](campaign.md#state). Campaign-specific
|
|
96
|
+
records get a `campaign_N` block, where `N` is the selected campaign number; Objects
|
|
97
|
+
also get `held_by` in that block.
|
|
98
|
+
|
|
99
|
+
### Sessions
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
armarium add session --campaign 1 --vault ../my-vault
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Creates a [Session](type.md#session), `S-N-NNN.md`, with the campaign link and session
|
|
106
|
+
number filled in. Session numbers range from 1 to 999.
|
|
107
|
+
|
|
108
|
+
### Players
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
armarium add player "Alex" --campaign 1 --vault ../my-vault
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The standard template creates an unassigned [Player](type.md#player) with `plays: []`.
|
|
115
|
+
Configured links must target shared or same-campaign PCs. Use [add content](#content) to
|
|
116
|
+
create a PC linked to the new Player; creating a Player does not change PCs or
|
|
117
|
+
backlinks.
|
|
118
|
+
|
|
119
|
+
### Notes
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
armarium add note "Working ideas" --vault ../my-vault
|
|
123
|
+
armarium add note "Session prep" --campaign 1 --vault ../my-vault
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Copies the local [Note](type.md#note) template, including its metadata and body. An
|
|
127
|
+
empty body is valid.
|
|
128
|
+
|
|
129
|
+
### Clues
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
armarium add clue --campaign 1 --vault ../my-vault --text 'The gate is locked from within.'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Creates a [Clue](type.md#clue), `C-N-NNNN.md`. Clue numbers range from 1 to 9999.
|
|
136
|
+
|
|
137
|
+
Supply nonblank `--text`, or omit it to use nonblank text from the local template.
|
|
138
|
+
`armarium add clue --vault ../my-vault --help` shows the discovered default text, or
|
|
139
|
+
indicates that `--text` is required when the template text is blank.
|
|
140
|
+
|
|
141
|
+
Text goes in [frontmatter](record.md#anatomy). Its [wikilinks](record.md#links) must
|
|
142
|
+
target shared or same-campaign [Content](#content). `subjects` is derived from those
|
|
143
|
+
targets without duplicates, or `[]` for unlinked text. Template status, session fields
|
|
144
|
+
and the Sessions section/Base embed are preserved.
|
|
145
|
+
|
|
146
|
+
### Transcripts
|
|
147
|
+
|
|
148
|
+
```sh
|
|
149
|
+
armarium add transcript S-1-001 --body-file recorded-speech.md --vault ../my-vault
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Select an existing [Session](#sessions) by name or vault-relative path. Its campaign and
|
|
153
|
+
identity determine the [Transcript](type.md#transcript) destination, `S-N-NNN
|
|
154
|
+
Transcript.md`. No Session is selected automatically.
|
|
155
|
+
|
|
156
|
+
`--body-file` is required and reads UTF-8 Markdown without frontmatter:
|
|
157
|
+
|
|
158
|
+
```markdown
|
|
159
|
+
## Arrival
|
|
160
|
+
|
|
161
|
+
- [GM] The door opens.
|
|
162
|
+
- [Player] Who is there?
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Follow the [Transcript body format](type.md#body-7): titled level-two sections, each
|
|
166
|
+
containing one bullet list of attributed, single-paragraph utterances. The supplied body
|
|
167
|
+
replaces the template's instructional sample. The command imports already-formatted text
|
|
168
|
+
without transcribing audio, editing speech or changing the source file or Session. Body
|
|
169
|
+
grammar and the local schema are checked before creating the file; link and contextual
|
|
170
|
+
checks follow.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Campaigns
|
|
2
|
+
|
|
3
|
+
Each [vault](vault.md) holds one or more **campaigns**, each in its own directory
|
|
4
|
+
`campaigns/campaign_N/` (with `N` a positive integer). Each campaign describes a series of TTRPG [sessions](type.md#session) in the vault's setting, along with their shared context and metadata.
|
|
5
|
+
|
|
6
|
+
## Directory
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
campaigns/campaign_N/
|
|
10
|
+
clues/ Clue records, C-N-NNNN.md
|
|
11
|
+
content/ Content records specific to this campaign
|
|
12
|
+
notes/ Note records specific to this campaign
|
|
13
|
+
reference/
|
|
14
|
+
Campaign.md the campaign overview, a Reference record
|
|
15
|
+
indexes/
|
|
16
|
+
Clues.md the clue index, a Reference record
|
|
17
|
+
players/ Player records
|
|
18
|
+
sessions/ Session records, S-N-NNN.md
|
|
19
|
+
transcripts/ Transcript records, S-N-NNN Transcript.md
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The starter vault ships `campaign_1`. Use [`armarium add campaign`](add.md#adding-a-campaign)
|
|
23
|
+
to add another.
|
|
24
|
+
|
|
25
|
+
## State
|
|
26
|
+
|
|
27
|
+
[Content](type.md#content) records carry `campaign_N` blocks in their frontmatter describing their campaign-related state:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
campaign_1:
|
|
31
|
+
first_session: "[[S-1-001]]"
|
|
32
|
+
last_session: "[[S-1-002]]"
|
|
33
|
+
campaign_2:
|
|
34
|
+
first_session:
|
|
35
|
+
last_session:
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
A block's `first_session` and `last_session` are both null until the record
|
|
39
|
+
first appears in that campaign, and then both link to the earliest and latest
|
|
40
|
+
Session of that campaign in the record's Appearances. `N` must be an existing
|
|
41
|
+
campaign, and a record under `campaigns/campaign_N/content` may carry only that
|
|
42
|
+
campaign's block; shared Content may carry a block for any campaign.
|
|
43
|
+
|
|
44
|
+
A Content record with the Object subtype has an additional field in its campaign blocks: `held_by`. This is null before the object enters play; then a link to a Content entry denoting the PC, NPC or Faction holding the object, or a list thereof for shared possession; then `GONE` if the object has left play.
|
|
45
|
+
|
|
46
|
+
In addition to the `campaign_N` blocks, a Content entry must also describe its subject's appearances in each campaign in its Appearances section; see [Content](type.md#content) for more details.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Creating a vault
|
|
2
|
+
|
|
3
|
+
```sh
|
|
4
|
+
armarium init ../my-vault
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
`armarium init PATH` initializes a new vault in a fresh directory by copying the
|
|
8
|
+
[starter vault](../vaults/starter/). `PATH` must be a nonexistent directory;
|
|
9
|
+
existing files and directories (even empty ones) are refused, as are symbolic
|
|
10
|
+
links. Missing parent directories are automatically created. If copying fails or
|
|
11
|
+
is interrupted, the partially created vault is removed safely. After copying
|
|
12
|
+
completes, the new vault undergoes validation before success is reported.
|
|
13
|
+
|
|
14
|
+
Use `armarium init --force PATH` to replace an existing directory and **all its
|
|
15
|
+
contents** with the starter vault. Files and symbolic links are still refused.
|
|
16
|
+
The replacement is copied before the old directory is removed, so a copy failure
|
|
17
|
+
leaves the existing directory intact.
|
|
18
|
+
|
|
19
|
+
`init` does not initialize Git or install Obsidian plugins. After completion,
|
|
20
|
+
open the new vault in Obsidian and enable the plugins listed in
|
|
21
|
+
[the README](../README.md) before editing. After initialization, the vault can be
|
|
22
|
+
moved or placed in its own Git repository.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Records
|
|
2
|
+
|
|
3
|
+
Every Markdown file in a [vault](vault.md) is a record: YAML frontmatter that
|
|
4
|
+
declares its type, followed by a Markdown body. What every record shares is
|
|
5
|
+
below; each type's fields, body and rules are documented in [Types](type.md).
|
|
6
|
+
|
|
7
|
+
## Anatomy
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
---
|
|
11
|
+
type: "[[types/Content]]"
|
|
12
|
+
subtype: NPC
|
|
13
|
+
summary: Harbour pilot who witnesses petitions.
|
|
14
|
+
aliases: [Mara]
|
|
15
|
+
campaign_1:
|
|
16
|
+
first_session: "[[S-1-001]]"
|
|
17
|
+
last_session: "[[S-1-002]]"
|
|
18
|
+
---
|
|
19
|
+
## Notes
|
|
20
|
+
Mara holds a seat for the eastern approaches. ^seat
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Frontmatter** is a YAML mapping between the opening and closing `---` lines.
|
|
24
|
+
Keys must be unique strings and values representable in JSON, so dates are
|
|
25
|
+
written as `YYYY-MM-DD` strings. A record without frontmatter has no type and
|
|
26
|
+
is invalid. Fields beyond a type's schema are allowed on every type.
|
|
27
|
+
|
|
28
|
+
**`type`** is the one field every record must have: a canonical
|
|
29
|
+
[wikilink](#links) to the record's Type record, `[[types/Content]]` or
|
|
30
|
+
`[[Content]]`, with no alias or anchor. The last path segment names the type,
|
|
31
|
+
and `reference/types/Content.md` must exist.
|
|
32
|
+
|
|
33
|
+
**The body** is everything after the closing `---`: CommonMark with tables,
|
|
34
|
+
as Obsidian renders it. Headings divide it into sections, nested by level; a
|
|
35
|
+
paragraph or list item may end in an Obsidian block id (`^seat`). Each type
|
|
36
|
+
fixes which headings its body must have; the rest is free Markdown.
|
|
37
|
+
|
|
38
|
+
**Templates** in `reference/templates/` are starting points, not records:
|
|
39
|
+
their placeholder values need not follow the rules. Copy one to start a record.
|
|
40
|
+
|
|
41
|
+
## Links
|
|
42
|
+
|
|
43
|
+
Records link to each other with Obsidian
|
|
44
|
+
[internal links](https://help.obsidian.md/links): `[[Quay Nine]]`,
|
|
45
|
+
`[[Quay Nine|the quay]]`, `[[S-1-002#Events]]`, `[[The Bell Accord#^hearing]]`,
|
|
46
|
+
`![[…]]` to embed. Armarium adds these rules:
|
|
47
|
+
|
|
48
|
+
- Every link must resolve to exactly one file. A target matches any trailing
|
|
49
|
+
part of a file's path, case-insensitively and with `.md` optional, so the
|
|
50
|
+
shortest spelling that is unique is enough; when two files share a name,
|
|
51
|
+
spell enough of the path to tell them apart.
|
|
52
|
+
- A heading or block anchor must exist in the linked record. Anchors on files
|
|
53
|
+
that are not records (`![[reference/views/clue-index.base#Active]]`) are
|
|
54
|
+
not validated.
|
|
55
|
+
- In frontmatter a link must be **canonical**: quoted, `"[[target]]"`, with no
|
|
56
|
+
alias or anchor. A frontmatter field may not name the same file twice.
|
|
57
|
+
- Inside a Markdown table, a `|` within a link is written `\|` to avoid
|
|
58
|
+
splitting the link between cells.
|
|
59
|
+
|
|
60
|
+
## Types, statuses and schemas
|
|
61
|
+
|
|
62
|
+
The type system lives in `reference/`:
|
|
63
|
+
|
|
64
|
+
- A **Type** record in `reference/types/` defines a type: its name is the
|
|
65
|
+
filename, and its `directories` field says
|
|
66
|
+
[where its records live](vault.md#where-records-live).
|
|
67
|
+
- A **schema**, `reference/schemas/<type>.schema.json`, describes each record
|
|
68
|
+
of the type as `{frontmatter, body}` in JSON Schema draft 2020-12: the
|
|
69
|
+
frontmatter as parsed, the body as one string. Every Type has a schema and
|
|
70
|
+
every schema a Type.
|
|
71
|
+
- A **Status** record in `reference/statuses/` defines a lifecycle state for
|
|
72
|
+
one type, named in `applies_to`. A record's `status` must be a Status whose
|
|
73
|
+
`applies_to` is the record's type. The six shipped statuses apply to Clues.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Releases
|
|
2
|
+
|
|
3
|
+
Every PR updates [CHANGELOG.md](../CHANGELOG.md), normally under `Unreleased`.
|
|
4
|
+
|
|
5
|
+
To prepare a release, update `version` in [pyproject.toml](../pyproject.toml),
|
|
6
|
+
rename the `Unreleased` heading to `VERSION (YYYY-MM-DD)`, and add a fresh
|
|
7
|
+
`Unreleased` heading above it. Merge the PR to create a draft GitHub release
|
|
8
|
+
whose text comes from that version's changelog section. The draft targets the
|
|
9
|
+
commit that triggered the workflow. The `draft-release` workflow can also be
|
|
10
|
+
run manually to retry draft creation.
|
|
11
|
+
|
|
12
|
+
Changes to `pyproject.toml` or `CHANGELOG.md` trigger the workflow. It skips
|
|
13
|
+
draft creation unless the changelog has a versioned heading matching the package
|
|
14
|
+
version, and skips versions that already have a GitHub release. PR titles do
|
|
15
|
+
not affect release creation.
|
|
16
|
+
|
|
17
|
+
Review and publish the draft on GitHub. The `publish` workflow checks out the
|
|
18
|
+
release tag, checks that it matches the package version, runs lint, type checks,
|
|
19
|
+
tests and vault validation, then builds and publishes to PyPI. Tags use the
|
|
20
|
+
package version without a `v` prefix, for example `0.1.0`.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Schema development
|
|
2
|
+
|
|
3
|
+
For contributors changing and testing schemas. Record authoring rules
|
|
4
|
+
live in the vault's `reference/types/` Type records.
|
|
5
|
+
|
|
6
|
+
## Input and schema selection
|
|
7
|
+
|
|
8
|
+
Draft 2020-12 schemas validate `{frontmatter, body}`: parsed frontmatter and the
|
|
9
|
+
Markdown body. Dates are represented as ISO date strings; Session `date` accepts
|
|
10
|
+
`YYYY-MM-DD` or null. Custom frontmatter fields are allowed.
|
|
11
|
+
|
|
12
|
+
Each supported `type` has a schema in the vault's `reference/schemas/` directory:
|
|
13
|
+
|
|
14
|
+
| `type` | Schema |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| `[[types/Content]]` | `content.schema.json` |
|
|
17
|
+
| `[[types/Clue]]` | `clue.schema.json` |
|
|
18
|
+
| `[[types/Note]]` | `note.schema.json` |
|
|
19
|
+
| `[[types/Session]]` | `session.schema.json` |
|
|
20
|
+
| `[[types/Player]]` | `player.schema.json` |
|
|
21
|
+
| `[[types/Transcript]]` | `transcript.schema.json` |
|
|
22
|
+
| `[[Reference]]` | `reference.schema.json` |
|
|
23
|
+
| `[[Type]]` | `type.schema.json` |
|
|
24
|
+
| `[[Status]]` | `status.schema.json` |
|
|
25
|
+
|
|
26
|
+
Schemas apply to typed records; unfinished templates are a separate category.
|
|
27
|
+
References are local. The tests enable URI and date format assertions.
|
|
28
|
+
|
|
29
|
+
## Limits
|
|
30
|
+
|
|
31
|
+
Body regexes check basic structure. Duplicate headings and matching fenced text
|
|
32
|
+
can satisfy Content/Session heading checks; Transcript checks only one heading
|
|
33
|
+
and attributed entry. Clue requires Sessions plus one Base embed, but cannot establish that
|
|
34
|
+
it executes or that the embedded Base exists. Content’s Active Clues and each
|
|
35
|
+
Session preparation view section also require exactly one Base embed; other
|
|
36
|
+
sections retain their free Markdown content. Link existence, target kinds, campaign and
|
|
37
|
+
filename identity, chronology, reciprocal relationships and history consistency
|
|
38
|
+
require vault-aware validation.
|
|
39
|
+
|
|
40
|
+
## Tests
|
|
41
|
+
|
|
42
|
+
From the repository root, without installing Armarium:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
python3 -m venv /tmp/armarium-schema-venv
|
|
46
|
+
/tmp/armarium-schema-venv/bin/pip install -r tests/schemas/requirements.txt
|
|
47
|
+
/tmp/armarium-schema-venv/bin/python -m pytest tests/schemas -q
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Tests cover meta-schemas, offline references, parsed JSON fixtures, committed
|
|
51
|
+
Markdown records and identical schema/type-reference copies in both vaults.
|
|
52
|
+
The PyYAML fixture loader is test support, not a production parser.
|