Metadata-Version: 2.4
Name: rekisteri
Version: 2026.6.18
Summary: Register / registry (Finnish: rekisteri) manages catalogs of documents organized per publication identifier stem, issue, and optionally revision.
Author-email: Stefan Hagen <stefan@hagen.link>
Maintainer-email: Stefan Hagen <stefan@hagen.link>
License-Expression: MIT
Project-URL: Documentation, https://codes.dilettant.life/docs/rekisteri
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: kaava>=2026.6.8
Requires-Dist: pyyaml>=6.0.3
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"

# rekisteri

Register / registry (Finnish: rekisteri) manages catalogs of documents organised
per publication identifier stem, issue, and optionally revision.

Requires Python 3.11 or later.

## Install

```
pip install rekisteri
```

## Documentation

- [Quick tour](quickstart/README.md) — feature walkthrough you can follow in minutes
- [Tutorial](tutorial/README.md) — step-by-step guided build of a running registry
- [Man page](docs/rekisteri.1) — full CLI reference (`man rekisteri` after placing the file on your `MANPATH`)
- [Changes](docs/changes.md) — release history
- [SBOM](docs/sbom/README.md) — dependency inventory

To use `man rekisteri`, copy `docs/rekisteri.1` to a directory on your `MANPATH`, for example:

```
mkdir -p ~/.local/share/man/man1
cp docs/rekisteri.1 ~/.local/share/man/man1/
```

## Overview

`rekisteri` is for operators of document publication registries — typically teams
that publish structured document sets (specifications, guides, manuals) and need a
stable, browsable web tree alongside a machine-readable catalog.

Given a `rekisteri.yaml` configuration it:

1. **Scans** a `source/ref/` tree for documents organised by stem, issue, and
   (optionally) revision.
2. **Validates** the tree: checks metadata completeness, issue numbering consistency,
   slug uniqueness, and catalog cross-references.
3. **Publishes** a `web-parent/` tree:
   - `ref/` — anchor copies of all documents with `index` navigation symlinks at
     issue and stem level.
   - `pub/` — per-slug cross-reference symlinks into `ref/`, grouped by issue.
   - `reference → ref` and `publication → pub` alias symlinks at the root.
4. **Generates** catalog JSON files (`documents.json`, `cards.json`) at a separate
   `catalog-out` path for consumption by a side-loading web application.

## Source tree structure

### Two-level (levels: 2, default)

```
source/ref/
└── <STEM>/
    ├── meta.yaml            ← stem-level metadata (title, status, …)
    ├── <ISSUE>/
    │   ├── issue.yaml       ← optional issue-level metadata overrides
    │   └── <stem>-<some_id>-<issue>.<ext>
    └── <ISSUE>/
        └── …
```

### Three-level (levels: 3)

```
source/ref/
└── <STEM>/
    ├── meta.yaml
    └── <ISSUE>/
        ├── issue.yaml
        └── <REVISION>/
            ├── revision.yaml    ← optional revision-level metadata overrides
            └── <stem>-<some_id>-<issue>.<ext>
```

Issue directories contain only digits (`01`, `2`, …).
Revision directories are any non-numeric non-hidden name (`A`, `B`, `draft`, …).

## Quick start

```
# Write rekisteri.yaml and meta.yaml templates into the current directory
rekisteri eject .

# Check the tree is well-formed
rekisteri validate --config rekisteri.yaml

# Show the discovered publication tree
rekisteri explain

# Publish the web-parent tree
rekisteri publish
```

## Configuration

`rekisteri.yaml` controls all paths and behaviour.
Run `rekisteri eject` to write a commented template.

```yaml
source-root: ./source/ref    # path to the source document tree
web-root: ./web-parent       # path where the published tree is written
catalog-out: ./catalog       # path where catalog JSON files are written
levels: 2                    # 2 (stem/issue) or 3 (stem/issue/revision)
# stem-pattern: null         # optional regex; only matching stems are scanned
# slug-pattern: null         # optional regex applied to some_id before slugifying
catalog:
  documents-file: documents.json
  cards-file: cards.json
  cards:
    - title: Guides          # display name for this card group
      identifiers: [INTRO]   # slugs of publications belonging to this group
```

All multi-word keys are kebab-case.
`--config` / `-c` accepts either a file path or a directory (looks for
`rekisteri.yaml` inside it).

## Metadata files

Each stem, issue, and revision may carry a YAML metadata file.
Outer scope (stem) keeps its keys; inner levels only add keys not already present.

```yaml
title: ""          # human-readable publication title (required; must not be empty)
abstract: ""       # short abstract
responsible: ""    # team or person responsible
tags: []           # free-form tags
status: active     # active | superseded | archived
supersedes: []     # list of STEM/ISSUE entries this publication supersedes
```

## Filename conventions

Documents are named `<stem>-<some_id>-<issue>.<ext>`, all lowercase.
The `some_id` part is extracted by stripping the stem prefix and the issue suffix
from the filename stem.  It is then uppercased (after optional `slug-pattern`
filtering) to form the **slug** used in `pub/` and catalog.

Example: `x-guide-intro-01.pdf` in stem `X-GUIDE`, issue `01`
→ `some_id = intro` → `slug = INTRO`.

The slug is stable as long as `some_id` is preserved across stem renames and
issue increments.

## Web-parent tree topology

After `rekisteri publish`:

```
web-parent/
├── ref/
│   └── <STEM>/
│       ├── index.<ext>              → latest issue's document
│       └── <ISSUE>/
│           ├── <doc-name>.<ext>     ← anchor copy
│           └── index.<ext>          → <doc-name>
├── pub/
│   └── <SLUG>/
│       ├── index.<ext>              → latest issue's document
│       └── <ISSUE>/
│           ├── <doc-name>.<ext>     → ../../../ref/STEM/ISSUE/doc
│           └── index.<ext>          → <doc-name>
├── reference                        → ref
└── publication                      → pub
```

With `--copy`, `pub/` entries are real file copies instead of symlinks
(useful for Windows or archival scenarios).

## Commands

### `rekisteri doctor`

Check the environment and configuration: Python version, config file presence,
source-root existence, and web-root parent.

```
rekisteri doctor [-c PATH]
```

### `rekisteri eject`

Write `rekisteri.yaml` and `meta.yaml` templates to a target directory.
Skips existing files unless `--overwrite` is given.

```
rekisteri eject [TARGET] [--overwrite]
```

### `rekisteri explain`

Print the discovered publication tree: stems, issues (and revisions for
three-level trees), documents, and slugs.

```
rekisteri explain [-c PATH]
```

### `rekisteri publish`

Build the `web-parent/` tree from the source tree.
Creates anchor copies in `ref/`, cross-reference symlinks in `pub/`,
and the `reference` / `publication` alias symlinks.

```
rekisteri publish [-c PATH] [--copy]
```

`--copy` replaces `pub/` cross-reference symlinks with real file copies.

### `rekisteri validate`

Validate the source tree and metadata.
Prints findings tagged `[error]` or `[warning]`.
Exits 1 on any error; with `--strict`, also exits 1 on warnings.

```
rekisteri validate [-c PATH] [--strict]
```

## Dependencies

- [kaava](https://pypi.org/project/kaava/) — typed configuration loading
- [PyYAML](https://pypi.org/project/PyYAML/) — YAML parsing
