Add the catalog index, and package a real prompt collection

CANP-WP-0004. The operator asked canned-prompts to build a database of
versioned prompts recording where each came from and when — the first step
toward a platform for collaborative prompting.

The format had nowhere to put that. `provenance` records who wrote a prompt and
where the idea came from; nothing recorded how a copy arrived in a particular
store. Section 20.3 now specifies an `index.yaml` as store metadata rather than
package data: how a copy arrived differs for every consumer, and recording an
arrival must never rewrite the package that arrived.

`add`, `install` and `publish` record registry, id, version, name, source,
method, first-inclusion date, and the package's declared author, source and
licence — the last three copied so a listing is readable without opening every
package. A new `index` verb lists it. `included_at` is never overwritten; a
re-run updates `last_seen_at`, because when a package first entered a
collection is a fact about history rather than about the last command run.

Tests 84 -> 90.

Also records two findings from actually using the format:

CANP-WP-0004-T03 — inclusion has no deduplication, so a diamond dependency
renders shared content once per path. Found by composing a real collection.
Not fixed here: deduplicating means choosing which occurrence survives and
deciding what happens when two paths resolve different versions, which is
resolver behaviour that section 10.4 deliberately avoids. Handed to
CANP-WP-0005 with a leaning: document it, warn at validation time, do not
deduplicate.

The add_ons workaround in practice/pqrst-estimate is evidence about section
23's deferred "richer template syntax" — an optional appendix has to be an
input with an empty default, because CPF has no conditionals.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bjefh8NUiEiahN4JLwoSKM

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 388925@bnt-lap001
Assistant-Session: 3507023f-e0fd-4a1e-9d90-a0d4217d1502
This commit is contained in:
tegwick 2026-09-06 17:14:21 +02:00
parent f55ef13c75
commit b3280df742
7 changed files with 386 additions and 1 deletions

View file

@ -1105,6 +1105,50 @@ registry/
A registry's own layout is not namespaced by registry name: within one
registry, an id is unambiguous by definition.
### 20.3 The index
A store MAY keep an `index.yaml` at its root recording which package versions
entered it, from where, and when:
```yaml
format: canned-prompt-index/v0.1
entries:
- registry: local
id: helix/repo-orient
version: 0.1.0
name: Repo Orientation
source: /home/worsch/helix-forge/prompts/repo-orient
method: add
included_at: "2026-09-06T13:31:02Z"
declared_author: Bernd Worsch
declared_source: personal prompt collection, contributed 2026-09-06
license: MIT
```
This is deliberately **not** package data. `provenance` (§ 13) records who wrote
a prompt and where the idea came from; the index records how a copy arrived in
*this* store — a fact about the store, not about the artifact, and one that
would differ for every consumer. Keeping it outside preserves immutability
(§ 17): recording an arrival never rewrites the package that arrived.
| Field | Meaning |
|---|---|
| `registry`, `id`, `version` | Which package version this entry is about |
| `source` | Where the copy came from: a path, a registry, a URL |
| `method` | How it arrived: `add`, `install`, `publish` |
| `included_at` | When it **first** entered this store |
| `last_seen_at` | When it was most recently re-recorded, if ever |
| `declared_author`, `declared_source` | Copied from the package's own `provenance`, so the index is readable without opening every package |
| `license` | Copied from the manifest, so licensing is visible in a listing |
`included_at` records first arrival and MUST NOT be overwritten when the same
`registry`/`id`/`version` is recorded again; a re-run updates `last_seen_at`
instead. When a package first entered a collection is a fact about history, not
about the last time someone ran a command.
Because identity is registry-scoped (§ 3.2), the same `id@version` from two
registries is two entries, not a conflict.
## 21. Reference CLI semantics
The reference tool uses two stores:
@ -1138,6 +1182,7 @@ satisfy.
```text
eval ID run an installed package's render checks
index [ID] show what entered this catalog, from where and when
```
`eval` runs the deterministic render checks of every recognized eval file and