Packages

development-driven-specs — the dds toolchain (protocol 2) as a Mix task. A thin shim over the bundled instruments (Python, stdlib); never a port.

Current section

Files

Jump to
dds priv toolchain migrations 0.11.0.md
Raw

priv/toolchain/migrations/0.11.0.md

# 0.11.0 — protocol 2: the tree-grain format generation
This version moves the repo to **protocol 2** (the protocol spec in
the framework repo): explicit class declarations, the claim-file facet
law, strict bare-list JSON, the stamped witness, and the walk-carried
register parse. The firmness contract applies throughout: reshape
structure freely; never alter a human's content bytes — surface every
conflict.
## 1. Pin the protocol
Append to `.dds-version` (the carried asset shows the shape):
protocol: 2
The check verdicts its presence from now on.
## 2. Risk files gain `Class:` declarations
The keyword-substring binding is gone; risk files now DECLARE their
fact classes. For each `docs/risks/<id>.md`, derive the seed from the
old rule — a class is seeded when any of its keywords is a substring
of the risk's id or of any covering ADR's `Risk:`/`Concern:` trailer
value:
| class | seed keywords |
|---|---|
| gating | `authoriz` · `access` |
| erasure | `retention` · `minimiz` · `erasure` |
| audit | `audit` · `account` |
| surface | `authentication` · `identity` |
| credential | `credential` · `secret` |
Write the seeded `Class: <name>` lines at the file end (before
`Addressed by:`). The seeds are DERIVED, so writing them is mechanical
— but the human reviews them in the migration PR: a wrongly-seeded
class is exactly the fragility this migration removes.
## 3. Trailer shape
- Collapse multiple `Addressed by:` lines into one (comma-separated).
- Strip backticks from `Addressed by:` values — bare stems.
- Remove any remaining `## Validation question` section. Its text is
CONTENT: quote each removed section verbatim in the hand-off (and
the migration commit body) — removed from the file, never silently
discarded.
## 4. The JSON side-files retire (holdings + class-signals)
Judgment lives in markdown; the register world's two JSON side-files
were judgment stored in machine format, and both retire.
**`docs/registers/holdings.json`** — for each pin
`{store, column, datum_key}`, append a line to the datum's own section
(`docs/registers/subjects/<subject>.md`), under its facet table:
Held by:
- <store>.<column> [<file> | "<the column's declaring line>"]
taking the declaring quote from the witnessed schema (the witness /
extraction record for the store's file). This is mechanical — every
pin already names its ratified datum, and the evidence is the
witness's, not a new judgment. Then DELETE the file. From here on the
holdings view is DERIVED from the ratified ledger lines every run;
new mappings enter only as `°`-drafted ledger lines a human merges.
**`docs/registers/class-signals.json`** — move each entry into the
`## Signals` ledger of the risk that declares its `class` (shape:
`- <text> [<file> | "<quote>"]` — the text/file/quote fields map
one-to-one), then delete the file. An entry whose class no risk
declares needs its risk created (or the class declared on the covering
risk) — surface it, never drop it.
After this step the committed register state is 100% markdown; the
check reports either file's continued presence as a structural
finding.
## 5. The witness stamp
- **Mechanical platforms**: nothing committed — CI regenerates the
witness; the new `witness.py` stamps `protocol: 2` and
`mode: "mechanical"` itself. If a legacy `witness.json` is still
committed, delete it and confirm `.gitignore` covers it.
- **LLM-extracted platforms**: the committed witness must carry
`protocol: 2` and `mode: "extracted"`. Adding the two fields to an
otherwise-current witness is mechanical (the facts and quotes are
untouched); if the witness is stale, run `/dds-sync` to regenerate
instead.
- Facts overlays now REQUIRE a `kind` field
(`store`·`router`·`secrets`·`empty`·`degraded`) — see
`extraction.md`.
## 6. The facet law
Run `/dds-check`. Datums missing a required facet row
(`Identifiability`, `Category`, `Provenance` — plus `Source party`
when provided) now surface as structural findings. Adding a missing
ROW with the value `needs-ratification` is mechanical scaffolding (an
honest hole); writing a VALUE is judgment — leave that to a human or
to `/dds-sync`'s evidenced drafting.
## 7. Declare the obligations
The `Regime:` and `Scope:` lines in `docs/governance.md` are now
machine-read (each token names a carried profile; unknown tokens are
findings; `TODO` degrades to core-only, honestly). Declare what
governs — e.g.:
Regime: gdpr
Scope: confidentiality
Declaring is a judgment: it lands in the migration PR for review like
everything else. Person subjects may declare `Kind` explicitly
(default `person`); tenant/system data enters as `organization` /
`internal` subjects whose datums carry `Classification` (and
optionally `Concern`) instead of the person facets.
## 8. Canon divergences replace `.dds-overrides`
Local canon edits are now DECLARED (`conventions.md` §12), and the
check verdicts canon conformance continuously:
- For each path listed in `.dds-overrides` (if any): either wrap its
local edits as `dds-divergence` blocks (anchored, with a `why:`), or
mark the file wholly local (`<!-- dds-divergence file why: … -->`),
or revert it to canon. Then DELETE `.dds-overrides`.
- Canon files with undeclared local edits will report as
`undeclared canon drift` — declare or revert each before merging
the migration PR.
## 9. Confirm
Run `/dds-check`. Expect: the protocol line verdicts clean, the
coverage table binds through the new `Class:` declarations (compare
its rows against the pre-migration run — membership should be
reviewed, not assumed identical), and the walk JSON now carries
`protocol: 2` plus the `register` section. Downstream (the portal)
ingests only that artifact from here on.