Skip to content

Step 1a: pin sdlc: edition 1 (split from #169) #174

Open

Description

@Hafeok

This issue is the edition half of step 1, split out of #169, and it needs no other repository. It only reads decision-driven-design, at a public tag. This repository is the only one it writes to, and it needs no definition change: the definition already says "Pin the sdlc: edition and its shapes" (chapter 7, step 1; D1.1, D1.19, D1.20).

The lift ADR and the lift map stay in #169.

Read first

  1. decision-driven-design applications/sdlc/product-cli/product-definition.md at main: D1.1, D1.19, D1.20, chapter 5 (W1, W3, W4, W5) and chapter 7, step 1.
  2. decision-driven-design at the tag v0.6.0 (tag object bb47a720832c77f6a53c82b90388cd4a2c5c23bf, commit 1ab1de005eb60ce2ea019e9942cd52b790aab0e7):
    • what/ontology.ttl and what/shapes.ttl;
    • applications/sdlc/what.md §7.2;
    • core/decisions/DDD-dec-72.yaml, DDD-dec-91.yaml and DDD-dec-113.yaml.
  3. AGENTS.md, ADR-0002 to ADR-0007 and ADR-0013.

Deliverables (one PR)

1. ADR-0015 (the next free number; check before you write): pin sdlc: edition 1.

  • The pin:
    • owl:versionIRI https://decision-driven-design.dk/ns/sdlc/1;
    • the tag and its commit;
    • the edition hash per DDD-dec-72, as carried by DDD-dec-91: sha256 over ontology.ttl then shapes.ttl, bytes as tagged. Expected: sha256:a2006d9da588586bbf7ac19b3eec4861ff5a1aec0006a61784e9e0d842672f29. If the release descriptor at v0.6.0 says otherwise, the descriptor wins. Stop and report the difference.
  • The validation regime, as ruled in DDD-dec-113 E-1 (what.md §7.2): the data graph is what ∪ ontology, SHACL Core with SHACL-SPARQL, and no entailment.
  • The severity mapping: a violation is refused at write (W1, W5). A warning is a finding (W3, W4). A requirement added in a later edition enters as a warning (DDD-dec-113 E-2).
  • The embedding (A5):
    • the two files are embedded byte for byte as resources of the layer that owns the vocabulary, which the ADR names;
    • the build fails if their hash differs from the pin;
    • there is no runtime fetch.
  • Alternatives, each with why it is refused:
    • fetch at runtime;
    • vendor an edited copy;
    • pin by commit without a tag.
  • Consequences: a new edition is a new ADR. That ADR shows this edition's exports still import, validate and diff (hard constraint 8 of the project rules; definition D1.20).
  • Out of scope: running SHACL. The engine (Varve.Shacl, Varve.Shacl.Sparql) is a new package and comes with step 3's ADR.

2. The embedded files and the build check.

  • Copy the two files at v0.6.0 byte for byte, and record their source in the ADR.
  • The check runs in every build, not only in CI. If it needs a new MSBuild target or analyzer, it goes into the existing projects. It needs no new package. If you find it does need one, stop and ask.

3. Tests (C#, observing bytes, ADR-0006):

  • the embedded resources hash, in that order, to the pinned edition hash;
  • each embedded file is byte-identical to its source, by its sha256 recorded in the ADR;
  • a changed byte fails the build check. Show this in a test, without editing the real resource.

4. Release and record.

  • releases/v0.8.0-preview.4.yaml (the next free number; check first), naming the edition pin, with accepted-by left for Emil.
  • <Version> in Directory.Build.props set to match.
  • docs/traceability/<date>-issue-<this issue>-edition-1-pin.md.

Rules

  • Follow AGENTS.md:
    • signed commits as the agent identity;
    • Refs to this issue and a DCO sign-off;
    • no model identifier anywhere.
  • No suppression of any analyzer or rule.
  • Nothing under .github/ or eng/gates/ changes.
  • Nothing is written to decision-driven-design, Varve or Writ.

Done when

  • The PR is green.
  • ADR-0015 is accepted.
  • The descriptor names the edition pin.

Generated by Claude Code

Activity

  1. added
    claudeStart a Claude Code action session (Emil only); see AGENTS.md
    on Nov 12, 2026
  2. Hafeok commented on Nov 12, 2026

    @Hafeok
    CollaboratorAuthor

    Issue session plan

    Nothing is changed yet. This is the plan for the edition pin, for your approval. There are five questions at the end; each has my default, so approved alone takes the defaults.

    What I read

    • The start. The claude label on Step 1a: pin sdlc: edition 1 (split from #169) #174 was applied by Hafeok, with no app. There was no plan comment on the issue.
    • This repository, at main 528a1f8: AGENTS.md, ADR-0002 to ADR-0007, ADR-0013, docs/decisions/README.md, Directory.Build.props, Directory.Build.targets, Directory.Packages.props, .gitattributes, the Vocabulary project, the test harness (tests/Harness/), BuildPolicyTests, the probes under tests/fixtures/, tests/fixtures/ddd/SOURCE.md, releases/v0.8.0-preview.3.yaml, the add gates to agent.md #172 record, and Step 1b: the lift ADR and the lift map #169.
    • decision-driven-design at main (84aa466): the definition's D1.1, D1.9, D1.19, D1.20, chapter 5 (W1, W3, W4, W5), chapter 7 with step 1, and the cross-repository table.
    • decision-driven-design at v0.6.0: releases/v0.6.0.yaml, applications/sdlc/what.md §7.2, the header of shapes.ttl, the owl:Ontology block of ontology.ttl, and DDD-dec-72, DDD-dec-91 and DDD-dec-113.

    What I checked against the tag

    Fact Value Result
    Tag object of v0.6.0 bb47a720832c77f6a53c82b90388cd4a2c5c23bf as the issue says
    Its commit 1ab1de005eb60ce2ea019e9942cd52b790aab0e7 as the issue says
    owl:versionIRI in ontology.ttl https://decision-driven-design.dk/ns/sdlc/1 as the issue says
    Edition hash, sha256 over ontology.ttl then shapes.ttl sha256:a2006d9da588586bbf7ac19b3eec4861ff5a1aec0006a61784e9e0d842672f29 computed here; equals the issue, and equals the descriptor releases/v0.6.0.yaml at the tag
    ontology.ttl 30,473 bytes, blob 43dd6a6e, sha256 e640b80f6312eee9063921756fd727700b65886201d769e9f16639736554aa02
    shapes.ttl 27,647 bytes, blob 6fdbc9dc, sha256 89084dc5dad52abaa29c8fe6e859005b367cf78aac233105996c11e4ecdb2741

    The descriptor and the issue agree, so there is no difference to report. Both files are UTF-8 with line feeds only, and no carriage return.

    ADR-0015 and v0.8.0-preview.4 are both free on main, and no pull request is open.

    What I will change, file by file

    1. docs/decisions/ADR-0015-sdlc-edition-1-pin.md (new, status Proposed; accepting it is yours).

    • D1. The pin. The version IRI, the tag with its tag object and commit, the edition hash and its rule (DDD-dec-72, carried by DDD-dec-91), and each file's path at the tag, size, blob and sha256, as in the table above.
    • D2. The validation regime, as DDD-dec-113 E-1 and what.md §7.2 state it: the data graph is what ∪ ontology, in the default graph. SHACL Core class semantics with SHACL-SPARQL, and no RDFS or OWL entailment. The ontology never enters a What graph's hash or an export.
    • D3. The severity mapping. A violation is refused at write (W1, W5). A warning is a finding (W3, W4), reported and never refused. A requirement added in a later edition enters as a warning (E-2).
    • D4. The embedding. The two files are embedded resources of ProductCli.Vocabulary, layer 0, which ADR-0002 D1 gives "the edition". They are copied byte for byte. There is no runtime fetch.
    • D5. The build check. Every build of the project that embeds the edition hashes the two files, in order, and fails if the result differs from the pin (PCLI0006). It also fails if either file differs from its own sha256 (PCLI0007), so the message names the file.
    • Alternatives, each refused: a fetch at runtime; a vendored, edited copy; a pin by commit without a tag. Also two of my own: a check in CI only, and a hash check at run time in place of the build's.
    • Consequences. A new edition is a new ADR, which shows that this edition's exports still import, validate and diff (hard constraint 8; D1.20). The edition's files stay in the tree beside the new ones.
    • Out of scope. Running SHACL. Varve.Shacl and Varve.Shacl.Sparql come with step 3's ADR.

    2. src/ProductCli.Vocabulary/Edition/1/ontology.ttl and shapes.ttl (new). The two files at v0.6.0, byte for byte, written with git show from the tag.

    3. .gitattributes. One line, src/ProductCli.Vocabulary/Edition/** -text, as tests/fixtures/ddd/** already has, so that no checkout changes a byte.

    4. src/ProductCli.Vocabulary/Edition/1/edition.props (new). The pin, stated once for the build: the version IRI, the edition hash, the two files in order, and each file's sha256. The Vocabulary project and the test probe both import it.

    5. src/ProductCli.Vocabulary/ProductCli.Vocabulary.csproj. It imports edition.props and embeds the two files as resources, with fixed logical names.

    6. Directory.Build.targets. A new target, ProductCliEditionPin, beside ProductCliBuildPolicy.

    • It runs before every build of a project that declares edition files, with no inputs or outputs, so an incremental build never skips it.
    • The per-file hash uses MSBuild's own GetFileHash task.
    • The hash over the two files in order uses a small inline task (RoslynCodeTaskFactory, which ships with MSBuild). MSBuild has no built-in task that hashes two files as one stream. I tried it here, in a scratch directory: it gives sha256:a2006d9d… on SDK 10.0.404.
    • The target also writes the pin as constants into a generated source file under obj/, so the code and the build check read one statement of the pin.
    • No package is added.

    7. src/ProductCli.Vocabulary/SdlcEdition.cs and PublicAPI.Unshipped.txt. One public static class, SdlcEdition: the version IRI, the edition hash, and OpenOntology() and OpenShapes(), which return the embedded bytes as a stream. Nothing parses them here. (Question 3.)

    8. tests/fixtures/edition/ (new): ProductCli.EditionProbe.csproj with its two public API baselines. The probe imports the same edition.props and takes the directory of the two files as a property, so a test can point it at a changed copy.

    9. tests/Harness/Probe.cs. One method, Probe.Edition(directory), built as the other probes are.

    10. tests/ProductCli.Vocabulary.Tests/EditionTests.cs (new). All of them observe bytes (ADR-0006):

    • the embedded resources, read from the built assembly, hash in the order ontology then shapes to the pinned edition hash;
    • each embedded resource has the sha256 that ADR-0015 records. The test also reads the ADR file and finds the three hashes, the tag object and the commit in it, so the ADR and the test cannot drift apart;
    • each embedded resource equals its file in the tree, byte for byte;
    • the probe builds against an unchanged copy of the two files;
    • the probe fails with PCLI0006 and PCLI0007 against a copy with one byte changed, once for ontology.ttl and once for shapes.ttl. The copies are in a temporary directory, and the real resources are not touched;
    • the probe fails with PCLI0006 when the two files are given in the other order.

    11. AGENTS.md. The Packages section's list of build failures gains PCLI0006 and PCLI0007. The layer table's line for Vocabulary names the embedded edition and ADR-0015. Nothing else changes.

    12. releases/v0.8.0-preview.4.yaml (new), in the form of preview.3, with sdlc-edition: naming the version IRI, the edition hash and the tag, adr: "0015", and no accepted-by. Directory.Build.props: <Version> becomes 0.8.0-preview.4.

    13. docs/traceability/<date>-issue-174-edition-1-pin.md (new), naming the routine prompt's version 1.

    Nothing under .github/ or eng/gates/ changes. Nothing is written to decision-driven-design, Varve or Writ.

    The commits

    Each is signed as Claude (Emil), with Refs #174 and your sign-off, and each builds:

    1. docs(adr): ADR-0015, pin sdlc: edition 1
    2. feat(vocabulary): embed the sdlc: edition 1 files, byte for byte (items 2, 3, 4 and 5)
    3. build: fail the build when the edition's hash differs from the pin (items 6 and 7)
    4. test(vocabulary): the embedded edition hashes to the pin, and a changed byte fails the build (items 8, 9 and 10)
    5. docs: AGENTS.md names the edition pin and its build errors
    6. releases: v0.8.0-preview.4, the edition pin
    7. docs(traceability): the #174 session record

    The checks I will run

    • dotnet build ProductCli.slnx -c Release, then dotnet test -c Release --no-build.
    • dotnet publish of the host for linux-x64, then eng/gates/smoke.sh with the new version.
    • eng/gates/selftest.sh, eng/gates/commits.sh origin/main HEAD, and adr-shape, adr-text, no-toolchain and claude-workflow.
    • sha256sum of the two files in the tree against the table above, and git verify-commit on each commit.

    The other three runtime identifiers publish only in CI.

    Questions

    1. The paths. The issue names what/ontology.ttl and what/shapes.ttl. At v0.6.0 they are at applications/sdlc/what/. The repository root has no what/. I read the issue as naming those two files, and their hash matches. Is that right? My default: yes.
    2. "The embedding (A5)". I found no A5 in the definition, in AGENTS.md or in the ADRs. I read it as D1.20, and the ADR will cite D1.20. Tell me if it names something else.
    3. The public API. The plan adds SdlcEdition now, so that the pin is one named thing in code and the tests read the resources through it. The alternative is no public member in this step: the tests would read the resources from the built assembly's metadata, and the API would arrive with the shape engine in step 3. My default: add it now. If an analyzer rule of DecisionDriven.Analyzers refuses the class as written, I will stop and report it, and suppress nothing.
    4. The inline task. It needs no package, and it compiles a few lines of C# inside the build. The alternative is GetFileHash on each file alone, which pins the same bytes but never computes the edition hash itself. My default: both, as planned.
    5. The published binary. No code in the host reads the edition yet, so Native AOT trimming may leave the two resources out of product until step 3 uses them. This plan asserts on the built Vocabulary assembly, not on the published binary. My default: leave the binary's assertion to the step that first reads the edition, and say so in the ADR's consequences.

    Answers: label


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    claudeStart a Claude Code action session (Emil only); see AGENTS.md

    Type

    No type

    Fields

    Priority

    None yet

    Effort

    None yet

    Progress

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions