Repository navigation
Description
This issue is the session brief for the lift half of step 1 of the order of work (definition, chapter 7). The session posts its plan as a comment here and waits for approval.
Re-scoped 2026-11-12.
- Deliverable 0 landed as decision-driven-design
e037d8e(product-cli definition: edition 1 shipped in v0.6.0; D1.19 ruled, M-12 corrected, the table met decision-driven-design#65). - The edition pin moved to Step 1a: pin sdlc: edition 1 (split from #169) #174.
- Emil's rulings on Q1 to Q5 of the plan in comment 6685760600 are in his hand-typed comment on this issue, and they are folded in below. They amend D1.21, which is product-cli definition: amend D1.21 for the lift (rulings on product-cli#169) decision-driven-design#76.
This issue only reads decision-driven-design, at tags and at main. Once both blockers below are met, an issue session can plan it.
Do not start until all of these hold:
- decision-driven-design release
v0.6.0is cut and its tag verifies. It shipssdlc:edition 1, with edition hashsha256:a2006d9da588586bbf7ac19b3eec4861ff5a1aec0006a61784e9e0d842672f29unless the release's descriptor says otherwise; the descriptor wins. The rulings are DDD-dec-113, from sdlc edition 1, before the tag: state the validation regime, and separate refusals from findings decision-driven-design#49, sdlc edition 1, before the tag: the five §3.4 and §3.7 checks not yet in shapes.ttl decision-driven-design#50 and sdlc edition 1 for its tag: the validation regime, warnings, the five checks, mapsFrom; DDD-dec-113; v0.6.0 decision-driven-design#59; - applications/sdlc: the product-cli definition (Draft 4) beside the What it implements decision-driven-design#52 (the definition, Draft 4) is merged;
- the tag
rust-finalexists at70395dfinmindovermachine-dev/product-cli; - the first rewrite pull request has removed the Rust tree from
main(D1.24); - slice 0 is merged (D1.25): the eight layer projects, the layering analyzer, the AOT gate and the package register. Step 1 adds its projects and tests inside that skeleton and changes none of its gates;
- Step 1a: pin sdlc: edition 1 (split from #169) #174 (the edition pin) is merged;
- product-cli definition: amend D1.21 for the lift (rulings on product-cli#169) decision-driven-design#76 (D1.21 amended) has landed. Its commit is posted on this issue, and the
pf:targetsPlatformquestion is ruled there.
If any of these does not hold, stop and say which one.
Read first
In this order:
-
decision-driven-design
applications/sdlc/product-cli/product-definition.md, atmain: chapters 4, 5 and 7, and D1.1, D1.3, D1.16 to D1.21 (as amended by product-cli definition: amend D1.21 for the lift (rulings on product-cli#169) decision-driven-design#76) and D1.24. -
The accepted ADRs,
ADR-0001onward (ADR-0007 for repository discipline, ADR-0015 for the edition pin from Step 1a: pin sdlc: edition 1 (split from #169) #174). -
Emil's rulings comment on this issue, and the plan of 2026-11-06 (comment 6685760600) that it answers. Read the plan for its data only: the violation table, the Q3 counts and the Q4 term list.
-
decision-driven-design at the tag
v0.6.0:applications/sdlc/what.md, in full, including §2.3 and the appendix "where the source went";what/ontology.ttlandwhat/shapes.ttl;core/decisions/DDD-dec-63.yaml,DDD-dec-64.yaml,DDD-dec-72.yaml,DDD-dec-91.yaml(which supersedes 72),DDD-dec-73.yamlandDDD-dec-113.yaml(the edition-1 rulings: the regime, the severities, the five shapes, E-7 and E-8).
-
The lift input, read only:
mindovermachine-dev/product-cliat the tagrust-final(70395df):.product/products/product-cli/;schema/ontology/product-framework.ttl, for thepf:terms.
Read the Rust crates for behaviour only. Copy no line.
-
AGENTS.mdin this repository.
Plan first
Post a plan as a comment on this issue and wait for approval. The plan names:
- each file;
- each ADR number;
- the shape of the lift map, including its
authoredsection; - the derivation rules, and the list of authored rows you will propose;
- the wire-name rule you will propose;
- the tests.
Do not write files before approval.
Deliverables (one PR in product-cli)
1. ADR (the next free number): the lift (D1.4, D1.21, ADR-0009).
-
The frozen input:
- repository
mindovermachine-dev/product-cliat the tagrust-final(70395df); - command
product domain export --product product-cli; - RDFC-1.0 graph hash
sha256:ad855b900abd76bdc8a26d91ce995e267856dad8c47d15e1ee509f41c5d07e06, with 1,412 triples.
Bytes are not the pin: Rust's Turtle is not byte-stable across builds.
- repository
-
The mapping of old Framework sections to
what.mdsections, once, taken fromwhat.md's appendix. -
The term rules. Every
pf:class and predicate in the input is either mapped to ansdlc:term or dropped by name with a reason. The How kinds are dropped:ReificationRule,Cio, style and tokens,versionedAs,targetsPlatform.inContext,ownsDomain,ownsSystem,systemOf,journeyOfandboundedBybecomesdlc:within(P-2). -
The element rules:
- IRI subjects that are vocabulary are not minted (Q3):
- the 12
pf:Aiomap to base-set individuals, each as a reviewed row; - the 6
pf:WcagCriterionmap to their W3C IRIs; pf:Cio,pf:ReificationRuleandpf:DesignSystemsubjects are dropped as How or catalogue (DDD-dec-57);
- the 12
- every other IRI subject gets one minted
P/what/<ULID>, keyed in the map by its old IRI; - the 32 blank nodes become elements (P-3), each keyed in the map by (owning subject IRI, predicate, the node's own description, sorted). That key was checked unique over all 32 at the frozen graph hash, and the ADR states this, so the map needs no blank-node labels:
- the 15
pf:hasAttributenodes becomesdlc:Fieldelements:attrNamebecomesrdfs:label, andattrTypebecomessdlc:fieldType; - the 7
pf:offersand the 10pf:surfacesnodes, all on wireframe steps, becomesdlc:Interactionelements within their UI step. They keepcommandorprojection, andtypedAs(what.md§3.2.1);
- the 15
- the product IRI P is
https://decision-driven-design.dk/products/product-cli(Q2).
- IRI subjects that are vocabulary are not minted (Q3):
-
Derived and authored facts (Q1).
- Where the input determines a fact that edition 1 requires, the ADR states a derivation rule and the lift applies it. An example is an element's
sdlc:withinthat follows from its flow or owner. - Where the input doesn't determine it, the fact is an authored row in the map, adopted in review with its reference, exactly like wire names. The 2026-11-06 plan lists the cases:
- the domain or domains, and the systems' domain references;
- the two triggers that appear in two systems' flows;
- the missing labels;
- the flow entry pages, and the two flows with no step;
- the events behind each
pf:projectsedge; - the quality-demand statements;
rel-session-inphase-phase.
- Re-run the violation table against the lifted graph: every row must be covered by a rule or an authored row.
- Where the input determines a fact that edition 1 requires, the ADR states a derivation rule and the lift applies it. An example is an element's
-
The
pf:What terms without ansdlc:counterpart (Q4) are mapped or dropped as the 2026-11-06 plan proposes. The exception ispf:targetsPlatform, which follows product-cli definition: amend D1.21 for the lift (rulings on product-cli#169) decision-driven-design#76's ruling. -
The wire-name rule. The input carries none. State the rule that proposes them for every kind that requires one (
what.md§6, R-1, R-2). Review adopts each, and the adopted name is stored in the map with a reference to the review that adopted it. Lifting again therefore reproduces the golden bytes, wire names included. -
The two fixtures:
- the self-hosted What, for structure and surface;
- decision-driven-design's
acme-shop-5.ttlandvectors-5.jsonatv0.6.0, for behaviour (A6, as moved to-5by sdlc edition 1 for its tag: the validation regime, warnings, the five checks, mapsFrom; DDD-dec-113; v0.6.0 decision-driven-design#59). It carries no findings, so the fixture test asserts zero violations and zero warnings.
2. The lift map, lift/map-1.json, committed and never regenerated:
- the term table;
- the vocabulary rows (Q3);
- one row per input element, by the keys above: key, new IRI (the minted ULID, stored rather than minted on each run), label, and wire name with its adoption reference;
- the
authoredrows: subject, predicate, object, reason, and adoption reference; - the drop list.
ULIDs are minted once, here, and stored. The lift reads them from the map and never mints. The map is input to step 3 and is not used by the product.
3. Tests (C#, observing bytes, ADR-0006):
- the lift map covers the frozen input: every subject and every
pf:term is mapped or dropped, and nothing in the map is absent from the input; - every minted IRI matches the identity shape's pattern;
- wire names are unique per kind, and within each owner for fields;
- every authored row and every vocabulary row has an adoption reference.
These tests read the input by its frozen hash. A changed input fails them.
Stubs: none expected. List any you need in the PR.
Rules
- Commits:
- signed, as the agent identity, with no model identifier in any commit or record;
Refs #Nand a DCO sign-off;- a traceability record for the session.
- No suppression of any analyzer or rule.
- Package versions come from nuget.org, never from memory. Each new package needs an ADR with an
Adr=entry in the register. - Nothing is written to decision-driven-design, Varve or Writ. A gap found there is an issue in that repository, linked from the PR.
- Nothing under
.github/oreng/gates/changes. - ADRs are files under the interim rule (A7) until Milestone: First slice — the C# file projector and the layer rule Hafeok/writ#7 exists.
Done when
- The PR is green.
- The lift ADR is accepted.
- The map is reviewed, and its wire names, vocabulary rows and authored rows are adopted.
- The release descriptor (the next free preview) names the lift input hash and the map.
Reconciliation
If another session lands first:
- merge
main; - re-run the tests;
- if that session touched the edition pin or the map, stop and ask.
Generated by Claude Code
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Effort
Progress
Activity
Hafeok commentedon Nov 6, 2026
Plan for step 1: edition 1 pin, the lift ADR and the lift map
I have written no files yet. I am waiting for approval, and for rulings on Q1 to Q5 at the end. Q1 blocks the map.
Preconditions: all hold (checked 2026-11-06)
v0.6.0cut and verifiedbb47a72on1ab1de0. GitHub reportsverified: true(valid). The descriptor's edition hash issha256:a2006d9d…2f29. I recomputed it from the taggedontology.ttlthenshapes.ttland got the same value.rust-finalat70395dfd0cf1f1, commit70395dfe…main(D1.24)mainholds no Rust filesmainis at4ce90e9The lift input reproduces. I parsed
.product/products/product-cli/product-cli.ttlatrust-finalwith pyoxigraph, in the scratchpad only, and computed its RDFC-1.0 hash. It issha256:ad855b90…7e06: 1,412 triples, 289 subjects, 32 blank nodes. That matches the frozen input.I also checked the blank-node key (owner IRI, predicate, sorted description):
Deliverable 0: decision-driven-design, one PR, first
applications/sdlc/product-cli/product-definition.md.Refs #49,Refs #50,Basis: DDD-dec-113; DDD-dec-73; DDD-dec-72and the DCO.python3 scripts/ci.pypasses before I push.If Q1 is ruled (a), this PR gains a second edit. See Q1.
Deliverables 1 to 4: product-cli, one PR, after deliverable 0 lands
ADRs. Both are written as
Proposed. A session never writesaccepted-by.docs/decisions/ADR-0014-sdlc-edition-1-pin.md. It covers:owl:versionIRI …/sdlc/1, the tagv0.6.0(bb47a72on1ab1de0), and the edition hash perDDD-dec-72as carried byDDD-dec-91;DDD-dec-113E-1: the data graph iswhat ∪ ontology, SHACL Core class semantics with SHACL-SPARQL, no entailment, and the ontology is never hashed;docs/decisions/ADR-0015-the-lift.md(D1.4, D1.21). It covers everything in deliverable 2:what.mdtable, taken once from the appendix;It also amends ADR-0009 D1 and D2, naming them (ADR-0001 D3). ADR-0009 put the outputs at
tools/migrate-pfandfixtures/self-hosted/, as a separate term map and IRI map. The single map is nowlift/map-1.json. The lift tool itself arrives at step 3.The edition, embedded (layer 0):
src/ProductCli.Vocabulary/Edition/sdlc-1/ontology.ttlandshapes.ttl, byte copies fromv0.6.0, with aSOURCE.mdrecording the tag, commit and sha256s..gitattributesmarks them-text.EmbeddedResourceitems inProductCli.Vocabulary.csproj.eng/Edition.targets:RoslynCodeTaskFactorytask, so no package is added;PCLI0006when the result differs from the pin (PCLI0001toPCLI0005are taken);SdlcEditionVersionIriandSdlcEditionHash.The lift input and the map:
lift/input/product-cli.ttl, the committed file's bytes atrust-final,-text. The pin is the graph hash, not the bytes: any isomorphic export passes.lift/input/SOURCE.mdrecords the blob and commit.lift/map-1.json, written once and never regenerated. Its shape:{ "format": "product-cli/lift-map/1", "input": { "repository", "tag": "rust-final", "commit", "command", "graphHash", "triples": 1412, "subjects": 289, "blankNodes": 32 }, "edition": { "versionIRI", "hash" }, "product": "<P>", // Q2 "terms": [ { "pf": "<iri>", "sdlc": "<iri>", "rule": "rename | within (P-2) | value-map | object-rewrite", "values"?: {…}, "reason" } ], "drops": [ { "pf": "<iri>", "reason": "…" } ], // classes and predicates dropped by name "elements": [ // one row per input element, sorted by key { "key": { "iri": "<old IRI>" } | { "owner": "<old IRI>", "predicate": "<pf iri>", "description": [["<p>","<o as N-Triples>"], …] }, "kind": "sdlc:…", "iri": "P/what/<ULID>", "label": "…", "wireName"?: { "name": "…", "adoptedBy": "<review URL>" } } ], "vocabulary": [ { "key": { "iri": "<old IRI>" }, "sdlc": "<individual or W3C IRI>", "reason" } ], // Q3 "droppedSubjects": [ { "key": { "iri": "<old IRI>" }, "reason" } ], "authored": [ { "subject", "predicate", "object", "reason", "adoptedBy" } ] // Q1 }what/mint.pyatv0.6.0, run in the scratchpad, since no Python goes in the tree. The record states this. The lift reads the ULIDs from the map and never mints.adoptedByabsent. After your review, a second commit fills eachadoptedBywith the review comment's URL.The wire-name rule. A wire name is the lifted
rdfs:label, lowercased, with each run of characters outside[a-z0-9]replaced by-, and trimmed. Examples:Add Bounded Contextbecomesadd-bounded-context, andInitialize Agent Contextbecomesinitialize-agent-context.WireNameShapeandFieldWireNameShaperequire, per R-1 and R-2. In the input that is:WireNameShapetargets every invariant atsh:Violation, not only those in rejections.The tests. All are C# and observe bytes (ADR-0006).
tests/ProductCli.Vocabulary.Tests/EditionTests.cs:ProductCli.Vocabulary.dllequal theEdition/files byte for byte;ontology.ttlthenshapes.ttlequals the pin;ontology.ttldeclaresowl:versionIRI <…/sdlc/1>, parsed with Varve.Turtle.BuildPolicyTests, a new planted case: a probe whoseshapes.ttlhas one byte changed fails withPCLI0006.tests/Lift.Tests/: a new test project inProductCli.slnx, using Varve.Rdf and Varve.Turtle, which are already admitted withScope="tests/". So: no new package and no stubs.LiftInputTests: the RDFC-1.0 hash equals the pin, with 1,412 triples, 289 subjects and 32 blank nodes. Every other lift test first loads the input through this check, so a changed input fails them all.LiftMapCoverageTests:elements,vocabularyordroppedSubjects;pf:class and predicate is intermsordrops;LiftMapIdentityTests: every minted IRI matchesElementIdentityShape'ssh:pattern, read from the embeddedshapes.ttlrather than retyped, and starts with P. IRIs are unique.WireNameTests:WireNameShape's token pattern and is unique per kind;authoredrow, has anadoptedBy. This fails until review adopts them, which is what "done" requires.Also in this PR:
AGENTS.md: thelift/directory, the edition embedding andPCLI0006.releases/v0.8.0-preview.3.yaml, naming the edition pin and the lift input hash.docs/traceability/2026-11-06-issue-169-edition-1-and-lift.md.Commits. Each is signed as the agent, with
Refs #169and the DCO:PCLI0006and their tests;AGENTS.mdand the record.Findings that need a ruling
Q1, blocking: the golden fixture cannot be violation-free from term and element rules alone.
I lifted the input naively in the scratchpad, applying only the rules in the brief plus the obvious renames. I ran edition 1's shapes over it under the E-1 regime (pyshacl,
what ∪ ontology, no inference). The result is 167 violations from 8 shapes:rdfs:labelpf:ownsDomainpoints at bounded contextsreferencesDomainpf:projectsis View → Entity, whilesdlc:projectsis View → Eventpf:boundexistsrel-session-inphase-phasepointstoa value objectSome of these are derivable, for example a step within the system of its flow or root. Others need a choice:
t-renderandt-open-viewsit in flows of two systems;D1.21 makes only wire names authored, so the map has nowhere to record these choices. I propose (a): the map gains the
authoredsection above. Each row is adopted in review with its reference, the same mechanism as wire names. D1.21 is amended to allow it, in deliverable 0 as one added clause. Lifting again then still reproduces the golden bytes.The alternative is (b): a separate definition PR before the product-cli PR. Deliverable 0 says "change nothing else", so I need your ruling on which.
Q2: the product IRI P. The old IRI is
https://productframework.org/product/product-cli, and acme useshttps://acme.example/products/shop. Options:https://decision-driven-design.dk/products/product-cli;I won't choose one.
Q3: IRI subjects that are not elements under
sdlc:. The brief says each IRI subject gets a ULID, butwhat.md§3.2.2 and §3.2.3 make some of these vocabulary:pf:Aio: I propose each maps to a base-set individual, for exampleaio-nav-tabstosdlc:aioNavigate. Each choice is a reviewed row.pf:WcagCriterion: each maps to its W3C IRI, for example#contrast-minimum. Nothing is re-minted under P.DDD-dec-57): 11Cio, 12ReificationRuleand 2DesignSystem. The self-hosted What then declares no design-system target, because aDeclaredTargetneeds an edition reference the input lacks.That leaves 213 minted IRI elements and 32 blank-node elements, plus P.
Q4:
pf:What terms with nosdlc:counterpart. ADR-0009 D4, as amended, fails the lift on an unmapped What term. The brief rules only the How drops. I will put each of these in the map with a proposed reason, for you to confirm or send to decision-driven-design as an edition question:pf:projectspf:displays,pf:triggerspf:containssdlc:inFlowfor steps; dropped for commands, events and viewspf:appliesTo,pf:identity,pf:means,pf:contextValue,pf:constrainsconstrainspoints at two IRIs that are not subjectspf:level,pf:verification,pf:satisfiedDDD-dec-52)pf:mappingKindpf:mustSatisfyon an AIOpf:targetsPlatformsdlc:targetsContextis documented as its generalisationQ5: the behaviour fixture's test. It needs a SHACL engine,
Varve.ShaclandVarve.Shacl.Sparql, which is a new package and so an ADR. I read it as step 3, where the fixtures are imported. In step 1, ADR-0015 states the fixture and its zero-violation, zero-warning assertion, andacme-shop-5.ttlis not vendored yet. Is that right?Generated by Claude Code
Hafeok commentedon Nov 9, 2026
Numbering update to the plan above. #171 takes
ADR-0014andv0.8.0-preview.3, so this step shifts:v0.8.0-preview.4.When I write the files, I will take whichever numbers are free at that point. I will rebase onto #171 and record the reconciliation in the session record (ADR-0007 D5).
Nothing else changes in the plan, and Q1 to Q5 are still open.
Generated by Claude Code
product-cli definition: edition 1 shipped in v0.6.0; D1.19 ruled, M-1…
product-cli definition: edition 1 shipped in v0.6.0; D1.19 ruled, M-1…
sdlc.md §19: O-8 (accepting the realisation plan) and O-9 (product-cl…
sdlc.md §19: O-8 (accepting the realisation plan) and O-9 (product-cl…
docs(traceability): #169 record, Round 5 and the #66 rebase onto e037d8e
Hafeok commentedon Nov 11, 2026
No plan posted: this issue needs a definition change in decision-driven-design first, so a normal session must do it.
The issue-session prompt (version 1) and
AGENTS.mdboth rule this out for an issue session. I changed no file, made no commit and pushed nothing.The start
The start checks passed: the
claudelabel was applied by hand byHafeokon 2026-11-11, it is still on the issue, and no plan comment withAnswers: labelexisted.What holds
e037d8e(product-cli definition: edition 1 shipped in v0.6.0; D1.19 ruled, M-12 corrected, the table met decision-driven-design#65, merged 2026-11-09). The cross-repository part of the brief is done.ontology.ttlthenshapes.ttlatv0.6.0(bb47a72on1ab1de0) issha256:a2006d9d…2f29.product-cli.ttlatrust-final(70395df) has 1,412 triples and 289 subjects, of which 32 are blank nodes.What blocks the lift map
D1.21 has not changed since deliverable 0, and under it the map cannot be written so that the golden fixture "carries no violation under its edition". D1.21 lets the map hold terms, ULIDs and wire names only. I re-checked the input against edition 1's shapes, and it needs facts that none of those can carry:
BoundedContextShape)pf:ownsDomainedges point from the product to a bounded contextViewShape)pf:projectsedges point from a read model to an entityKindNeedsContainerShape)rdfs:labelon 33 invariants and 3 context mappingsThis is Q1 of the plan of 2026-11-06 (comment 6685760600), and it is still unruled. Both of its options change D1.21. Q3 does too: D1.21 gives every IRI subject a minted ULID, but 12
Aioand 6WcagCriterionsubjects are vocabulary underwhat.md, and 25 more are How. Q2 (the product IRI P), Q4 and Q5 are also open, but they can be answered on this issue.What a normal session needs
e037d8e.One part does not depend on any of this
The edition half needs no definition change and no other repository: the pin ADR, the two embedded files, the build-time hash check and their tests. If you split it into its own issue, an issue session can plan it. Numbering has moved since the note of 2026-11-09:
ADR-0015is the next free ADR, andv0.8.0-preview.3is taken, so the next descriptor isv0.8.0-preview.4.Generated by Claude Code
[-]Step 1: pin sdlc: edition 1, the lift ADR and the lift map[/-][+]Step 1b: the lift ADR and the lift map[/+]Hafeok commentedon Nov 12, 2026
Rulings on Q1–Q5 of the plan in comment 6685760600:
Q1: (a), refined. The lift ADR states derivation rules for every fact the input determines (e.g. sdlc:within from an element's flow or owner). Only facts the input does not determine become rows in the map's
authoredsection, each adopted in review with its reference, like wire names. D1.21 is amended for this in mindovermachine-dev/decision-driven-design#76.Q2: P = https://decision-driven-design.dk/products/product-cli
Q3: as proposed. Aio → base-set individuals (reviewed rows), WcagCriterion → W3C IRIs, Cio/ReificationRule/DesignSystem dropped.
Q4: as proposed, except pf:targetsPlatform: ruled in mindovermachine-dev/decision-driven-design#76, not dropped here.
Q5: as proposed. SHACL engine and its ADR belong to step 3; step 1 only states the fixture's zero-findings assertion.
The edition pin moves to #174. This issue is now the lift only.