stack: Typ project und Collection kb/gtd/ (#123)
CI / verify (push) Successful in 45s
Release / release (push) Successful in 36s

Files changed:
- CHANGES.md
- README.md
- VERSION
- kb/CONTRACT.md
- kb/CONVENTIONS.md
- kb/entities/COLLECTION.md
- kb/gtd/COLLECTION.md
- kb/gtd/INDEX.md
- kb/index.md
- tools/CONTRACT.md
- tools/chemenu/kb_collections.py
- tools/chemenu/tests/test_conventions.py
- tools/chemenu/tests/test_docs_verify.py
- tools/chemenu/tests/test_kb_collections.py
- tools/chemenu/tests/test_new_page.py
- tools/chemenu/tests/test_type_resolver.py
- tools/chemenu/tests/test_types_cmd.py
- types/project.md
- types/project.schema.yaml
- types/type-spec.md
This commit is contained in:
torben committed 2026-09-19 21:13:24 +02:00
1 parent 3c9d669729
commit ee24b6e5b8
20 files changed
+507 -38

No files matched your search

+100
View File
@@ -0,0 +1,100 @@
---
type: types/type-spec.md
name: project
description: Structured type for a committed initiative (a GTD project) - goal, participants, durable status, open loops
schema: types/project.schema.yaml
subtype_field: responsibility
base_dir: gtd
page_ref_fields: [related, sources]
layout:
haus: {dir: haus, title: Haus}
finanzen: {dir: finanzen, title: Finanzen}
technik: {dir: technik, title: Technik}
---
# Project
This instance's configuration for the `project` type: its frontmatter fields as this schema
requires them, and the page skeleton `wikitool new project` scaffolds. `project` is instance-owned
end to end - it declares no `guidance:`, so this file's own prose (below) carries its authoring
contract, the same way a type an instance invents for itself always does.
## When to use
- A committed initiative in the GTD sense: something with a goal, an end state, and open loops -
a household project, a piece of paid work, a piece of volunteer work.
## When NOT to use
- **The artifact the initiative is about.** `project` names the *Vorhaben* - the undertaking - not
the thing it produces or touches. A codebase, a deployed system, a tool: that is `entity` with
`entity_type: codebase` (or `system`/`tool`/`technology`). "Ship Chemenu 7.0" is a `project`;
Chemenu the codebase is an `entity`. The two are homonyms, not the same page under two types -
see `kb/entities/COLLECTION.md` for the artifact side of that line.
- A bare task or a day-to-day commitment with no project shape of its own - that lives in the
task provider, not here (`kb/` never mirrors the tracker's momentary state, see below).
## Frontmatter
| Field | Required | Use |
|---|---:|---|
| `type` | Yes | `types/project.md` |
| `state` | Yes | One of: active, dormant, completed, abandoned - a durable characterization, not the tracker's momentary state (see `## Status` below) |
| `responsibility` | Yes | `subtype_field`, one of: haus, finanzen, technik - selects the area under `kb/gtd/` |
| `created` / `modified` | Yes | As everywhere |
| `related` | No | Titles of related pages (entities, concepts, sources, other projects) |
| `sources` | No | Titles of the source pages backing this page's claims |
| `provenance` | Yes | sourced, general or mixed - `general` is the common case: a project page is usually written by the operator from their own participation, not from an ingested source |
| `summary` | Yes | One-liner for `kb/index.md` |
## Authoring guidance
- **`## Status` is a durable characterization, never a momentary state.** "Pilotbetrieb seit
2026-03, zwei Abteilungen angebunden" - not "warte auf Freigabe". The page never summarizes the
task list; the momentary state lives in the tracker, and the two are joined only by name, never
synced (`AGENTS.md` invariant 8 - one truth about "status").
- **`## Beteiligte` carries mentions, not links.** One to two lines per person, in prose, with
**no `[[wikilink]]` and no page of their own.** A person earns a page only once they matter for
the *knowledge*, independent of this project - at that point the mention becomes an edge with a
participation label. This is a deliberate, named exception to `kb/CONTRACT.md` § "Every page
should" (link to the entities it mentions): it is held by this rule, not by a checker, so read
a page here with no person-links as conforming, not as incomplete.
## Template
The block below is page material, so it is written in this instance's KB language
(`kb/CONVENTIONS.md` `language:`) rather than in the control plane's English - its headings
become the headings of every page `wikitool new project` scaffolds.
```markdown
# {name}
**Status:** {state|capitalize}
**Bereich:** {responsibility|capitalize}
## Ziel
TODO: Was ist der angestrebte Endzustand? Woran erkennt man, dass dieses Vorhaben abgeschlossen ist?
## Kontext
TODO: Warum jetzt, warum überhaupt - der Hintergrund, der nicht aus dem Titel folgt.
## Beteiligte
TODO: Ein bis zwei Zeilen je Person - Erwähnung im Fließtext, kein Wikilink, keine eigene Seite.
## Status
TODO: Dauerhafte Charakterisierung des aktuellen Stands - keine Aufgabenliste, kein Momentzustand.
## Entscheidungen
TODO: Festlegungen, die dieses Vorhaben getroffen hat, und warum.
## Gelerntes
TODO: Was sich im Verlauf gezeigt hat.
```
The value behind `**Status:**` and `**Bereich:**` stays the English enum value - that is what
`search --field` filters on.
+78
View File
@@ -0,0 +1,78 @@
# YAML Schema for project type
type: object
properties:
type:
type: string
const: "types/project.md"
description: Must reference the project type-spec
state:
type: string
enum: [active, dormant, completed, abandoned]
default: active
description: >-
Durable characterization of this initiative, not the tracker's momentary
state. `active` and `dormant` both mean the initiative is ongoing -
`dormant` is a deliberate pause, so the weekly review does not flag it as
stalled the way an `active` project with no next action is flagged.
`completed` and `abandoned` both mean it is over; the distinction is for
the record, not for review behaviour.
responsibility:
type: string
enum: [haus, finanzen, technik]
description: >-
Which area of responsibility this initiative belongs to. No default -
the machine must not pick one on the author's behalf. Must match a key
in this type-spec's own `layout:`, or placement falls back to a naively
pluralized directory with no catalog title (see `types/type-spec.md`
§ Anatomy of a type).
created:
type: string
format: date
pattern: "^\\d{4}-\\d{2}-\\d{2}$"
description: Creation date in YYYY-MM-DD format
modified:
type: string
format: date
pattern: "^\\d{4}-\\d{2}-\\d{2}$"
description: Last modification date in YYYY-MM-DD format
related:
type: array
items:
oneOf:
- type: string
- type: object
minProperties: 1
maxProperties: 1
additionalProperties:
type: string
description: >-
Declared outbound edges. Each entry is either `<label>: <page title>` -
the label drawn from instructions/link-taxonomy.md and authorised per
destination by kb/gtd/COLLECTION.md's `outbound:` block - or a bare page
title for an edge whose label has not been declared yet.
sources:
type: array
items:
type: string
description: Source page titles that support claims on this page
provenance:
type: string
enum: [sourced, general, mixed]
default: general
description: >-
Provenance classification. `general` is the common case: a project page
is usually written by the operator from their own participation, not
from an ingested source.
summary:
type: string
description: 1-line summary for index.md
minLength: 1
required:
- type
- state
- responsibility
- created
- modified
- provenance
- summary
additionalProperties: false
+14 -8
View File
@@ -67,7 +67,7 @@ frontmatter before anyone drew it:
| Type-spec | Describes | Owned by | Ships as |
|---|---|---|---|
| `root: kb` (`entity`, `concept`, `source`, `comparison`) | A page **this instance** writes | The instance | `types/<name>.md.template` plus its `.schema.yaml.template`, adopted by a rename |
| `root: kb` (`entity`, `concept`, `source`, `comparison`, `project`) | A page **this instance** writes | The instance | `types/<name>.md.template` plus its `.schema.yaml.template`, adopted by a rename |
| `root: repo` (`instruction`), no `base_dir` (`lint-report`), and `type-spec`/`type-guidance` themselves | A stack artifact | The stack | Verbatim |
A page type-spec's frontmatter configuration and its `## Template` body are therefore the
@@ -104,13 +104,19 @@ exactly as it binds the four shipped ones: a new page type is instance-owned end
settles who may change it, not which language each half is written in - and it may declare its
own `guidance:` file if it wants the same shape, though nothing requires it to.
**What the stack still requires of the type layer is one line.** There must be a type-spec
declaring `name: source` whose schema requires `raw_files:` — the whole `raw/` → `kb/`
provenance path (`sources coverage`, `[^cite-id]` resolution, `kb/provenance.md`) asks
`page.kind == "source"`, so without it nothing resolves. `docs verify` checks exactly that and
nothing beyond it: not the directory, not the title prefix, not a word of the prose. Which
collection is stack-required is *derived* from where that type writes rather than listed
separately, so renaming it stays consistent instead of tripping a hardcoded name.
**What the stack still requires of the type layer is one line per type, and there are two of
them today.** There must be a type-spec declaring `name: source` whose schema requires
`raw_files:` — the whole `raw/` → `kb/` provenance path (`sources coverage`, `[^cite-id]`
resolution, `kb/provenance.md`) asks `page.kind == "source"`, so without it nothing resolves.
There must equally be one declaring `name: project` whose schema requires `state:` — the weekly
review asks `page.kind == "project"` and reads `state:` to tell an ongoing initiative with no
next action from one that is deliberately paused or over, so without it nothing to review
resolves either. `docs verify` checks exactly that, for each, and nothing beyond it: not the
directory, not the title prefix, not a word of the prose. Which collection is stack-required is
*derived* from where that type writes rather than listed separately, so renaming it stays
consistent instead of tripping a hardcoded name. The anchor stays this small on purpose — the
page type-specs belong to the instance, so anything more would be the stack reaching into a file
it does not own (`tools/chemenu/kb_collections.py`'s `STACK_REQUIRED_TYPES`).
**Quality goal:** a type-spec is the single source of truth for its type. No structural fact
about a page type may be restated anywhere else — not in `AGENTS.md`, not in a skill, not in