Skip to content

D1.24: remove the Rust tree from main #165

Closed

Description

@Hafeok

The first rewrite pull request, as the product definition rules in D1.24`` (Draft 4, 2026-11-03, decision-driven-design fcda5ed):

The first rewrite pull request removes the Rust tree from main, .decisions/ included. From then on, main holds the rewrite alone: one toolchain, one CI and one AGENTS.md.

The Rust workspace is frozen at the tag rust-final: tag object d0cf1f1ec40eb55c271b8d4dadfefcd260c03312, pointing at commit 70395dfe317cb9a00665433813766ca763f3c58a. GitHub reports it verified (valid). Everything removed stays readable there, and nothing at the tag changes.

Scope:

  • remove the Rust tree;
  • add AGENTS.md, CLAUDE.md, README.md, LICENSE (Apache-2.0) and NOTICE;
  • add ADR-0001 to ADR-0012 under docs/decisions/ (D1.22), the session's traceability record, a release descriptor, and gates.yml;
  • close out the Rust tool's open PRs and issues.

The plan follows as a comment, for approval before any file is written.

Activity

  1. Hafeok commented on Nov 3, 2026

    @Hafeok
    CollaboratorAuthor

    Plan, for approval

    No file is written until you approve. The plan has nine parts:

    • §0 the preconditions I checked;
    • §1 to §6 the PR (claude/lucid-hamilton-jxk6pv, Refs #165), one commit per numbered item;
    • §7 the decision-driven-design PR;
    • §8 the dispositions;
    • §9 questions.

    0. Preconditions, checked

    • rust-final on GitHub is tag object d0cf1f1ec40eb55c271b8d4dadfefcd260c03312. It points at 70395dfe317cb9a00665433813766ca763f3c58a, and GitHub reports verified: true, reason: valid.
    • origin/main is 70395dfe317cb9a00665433813766ca763f3c58a.
    • product-cli-adrs.md is in hand. The PR copies it unchanged and adds no ADR text of its own.
    • I read:
      • the definition at decision-driven-design fcda5ed (Draft 4, all of it);
      • Writ 6737ac9 ADR 0008 and docs/traceability/;
      • Varve 3024c7a AGENTS.md, eng/ and releases/ with docs/releases.md;
      • this repository at 70395df.

    1. Removal: one commit, nothing edited first

    chore: remove the Rust tree from main (D1.24) deletes these paths, with their tracked file counts at 70395df (1,935 of 1,939 files):

    • Workspace and crates:
      • Cargo.toml (1), rust-toolchain.toml (1), deny.toml (1), dist-workspace.toml (1), .cargo/ (1), xtask/ (11), dagger/ (6);
      • product-core/ (232), product-mcp/ (115), product-cli/ (93);
      • ddd-core/ (48), ddd-lsp/ (36), ddd-mcp/ (15), ddd-cli/ (106);
      • ledger/ (30), ledger-core/ (143), ledger-cli/ (114);
      • spec-core/ (31), spec-cli/ (24), spec-mcp/ (8), spec-flow/ (43, .NET);
      • eval-core/ (25), eval-dotnet/ (24, .NET), ground-cli/ (8).
      • There is no Cargo.lock at 70395df, so there is nothing to remove for it.
    • Content: schema/ (28), spec/ (38), conventions/ (12), examples/ (2), scripts/ (13), docs/ (58).
    • Stores and agent configuration: .product/ (53), .decisions/ (189), .ddd/ (411), .claude/ (7), .mcp.json, .htmlvalidate.json, .stylelintrc.json.
    • CI: .github/workflows/product-ci.yml, publish-mcp.yml and release.yml.
    • CLAUDE.md.
    • Beyond your list. These two paths are not in the brief, but "main contains only what deliverable 2 adds" requires removing them:
      • .gitignore;
      • .github/copilot-instructions.md. AGENTS.md becomes the single source for agents.
    • Kept in this commit and replaced later: LICENSE and README.md. Each is rewritten in its own commit (§2), so the relicensing and the README rewrite each show as a diff.

    2. Additions, in this order

    1. docs: AGENTS.md, the single source for agents (ADR-0007). It covers:

      • what the repository is: the tool, its ADRs and its tests;
      • where the definition lives, and that a definition change merges in decision-driven-design first, with its commit cited here (D1.24);
      • the gates, and how to run them locally;
      • commit rules:
        • signed;
        • Refs #N;
        • Signed-off-by: Emil Okkels Klein <emil@okkels-klein.dk>;
        • no model identifier anywhere, Co-Authored-By trailers and author names included;
        • Claude-Session: kept, as in Writ, because it is a session URL and names no model;
      • the session record (ADR-0007 D2);
      • the never list (question 1).
    2. docs: CLAUDE.md points to AGENTS.md: one line.

    3. docs: README.md for the rewrite:

      • two paragraphs from chapter 1: the promise and its consequences;
      • that the Rust tool is frozen at rust-final and its published releases (through v0.7.0) keep working;
      • a link to the definition.
    4. licence: Apache-2.0 replaces MIT; add NOTICE:

      • LICENSE is the canonical Apache-2.0 text from apache.org, unedited;
      • NOTICE names the copyright holder, and states that everything at rust-final and before remains under the MIT licence it was published with.
      • The PR states this, and asks you to confirm the relicensing in review as the holder named in the MIT file ("Emil Klein").
    5. docs(decisions): the collected ADR text of 2026-11-03 adds docs/decisions/collected-2026-11-03.md, byte-identical to the attachment. The PR states its sha256.

    6. docs(decisions): ADR-0001 to ADR-0012, split from the collected file adds the twelve file names from the brief.

      • Each file is its section: ## ADR-… becomes # ADR-…, and ### … becomes ## …. Nothing else changes, including the trailing newline. The --- separators belong between sections, so no file carries one.
    7. docs(decisions): the Draft 4 notes on ADR-0001, 0008, 0009 and 0011. This is a separate commit, so the notes are a reviewable diff on top of the verbatim split.

      • Each note sits after the status lines and before ## Context.
      • Its text is the preamble's bullet with the **ADR-NNNN.** lead removed and its sub-bullets de-indented one level. For example:
        > **Note (2026-11-03, Draft 4)**
        >
        > D1 now reads `docs/decisions/ADR-####-<slug>.md` (D1.22). The first PR carries ADR-0001 to ADR-0012.
        
    8. docs(decisions): README, the interim rule (D1.22). It says:

    9. ci: gates.yml with the checks in eng/gates/. They are Bash plus git, jq and curl, which the runner has, so they add no toolchain file. Five jobs run on every pull_request against main, with permissions: contents: read, pull-requests: read:

      • commits, over every commit in base..head, checks:

        • a Refs #N line;
        • a well-formed Signed-off-by: naming a person, never a noreply or agent address;
        • no model identifier in the message, the author or committer name or email, or any trailer. The pattern covers vendor model ids (claude-…, gpt-…, gemini-…, o1/o3/o4-style, llama…, mistral…), the product family names followed by a version number, and any Co-Authored-By: naming an AI vendor address. Claude (Emil) and Claude-Session: pass.
      • signatures reads each PR commit's verification from the REST API and fails on any verified: false, printing the reason.

      • adr-shape checks each docs/decisions/ADR-NNNN-*.md:

        • an H1 # ADR-NNNN: … whose number matches the file name;
        • a **Status:** line;
        • ## Alternatives considered;
        • ## Consequences.

        Any other file in the directory fails, except README.md and collected-*.md, so nothing escapes the shape check by its name.

      • adr-text rebuilds each ADR file from the collected file and compares bytes. It takes the section, promotes its headings outside code fences, and inserts the preamble's note for the four noted ADRs. It fails on any byte difference, on a note in any other ADR, or on a missing note.

      • no-toolchain fails if any Rust, Node or Python toolchain file is at the root:

        • Rust: Cargo.toml, Cargo.lock, rust-toolchain, rust-toolchain.toml, .cargo/;
        • Node: package.json, the npm, yarn, pnpm and bun lockfiles, pnpm-workspace.yaml, .nvmrc, .node-version, deno.json;
        • Python: pyproject.toml, setup.py, setup.cfg, requirements*.txt, Pipfile, Pipfile.lock, poetry.lock, uv.lock, .python-version, tox.ini;
        • and .tool-versions.

      A sixth job, selftest, plants a failing case for each check in a scratch repository on the runner and passes only if every check fails on its case. It keeps the "fails on a planted case" property on every run. The red runs to show in the PR are in question 3.

      • CI kept: none. CI added: gates.yml only.
      • No .NET solution, project, global.json or SDK pin. Those come in slice 0 (ADR-0002/0003/0004).
    10. releases: <descriptor> in Varve's shape (format: 1, version, title, date, basis, summary).

      • basis names issue 165, rust-final (tag object d0cf1f1…, commit 70395df), and the edition: sdlc: edition 1, owl:versionIRI <https://decision-driven-design.dk/ns/sdlc/1>, hash pending until decision-driven-design tags it (D1.20).
      • The summary says no Rust release follows rust-final. The tool's last Rust release is v0.7.0.
      • No accepted-by: that line is yours. The version is question 4.
    11. docs(traceability): 2026-11-03-issue-165-rust-removal.md, in Writ's shape. It holds:

      • the prompt, verbatim;
      • the tool;
      • what was read, with SHAs;
      • the approved plan;
      • the commits;
      • the checks and their results;
      • deviations, with reasons.

      The model field is question 2.

    3. Gate, reported in the PR

    • gates.yml is green on the head.
    • Every SHA's verification is read through the API and pasted in.
    • git ls-tree -r --name-only HEAD is pasted in. It should list only:
      • AGENTS.md, CLAUDE.md, README.md, LICENSE, NOTICE;
      • docs/decisions/ (twelve ADRs, the collected file, README.md);
      • docs/traceability/…;
      • releases/…;
      • .github/workflows/gates.yml;
      • eng/gates/*.
    • The description says the removed tree stays readable at rust-final, and that MIT governs everything there.

    4. decision-driven-design: one commit, signed, Basis: DDD-dec-72, not merged by me

    In applications/sdlc/product-cli/product-definition.md:

    • Header: "Draft 4 adds D1.16 to D1.24" becomes "… D1.16 to D1.25". The sentence "D1.24 supersedes D1.23." becomes "D1.24 supersedes D1.23, and D1.25 adds step 0 to the order of work."
    • Table:
      • the rust-final row becomes **met**: tag object d0cf1f1ec40eb55c271b8d4dadfefcd260c03312;
      • a new row follows it: | D1.24 | the Rust tree removed from main | product-cli | … |, either met with the merge SHA or in review with the PR number (question 5);
      • the README row is unchanged.
    • Chapter 7: step 0 goes in as the new first item, verbatim from the brief.
    • I run python3 scripts/ci.py green after pip install -r scripts/requirements.txt.

    5. Disposition: executed only after you approve this list

    PRs: close unmerged, and delete no branch. These are #143 and #154 to #164 (12 PRs). Each gets this comment:

    Closed unmerged under D1.24: the Rust tree left main in #, and this branch's work stays readable at rust-final and on its branch. The ledger is Writ's authority graph now (definition chapter 8); writ import reads .decisions/ once, at the tag.

    Issues: close as not carried (30). Each gets a comment citing D1.24 and chapter 8, and is closed not_planned.

    Issues: propose re-filing (2). I re-file nothing myself and leave both open for you.

    6. Questions

    1. The never list. I don't hold the Product-Cli project prompt, only this session's prompt. Unless you paste its constraints, I'll draft the list from:

      • this prompt's Rules;
      • chapter 7's Constraints;
      • chapter 8's "Not in scope" and "No authority, ever";
      • W10;
      • ADR-0006 and ADR-0007.
    2. The model in the traceability record. Writ's shape names the model, but this session may write no model identifier into anything pushed. I propose to use ADR 0008's own provision: the record states the tool will not write it, and you fill it in.

    3. Real red runs. The planted cases need commits that break the rules on purpose (no Refs, no sign-off, a fake model id such as gpt-planted-0), plus a malformed ADR, an edited ADR byte and a root Cargo.toml. The commits are still signed with this key. The signature case is signed but committed as planted@example.invalid, so GitHub reports it unverified. My proposal:

      • seven branches planted/<check> off the PR head;
      • one draft PR to main each, closed after its red run;
      • the run links pasted in the PR;
      • branches kept.

      That needs your permission to push those branches. The alternative is selftest evidence only.

    4. The descriptor's version. It must follow v0.7.0. I propose releases/v0.8.0-preview.1.yaml, with nothing cut until slice 0 brings a release path. Or would you rather start the rewrite at v1.0.0-preview.1?

    5. The decision-driven-design PR's single commit. If that PR opens before your merge here, updating the row afterwards means a second commit, because I won't rewrite the branch. I propose to open it right after your merge, with the row met and the merge SHA, in one commit. If you want it open earlier, I'll mark the row "in review" and add the update as a second commit.


    Generated by Claude Code

  2. Hafeok commented on Nov 3, 2026

    @Hafeok
    CollaboratorAuthor

    Outcome

    This issue stays open for you to close.


    Generated by Claude Code

  3. Hafeok commented on Nov 3, 2026

    @Hafeok
    CollaboratorAuthor

    Done: #166 fast-forwarded main to 53bd547; definition updated in decision-driven-design #57.

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

    No labels
    No labels

    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