Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

dstack logo

dstack is a documentation-first, Beads-backed workflow for planning, implementing, reconciling, and delivering agent-assisted software projects.

Use this book to:

  • understand the authority and trust boundaries between Beads, designs, reader documentation, code, and delivery records;
  • install the skills and create or update a Copier-managed project;
  • follow the feature lifecycle from planning through delivery;
  • maintain or extend dstack itself;
  • find exact repository paths and validation commands.

The project overview defines current scope and boundaries. Install and use dstack is the shortest path for adopters. Maintainers should start with Workflow architecture and Developing dstack.

dstack overview

Purpose

dstack gives coding agents and maintainers a shared, auditable workflow in which product intent, executable work, reader documentation, implementation evidence, and delivery records remain aligned.

Intended users

  • Maintainers planning and delivering software with coding agents.
  • Coding agents that need explicit authority, lifecycle, and validation contracts.
  • Teams adopting the bundled Copier scaffold in new or existing repositories.
  • dstack contributors maintaining the skills, template, and migration behavior.

Current scope

dstack ships installable agent skills, a versioned Copier template, Beads lifecycle formulas, safe setup/update/migration helpers, documentation validation, and GitHub review workflows. New-project setup records an explicit purpose, intended users, current scope, key boundaries, and project kind, then renders only factual initial reader pages. dstack also supports legacy workflow migration, planned feature delivery, close-out, and drift audits.

Future behavior belongs in Planned Features until delivered.

Boundaries

  • Beads owns live work state; dstack does not replace the issue database with Markdown task lists.
  • Copier owns generated scaffold updates; Skills CLI owns installed skill files.
  • dstack defines workflow and documentation contracts, not an application framework or universal build system.
  • Setup never adopts an existing repository implicitly; migration and updates are separate explicit workflows.

Current status

dstack is versioned and usable, but remains an evolving personal workflow toolkit. Published tags are the supported update boundary. Repository tests cover template rendering, workflow helpers, migration behavior, and external skill installation.

Documentation conventions

Source responsibilities

  • Beads stores workflow state, dependencies, priorities, claims, findings, and execution evidence.
  • Feature design.md files store intended feature behavior and design decisions.
  • Reader-facing pages under docs/src/ describe current supported behavior.
  • Implemented-feature index.md files preserve feature-specific delivery and audit history.
  • planned-features.md provides a human roadmap; Beads is authoritative for live execution state.
  • Code and tests provide implementation evidence.

Page placement

Choose a page by the question the reader is asking:

Reader questionDocumentation concern
What is this project, who is it for, and what does it currently promise?Introduction
Why is it structured this way, and what boundaries or invariants apply?Architecture
How do I use, deploy, configure, observe, operate, or recover it?Operator’s Manual
How do I build, test, change, migrate, or extend it?Development Guide
What is the exact command, configuration key, interface, field, schema, default, or contract?Reference
What did one delivered feature change, and how was it verified?Implemented Features

Create focused project-specific pages when a durable reader question exists. Do not create empty pages merely to fill a category. A project may rename or omit a concern when it genuinely does not apply, but navigation, feature designs, and validation rules must be updated together.

Feature documentation

A feature design must name exact existing pages to update and exact new pages to create. Section names alone are not sufficient. User-facing documentation must stand on its own; readers should not need the internal feature design to understand supported behavior.

Status language

  • Planned: intended but not delivered.
  • Implemented: present in code but not necessarily validated or fully documented.
  • Supported: implemented, validated, documented, and part of the current contract.
  • Deprecated: still present but scheduled for replacement or removal.
  • Removed: no longer available.

Drift handling

When design, implementation, tests, Beads, or published docs disagree:

  1. record the mismatch in Beads;
  2. determine whether the divergence was intentional;
  3. correct the implementation or update the appropriate authoritative artifact;
  4. preserve the rationale and validation evidence;
  5. close the drift issue only after the sources agree.

Writing style

State current behavior directly. Separate planned behavior from delivered behavior. Prefer exact commands, paths, defaults, failure cases, and validation evidence where precision matters.

Workflow architecture

Components

  • skills/ contains the installable workflows. Each skill owns its scripts and references.
  • skills/setup-project/template/ is the canonical Copier scaffold used by both repository and skill entry points.
  • Root copier.yml exposes the same scaffold for repository development and integration tests.
  • Beads stores live feature state and dependencies; .beads/formulas/dstack-feature.formula.toml defines the lifecycle graph.
  • docs/src/features/<slug>/design.md owns intended feature behavior.
  • Reader pages under docs/src/ own supported current behavior.
  • Implemented-feature index.md pages preserve delivery reconciliation and audit evidence.

Authority boundaries

Skills CLI installs and updates workflow code. Copier records and applies scaffold evolution. Beads owns executable work. Git commits and tests provide implementation evidence. No helper silently substitutes one authority for another.

Monorepo tooling ownership

Monorepo answers remain Copier-recorded state. Root mise.toml, mise.lock, hk policy, documentation, workflow state, and the tooling provisioner remain repository authorities. Explicit package roots receive task-only mise configs; root configuration owns the profile-tool union and aggregate check/fix dependencies. Setup and update render those deterministic package configs from Copier answers without package discovery or a progress manifest.

Ordinary managed template changes retain Copier’s three-way update behavior, and previously recorded package configs refresh from current answers. If a newly requested package config path already contains a project file, update preserves its bytes and writes the generated alternative under migration/copier-adoption-candidates/<same-relative-path>. Candidate presence blocks generated tooling execution until explicit reconciliation.

Template rendering boundary

New-project setup treats the structured project brief as the only source for initial product facts. Every project kind receives the same minimal reader file set; kind changes only the future-concern guidance in documentation conventions. The template omits architecture, usage, development-overview, and reference-overview pages until implementation creates concrete content for them. Copier records the brief so later template renders remain deterministic.

Validation policy

Root and generated hk configurations prefer version-pinned built-in steps. Native file locking coordinates independent checks; explicit dependencies are reserved for demonstrated output ownership rather than global serialization.

Migration boundary

Legacy adoption is additive. A committed session-authority record binds execution to the user-selected base SHA, migration branch, exact worktree, and Git repository; its original introduction commit is immutable, so later branches, manifests, and checkpoint commits cannot replace authority or authorize resume. Resume events are separate audit data. The migration manifest records pre/post hook capabilities, artifact dispositions, contextual safety decisions, feature-specific semantic evidence, and verified checkpoints; it does not replace Beads as live work authority or Copier as scaffold authority. Project-owned files remain authoritative through candidate reconciliation. Only the rendered project-local provisioner may install locked tools and hooks, and ordinary Git commits remain the checkpoint authority.

Repository identity boundary

Migration distinguishes the active worktree path from canonical repository identity. Explicit recorded answers win; otherwise the primary Git common directory supplies the project name and slug, and refs/remotes/origin/HEAD supplies the default branch; only a primary worktree may use its current branch as evidence. A suffixed migration-worktree basename is never adopted as project identity. An uninitialized migration runs on its dedicated branch in the primary checkout so native bd init can commit collaborative controls, discover Git origin, and establish shared-worktree Dolt state. The native commit is inspected and amended through project hooks. Database path/name, project ID, repository root, and issue prefix must match before import or verification. Cross-clone issue history uses Git special refs through bd dolt push and bd bootstrap, not committed database files or JSONL. Large imports derive and reconcile the complete deterministic issue/status/parent/relationship set before trusting phase state and rejects unexpected migrated records, then uses bounded Dolt batch commits for at most two incomplete features by default. Native parent-label inheritance is verified as a complete exact formula/ancestry set rather than treated as optional or mistaken for foreign lifecycle state. A separate dry-run-first repair derives missing labels from immutable manifest/formula identity and permits additive restoration only; replacement and unexpected labels remain fatal. Native Beads owns worktree discovery, control placement, and synchronization; dstack validates the effective context rather than mirroring controls or injecting database paths. The manifest remains a recovery cursor, never independent proof that records exist. Finalization is a journaled staging transaction that seals archive digests and parsed task identity; finalized verification compares the exact recursive archive and current feature/design/task inventory with that sealed record.

Safety invariants

  • New-project setup does not overwrite or migrate existing project content.
  • Remote template overrides require an explicit reviewed ref and never fall back silently to HEAD.
  • Human feature commands use stable slugs or names; opaque Beads IDs remain mutation and audit details.
  • Feature implementation cannot become ready before specification reconciliation.
  • Reader documentation must stand alone rather than embedding internal designs or legacy task files.
  • Delivery follows documentation reconciliation, validation, and independent drift/delivery reviews.
  • Installed skill metadata is execution authority; startup records its version and compares only against trustworthy local canonical evidence.

Update flow

Setup and update resolve either the newest stable tag or the explicitly selected unstable default-branch HEAD and persist its SHA plus channel in .copier-answers.yml. Setup first verifies its installed bundle matches that exact commit; update renders the selected source through Copier. /update-project preserves the channel and lets Copier perform the three-way update. The dstack template source may explicitly bootstrap itself with --adopt --unstable; /migrate-workflow handles other repositories that predate the Copier/Beads contract.

Generated tooling authority

Every generated project receives one universal mise.toml task/tool interface and one hk.pkl quality policy. The hk binary and both versioned Pkl imports are pinned together; fuzzy versions for the other tools become deterministic in the project-owned mise.lock. The generated provisioner ignores user-global mise configuration so that lock resolution and locked installation cover only project-declared tools.

Copier only renders files. After rendering and optional Git initialization, /setup-project invokes the generated scripts/setup-tooling.py. A conflict-free /update-project invokes that same project-local provisioner after Copier reconciliation. An update with conflicts never executes newly rendered project code. Provisioning resolves the lock, installs with --locked, then installs hk hooks as a separate stage so hook failure cannot erase successful lock/install state.

Language quality profiles extends these same generated files from one canonical language_profiles answer. Recognized profiles compose by direct membership-gated template sections; other is exclusive and preserves only the universal baseline. Multiple profiles apply one root policy to a polyglot repository, not package-local or monorepo configuration. Setup collects an explicit selection, while updates preserve it unless the user explicitly adds or removes profiles. The existing provisioner and conflict gate remain the only network-backed tooling path. Source steps are file-gated; project checks are root-manifest-gated. Profiles never create manifests, dependencies, source, package roots, or package-local policy. The Nix exception keeps the universal four-platform lock while atomically removing only nixfmt-rs’s unsupported macOS x64 table before locked installation.

GitHub validation and docs deployment consumes the stable named tasks without adding package manifests, application source, or duplicate CI policy. Generated projects include a documentation deployment workflow, but repository creation and Copier updates never enable it. The workflow accepts only pushes to the configured default branch and explicit manual dispatches; both build and deploy jobs require DOCS_DEPLOYMENT_ENABLED to equal true, so pull requests and forks cannot deploy.

The build job receives only contents: read, installs the committed mise lock in isolation, runs the existing docs:build task, and uploads docs/book. The deploy job alone receives pages: write and id-token: write, targets the github-pages environment, and publishes the reviewed artifact. This separates untrusted change validation from the credentialed deployment boundary.

Enablement is a separate administrative boundary: an operator supplies an external, authenticated GitHub CLI with repository administration access. The helper configures Pages with build_type=workflow before setting the repository variable. Deployment therefore requires both repository-side Pages configuration and an exact true variable; rendering or updating the workflow alone grants nothing.

Install and use dstack

Install the skills

npx skills@latest add RobertDeRose/dstack --all

Create a project

Run /setup-project in a new project directory. The skill asks one question at a time for the project’s purpose, intended users, current scope, key boundaries, kind, and language profiles. Supported kinds are library, CLI, service, application, infrastructure, documentation, and other. Select one or more recognized language profiles for a polyglot root policy, or select exclusive other for only the universal baseline. Setup does not infer or fabricate missing facts.

The skill resolves the stable channel by default or --unstable explicitly, verifies its installed template matches the exact selected commit, renders the bundle, initializes Git and Beads when available, and validates the documentation. Existing repositories are routed to /migrate-workflow; already managed repositories are routed to /update-project with explicit consent.

Deliver features

/plan-features
/start-feature feature-name
/implement-feature feature-name
/implement-task task-selector
/close-feature feature-name
/audit-project

Use bd prime at session start. Use /implement-task <task-selector> for exactly one standalone executable issue. Use /implement-feature for reviewed feature children; it continues until the feature implementation coordinator closes. Beads owns live readiness and dependencies; docs/src/planned-features.md is only the human roadmap. When /audit-project creates or updates corrective Beads records, it performs one ordinary non-force bd dolt push to the configured native remote after validation. It does not create remotes or publish Git branches. The audit also requires read-only Git history comparison; a bd prime stealth-mode message forbids Git mutations, not this required evidence. If the execution context denies read-only Git inspection, the result must be reported as audit state: incomplete, not as a completed audit with Git comparison silently excluded.

Repository-layout preflight

New and older projects remain single-package unless monorepo conversion is explicit. Before setup or update, supply the complete 1-32 package list and inspect the JSON layout preflight. It reports each preserved display name, slug, profile list, exact destination, occupied state, and collision paths. Rendering does not start when a package is invalid, overlaps another package, uses a root-owned path, differs only by case, traverses a symlink, or exceeds the bounded list. Existing package destinations are reported as collisions for later additive-render reconciliation; they are never permission to overwrite project files.

During update, a newly occupied <package-path>/mise.toml remains byte-identical. Its generated alternative is written to migration/copier-adoption-candidates/<package-path>/mise.toml; tooling and documentation execution stop until the operator compares the files, chooses the supported result, removes the candidate, and reruns /update-project. Ordinary Copier-managed conflicts continue to use Copier’s configured inline or reject-file recovery.

Update

  • npx skills update refreshes installed skill definitions and scripts.
  • /update-project applies the newest revision from the recorded stable or unstable channel to a managed repository. Pass --stable or --unstable to change the preserved channel. Repeat --add-profile and --remove-profile for explicit idempotent profile changes; their sets must be disjoint and the result nonempty.
  • /update-project --adopt --unstable explicitly bootstraps dstack itself as an unstable template consumer; reconcile every generated candidate before validation or commit.
  • /migrate-workflow adopts an existing legacy Markdown workflow before normal updates.

Migration first asks for the exact base branch and either a fresh branch or an explicitly named branch/worktree to resume. It never discovers or selects a resume candidate automatically. Git is mandatory. authorize-session records the base SHA, branch, absolute worktree, and repository; after baseline, every command requires that record to be tracked and byte-identical to HEAD and its single original introduction commit. Resume additionally requires the user’s exact generated phrase and writes a separate audit record rather than mutating identity.

Migration captures the legacy hk hook/step inventory before adoption. Candidate reconciliation is additive: a removed step or changed same-key definition blocks verification until restored or explicitly approved with both behaviors and a reason. If the legacy config cannot be evaluated, migration stops for manual inventory confirmation rather than treating the generated policy as equivalent. Durable manifests, reports, baselines, session-authority audits, and legacy-task archives must be committed. Delivered-record candidates under migration/delivered-record-candidates/ are transient local review material: never stage or commit them. Template-adoption candidates under migration/template-adoption-candidates/ are separate adoption conflicts; reconcile each one and remove that directory before the adoption checkpoint. Conditional adoption backups require an explicit retain/remove disposition. Repeated unchanged scans do not churn committed migration evidence. For migration brief fields, the helper first extracts clear current values from README/docs, AGENTS.md, manifests, and CI. It prompts only for missing, stale, or conflicting values; it does not ask the user to restate documented context. Project purpose, users, scope, and boundaries remain structured Copier context rendered into the reader overview and roadmap, and are also available to agents through AGENTS.md. Language profiles are inferred from manifests and CI when possible. Project brief and semantic questions still use an evidence-backed recommendation when a decision is genuinely unresolved, with a concise decision title, why it is needed, current evidence/uncertainty, controlled behavior, a concrete example, choices/safe default, and the consequence of deferral. After reconciliation, the rendered project provisioner must install the locked tools and Git hooks before an ordinary checkpoint commit. Preserve the existing project hook policy and do not activate a generated strict docs step while legacy task files remain; defer it until archival or make it migration-aware. Documentation-step skips are not a migration path. Rerun the actual strict hook after each fix; a plan-only invocation is not validation. If the existing policy cannot be sequenced or made migration-aware, stop with the named blocking step instead of requesting approval to skip it. Whole-hook bypass is never allowed. Final verification requires durable passed checkpoint evidence and treats migration markers as provenance only; they do not weaken normal documentation validation after finalization. After final verification, migration reports completion and presents the configured delivery action: merge, create a PR, or leave it complete without delivery.

Beads initialization and every import/verification command require nonsymlinked repository-local metadata, embedded database location/name, project ID, repository root, and issue prefix. Uninitialized migrations use the primary checkout on the dedicated migration branch. Native bd init commits collaborative controls, discovers Git origin, configures Dolt synchronization, and establishes worktree sharing; dstack inspects that commit and amends it through project hooks. Formula-only state remains uninitialized, and global/shared fallback fails. Subsequent commands use native repository discovery while dstack checks authority identity before and after mutations. Push issue history with bd dolt push; fresh clones recover it with bd bootstrap. Beads import dry-run is nonmutating and reconciles every manifest ID against actual deterministic metadata, including completed phases. Apply handles at most two incomplete features by default and uses bounded Dolt commits rather than one transaction per field or relationship. Repeat it until remaining: 0; reduce to --batch-size 1 or select --feature <slug> for narrow recovery. It begins with an explicit APPLY STARTED notice and reports existing, recovered, pending, conflicting, completed, remaining, and total features. Per-feature phases persist, but retries trust them only after real-record reconciliation. A terminated fresh import resumes its persisted identities; it is not a migration-session resume. Missing native workflow/formula labels stop import. Preview repair-beads-labels, review every ID/label, then use --apply for additive-only restoration; extras block before mutation, and an empty repair writes nothing. Status transitions use bd update --status for Beads 1.1 compatibility.

Adoption preserves recorded project identity first. Otherwise it derives the project name from the primary Git checkout and the default branch from origin/HEAD. Supply explicit project name, slug, and default branch when evidence is missing or incorrect. Run beads-authority --init, inspect the native Beads commit, apply the README formatting exclusion, and amend it through ordinary hooks. Keep embedded Dolt storage, credentials, locks, sockets, and other runtime state ignored. Once initialization is committed, native Beads shares the authority with linked worktrees.

prepare --apply regenerates implemented-feature navigation from standalone completed records. draft-delivered-records --apply can create transient historical record candidates from legacy tasks, design paths, and imported Beads identities, but candidates do not establish truth or belong in commit history. Inspect one feature at a time, reconcile its actual implemented record, then supply a unique feature-naming summary, non-generated corroborating path, related Git commit, and rationale to review-delivered-record. Before finalization, candidate files must exist and match their recorded digests; if one disappears, redrafting clears its prior review metadata and semantic review must be repeated. Finalization derives and verifies the exact live Beads graph, including absence of unexpected migrated records, rejects artifact-path collisions, preflights all archive paths and reviewed candidates, stages and journals every move, rolls back validation failure, seals archive digests/task identities, and persists state before deletion. A leftover journal requires explicit recovery rather than guessed continuation. Only after finalize --apply succeeds, verify --beads confirms migration_finalized: true, and the user explicitly authorizes cleanup may the agent delete migration/delivered-record-candidates/; rerun verification afterward. Final verification compares the exact recursive archive and feature inventory; manifest booleans alone cannot authorize evidence removal. It requires a native Git-origin remote and emits one authoritative state: complete or mechanically complete with semantic reconciliation pending.

Legacy managed projects keep their recorded profiles. When none are recorded, update preflight inspects only root pyproject.toml, tsconfig.json/package.json, Cargo.toml, go.mod, mix.exs, and flake.nix, then presents recognized profile suggestions for confirmation. It never applies suggestions automatically.

Enable generated GitHub Pages

Generated projects include a default-disabled Documentation workflow. From the generated project, install and authenticate external GitHub CLI with repository administration access, then run:

mise run docs:deployment:enable

The helper resolves the current GitHub repository, creates or updates Pages with build_type=workflow, sets DOCS_DEPLOYMENT_ENABLED=true only after Pages configuration succeeds, and prints the Pages URL. Repeating the command updates the existing configuration. A failure names the operation and never reports success.

For manual recovery, install gh from https://cli.github.com/ if needed, then run:

gh api --method PUT repos/OWNER/REPO/pages -f build_type=workflow
gh variable set DOCS_DEPLOYMENT_ENABLED --body true --repo OWNER/REPO
gh api repos/OWNER/REPO/pages --jq .html_url

Use POST instead of PUT when Pages does not exist. If the final URL query failed, verify state before retrying because the variable may already be set.

Failure boundaries

Setup refuses non-empty unmanaged destinations. For a new destination, direct helper invocation also rejects missing, blank, multiline, or NUL-containing brief values and names the required flags. This is an intentionally breaking pre-v1 setup contract; Purposeful project scaffold does not support updating or adopting older answer sets.

Update refuses missing or invalid Copier state and unreachable revisions. Stable never falls back to untagged code; unstable explicitly resolves the source default-branch HEAD. If Beads is unavailable, setup reports initialization and verification as outstanding rather than claiming a complete workflow installation.

Tool provisioning and recovery

Setup and conflict-free updates run the generated project provisioner after rendering. It executes, in order:

mise lock --yes --platform linux-x64,linux-arm64,macos-x64,macos-arm64
mise install --locked
mise x -- hk install --mise

The lock/install commands ignore user-global mise tools. For the Nix profile, the provisioner validates the three supported nixfmt-rs lock entries and removes only its macOS x64 entry before locked installation; all other tools retain the four-platform lock. hk hook installation runs only when Git exists and is reported separately. After native Beads initialization, setup runs bd hooks install and verifies bd hooks list --json; conflict-free updates do the same after successful tooling. These Beads hooks are separate from hk and are reported in beads_hooks. Setup with --no-git-init can therefore finish lock/install work while reporting hooks as skipped-no-git; --skip-post-setup performs no generated code and reports all tooling stages as skipped.

Profile source checks skip when no matching files exist. Package checks skip without their root manifest. A selected manifest with missing project-owned pytest, Vitest, or Credo fails with the named prerequisite; flake checks similarly require system Nix. Matching Nix inputs fail clearly on unsupported macOS x64.

A missing mise executable, failed lock resolution/download, failed locked install, or failed hk/Beads hook does not roll back the scaffold. Inspect the returned tooling and beads_hooks stages and run each listed recovery command. For Beads hook recovery, use:

bd hooks install
bd hooks list --json

The general tooling rerun command is:

python3 scripts/setup-tooling.py --json

Do not commit an empty or stale mise.lock. A Copier conflict skips provisioning entirely: resolve every conflict, account for every changed path, then rerun the project provisioner. /update-project keeps readiness false while conflicts, degraded tooling, a missing/stale lock, or unclassified changed paths remain.

GitHub Pages deployment

Documentation deployment is generated but disabled by default. Local documentation commands and pull-request validation do not require GitHub Pages.

Enable deployment

Install GitHub CLI separately, authenticate an identity with repository administration access, and run from a clone whose GitHub repository can be resolved:

gh auth login
mise run docs:deployment:enable

The task checks gh, authentication, and repository resolution. It creates or updates Pages with the GitHub Actions build type, then sets DOCS_DEPLOYMENT_ENABLED=true as the last mutation and prints the Pages URL. Repeating the task updates the same configuration safely.

Deployment requires both Pages build_type=workflow and the repository variable to be exactly true. The workflow runs only for pushes to the configured default branch and explicit manual dispatches; pull requests never deploy.

Recovery

A failed task names the failed GitHub operation and does not report success. Install gh from https://cli.github.com/ if necessary. Complete the same state manually:

gh api --method PUT repos/OWNER/REPO/pages -f build_type=workflow
gh variable set DOCS_DEPLOYMENT_ENABLED --body true --repo OWNER/REPO
gh api repos/OWNER/REPO/pages --jq .html_url

Use POST instead of PUT when the repository does not have an existing Pages site.

If URL lookup fails after the variable is set, the repository may already be enabled; verify both settings before rerunning or dispatching the Documentation workflow.

Developing dstack

Repository areas

  • skills/: canonical skill definitions, scripts, references, and the bundled setup template.
  • tests/: repository, migration, setup, update, and workflow validation.
  • copier.yml: repository-development Copier entry point.
  • mise.toml: reproducible tool and task interface.
  • hk.pkl: shared local and CI quality policy.
  • docs/: this mdBook and feature planning records.

Setup

Install declared tools with mise install. The post-install hook installs hk through mise so Git hooks use the same tool versions as manual checks.

Validation

mise run check
mise run docs:build
uv run --frozen --group test pytest -m "not integration and not external"
uv run --frozen --group test pytest -m integration
uv run --frozen --group test pytest -m external

Use mise run fix for deterministic formatting fixes. The canonical full suite is uv run --frozen --group test pytest; pytest uses four bounded xdist workers with load-group scheduling. Mark tests that mutate shared repository state with xdist_group so those tests remain serialized.

Migration checkpoint fixtures must exercise the rendered project-local provisioner and ordinary Git commits. They cover provisioning failure, installed hook routing, hook failure recovery, and the narrow approved docs-step exception without bypassing unrelated checks.

Generated project command contract

Generated projects expose six stable task names to contributors, operators, and future CI:

mise run check
mise run fix
mise run docs:check
mise run docs:build
mise run docs:deployment:enable
mise run docs:serve [port]

check is read-only. fix applies deterministic changes. Pre-commit uses the same hk step map with fixes enabled and stash = "git", so unrelated unstaged work is restored after the hook. Native hk steps and file locking coordinate independent checks without a broad dependency chain. HK_MISE=1 makes installed hooks run tools through mise.

The generated baseline covers documentation, Markdown, typos, mise formatting, conflicts, private keys, BOM/newline and whitespace hygiene, case conflicts, and executable/shebang consistency. Commit-message Harper linting keeps its full native rule set but filters Git comments/diffs, a canonical release subject, and a canonical machine-readable Beads: footer before checking the human-authored text. Selected profiles extend the same hooks:

ProfileSource check/fixRoot-manifest checks
PythonRuff lint/format and typytest through uv
TypeScriptBiome check/writeVitest through Aube
Rustrustfmt edition 2024Clippy and Cargo tests
Gogoimports, then gofumpttidy diff/verify, golangci-lint, tests; fix may tidy
ElixirMix formatwarnings-as-errors compile, strict Credo, tests
Nixnixfmt on supported hostssystem-Nix flake check

Source steps are file-gated; project checks are root-manifest-gated and check-only except Go’s explicit tidy fix. Profiles add no tasks, manifests, dependencies, or source. The scaffold intentionally omits dstack’s release task.

Generated GitHub validation

Generated .github/workflows/validate.yml runs on every push and pull request with contents: read. It disables automatic mise installation, isolates user-global mise configuration, installs the committed lock, and invokes only mise run check. The workflow therefore reuses hk and the generated documentation contract instead of defining a second CI policy or regenerating mise.lock.

Documentation checker contract

The documentation checker validates the pages a project actually publishes rather than requiring a fixed taxonomy. A project may omit architecture, operations, development overview, or reference overview pages until it has concrete content for them. Existing links must resolve, feature designs remain published audit records, legacy task files stay out of reader navigation, and delivered feature records must retain valid directories, sections, markers, and registrations in both implemented-feature indexes. The repository and generated-project checker copies must remain identical.

Scaffold matrix validation

The integration matrix renders every project kind and all 64 valid language-profile selections through both Copier entry points. It checks structured answers, conditional tools/hooks/ignores/docs, Pkl and TOML parsing, stable tasks and navigation, generated checker success, and mdBook builds. Single-profile fixtures execute source and manifest gates with shims; the full polyglot external fixture runs real source fix-to-check convergence. Bounded external validation resolves the combined four-platform lock, exercises check/fix/pre-commit/commit-message contracts, and verifies unrelated unstaged bytes are restored exactly. Separate regressions cover invalid selections, no-overwrite routing, update preservation, explicit add/remove transitions, conflicts, relocking, and conditional destination uniqueness.

Large migration imports

Beads mutations run with --dolt-auto-commit=batch. Before mutation, tests prove repository-local database authority and reconcile manifest IDs against actual metadata even when phases claim completion. Migration commits bounded root/state work per feature and performs a separate relationship reconciliation commit, while the JSON manifest preserves finer recovery phases. The deterministic large-import fixture creates at least 300 Beads records, bounds batch-commit count, records elapsed time, and proves a relationship-interrupted retry mutates only its missing outgoing dependency and does not replay completed dependents.

Migration reconciliation automation

Before finalization, verify automatically runs check-docs.py --migration-mode; afterward it runs strict mode. The migration checker operates on reader documentation, so generated assets and legacy command directories are not broadened into its input, and it never rewrites project acronyms or mdBook H1 part headings. Prepare regenerates only bounded implemented-feature marker bodies. Delivered-record drafts include legacy tasks/design, imported Beads identity, Git commits, and changed paths, remain candidates, and block verification and finalization until per-feature semantic review binds the actual implemented record to unique summary, path digests, and corroborating commits. Regression fixtures also cover renamed/unapproved/uncommitted or later-committed authority replacement, non-Git execution, formula-only/global Beads fallback, pinned Beads commands, dry-run byte preservation, missing and unexpected records, wrong statuses/labels/relationships, transactional finalization rollback, archive digest/inventory drift, CLI artifact collisions, unsupported create status flags, path and symlink escapes, evidence/commit association, and non-exact hook approval.

Monorepo mise compatibility

The monorepo implementation targets stable mise task-path behavior, verified with mise 2026.7.5 while MISE_EXPERIMENTAL=0. A root config with monorepo_root = true and explicit [monorepo].config_roots discovers namespaced package tasks such as //packages/api:check; root aggregate dependencies execute those tasks in each package config root. [monorepo].lockfile = true selects one root lockfile. dstack keeps every profile tool declaration in the root config, so package configs contribute tasks and working directories but cannot create independent tool locks.

Primary evidence: mise’s Monorepo Tasks, configuration, and lockfile documentation, reviewed 2026-07-18. Verification used mise 2026.7.5 with a temporary MISE_CONFIG_DIR; a hostile user-global-only tool was excluded from project resolution:

  • MISE_EXPERIMENTAL=0 mise tasks --all --name-only discovered //:check, //packages/api:check, and //packages/web:check from the two explicit config_roots;
  • MISE_EXPERIMENTAL=0 mise run check executed both package checks from the root aggregate;
  • mise lock --dry-run --platform linux-x64 targeted the root mise.lock and resolved the root-declared tool;
  • the regression drives the rendered provisioner’s lock, install --locked, and hook stages, asserts root lock contents, and rejects package lock creation; the existing external generated-tooling fixture supplies live locked-install coverage.

task_config.includes remains supported for reusable file tasks but does not supply package config-root semantics. Implicit recursive discovery was rejected in favor of explicit config_roots. Package-owned tools plus monorepo lockfile migration are supported by current mise, but dstack deliberately keeps the profile-tool union at root to preserve its single provisioner and cross-platform/Nix lock contract. No experimental setting is required.

Monorepo scale and update evidence

The bounded maximum fixture renders 32 explicit packages across all seven profile choices. On 2026-07-18 it completed in 94.55 seconds, discovered exactly 32 package check tasks, executed every package through the root dependency graph, and produced one package marker per declared slug. A second deterministic render produced byte-identical package mise files. Pkl evaluation confirmed a middle TypeScript path selected only its package-namespaced Biome step; neighboring package steps did not match. Candidate retries preserve the original occupied bytes, retain the same generated candidate, and continue blocking update completion until reconciliation. Existing Copier conflict fixtures continue to exercise managed three-way recovery separately.

Change discipline

Keep both Copier entry points aligned. Template changes require generated-project tests and must preserve Copier update compatibility. Skill versions are synchronized during semantic release. Changes to workflow behavior must update the owning skill, tests, reader documentation, and feature evidence in the same work unit.

See Feature lifecycle for the repository’s planning and delivery workflow.

Feature lifecycle

Responsibilities

Beads                                            executable state and dependencies
docs/src/features/<slug>/design.md         intended feature behavior and design
reader-facing docs under docs/src/               current supported behavior
code and tests                                   implementation evidence
docs/src/features/<slug>/index.md          delivered reconciliation and audit record

Workflow commands are installed from RobertDeRose/dstack with the skills CLI. The CLI manages the agent-specific installation paths and updates; Copier manages this repository scaffold.

Start a session

bd prime
bd ready --type epic --label workflow:feature --json --limit 0
bd ready --json

Executing skill version

Each workflow records the installed skill’s frontmatter metadata.version before its first mutation. When a local canonical dstack checkout is available, startup compares that version and records the exact Skill version evidence: line. A stale installed skill warns with npx skills update; unavailable canonical evidence reports that no freshness claim was made and does not block offline work. The installed skill remains execution authority.

Plan

/plan-features asks design-changing questions, defines the documentation architecture, creates slug-named feature designs, pours one Beads epic/molecule per feature, and decomposes lifecycle and implementation into bounded child tasks. Native planning resolves every decision needed by those tasks before implementation; unresolved decision gaps may remain only on imported migration work with explicit reconciliation blockers. It recommends the next feature by canonical slug and human name rather than by an opaque Beads hash.

A new feature uses:

docs/src/features/feature-slug/design.md
feat/feature-slug

Review and start

/start-feature <slug> resolves the human feature reference through Beads, activates the worktree, and runs four isolated reviews. An exact feature name or a unique name fragment also resolves; the Beads ID remains internal mutation/audit evidence.

The feature root is an epic. Lifecycle tasks are direct children, and bounded implementation tasks sit beneath the implementation coordinator task. A milestone is not used as the feature container.

One fresh, read-only context builder gathers a factual evidence packet once. Four fresh reviewers share that packet and independently cover:

  1. architecture consistency;
  2. simplicity and maintainability;
  3. documentation readiness;
  4. execution-graph readiness.

Optional Pi reviewer adapter

The dstack review contract is tool-agnostic. A Pi-based controller may opt into the exact roster in skills/dstack-core/references/PI-REVIEWER-ROSTER.md without installing or mutating user Pi configuration. If required names are missing, offer the explicit project-local sync documented by that reference; the adapter itself remains non-mutating:

Logical rolePi agent definition
context-builderdstack-context-builder
architecturedstack-architecture-reviewer
simplicitydstack-simplicity-reviewer
documentationdstack-documentation-reviewer
executiondstack-execution-reviewer
taskdstack-task-reviewer
deliverydstack-delivery-reviewer
driftdstack-drift-reviewer

The adapter preserves the workflow counts: context packets are built synchronously, then independent role reviewers launch concurrently with the same packet. A declined or failed sync, or an unavailable named agent, fails visibly; there is no silent role substitution. Beads review beads or standalone task notes remain the authoritative Review state:/Finding: owner.

The packet contains factual source locations but no findings, recommendations, or verdict. Reviewers read extra source when it is insufficient. Feature workflows persist the durable Review state: record from the installed dstack-core REVIEW-STATE.md reference on their review beads. A standalone workflow has no separate review bead: its selected task notes are the authoritative review ledger for Review state: and Finding: records, including reviewer session, packet identity/digest, reviewed commit/diff boundary, and disposition. Supply reviewers the current open projection from REVIEW-FINDINGS.md; retain historical findings for audit. Do not add confidence reviewers without a distinct uncovered risk or user request. Fix verification resumes only affected reviewers and their run IDs; fresh replacements are used only when an original is unavailable. A material scope change invalidates the whole review run; reopen specification reconciliation, commit the redesigned boundary, and run one new bounded review with a new packet. Refresh a shared packet only after broad design, architecture, task-graph, or documentation-structure changes. Two unresolved review rounds in the same domain are a convergence stop: record redesign_required, do not launch another reviewer, and return through specification redesign or decomposition before creating a new packet.

Open review tasks and spec-reconcile are expected during review and are not findings by themselves. Reviewers report stale dependency direction, missing tasks, and other graph defects; the controller verifies gate closure only after approval and the specification-reconciliation commit.

Invoking /start-feature authorizes its local reconciliation work, including the reviewed design/graph commit and feature-scoped Beads mutations. It does not authorize remote publication, pull-request creation, or branch pushes. It reconciles clear findings, asks only blocking design questions, commits the reviewed design, and closes spec-reconcile only when implementation can proceed without inventing intent. Before recommending implementation, it commits any remaining in-scope workflow state and confirms the feature worktree is clean. A successful start records the canonical feature in repository-local Git configuration so /implement-feature can resume it from the base worktree when no selector is supplied.

Implement

Claim the next ready task beneath the implementation coordinator:

bd ready --parent <implementation-id> --claim --json
bd show <task-id> --json

Before mutating code, run a semantic boundedness check: one independently reviewable behavior, one primary owner, and one practical commit boundary. Character counts are warning signals only. Cross-boundary work returns to specification reconciliation without code changes.

Material changes to behavior, ownership, compatibility, or acceptance stop implementation and invalidate the reviewed source boundary. Reopen specification reconciliation and affected review gates, mark stale review evidence invalid, reconcile and commit the new specification boundary, and complete its review before reclaiming implementation. An editorial clarification may stay in place only when it does not alter reviewed intent, ownership, compatibility, acceptance, or the review boundary.

After each child closes, the implementation loop runs a cohesion checkpoint against new evidence. New ownership boundaries, migrations, external dependencies, or risky effect classes require inspection, but incidental complexity alone does not require decomposition. If remaining outcomes are independently valuable and reviewable, pause the coordinator and return through normal feature planning authority to define dependent feature epics. Do not create replacement children under an incoherent coordinator; preserve user authority, completed work, and real Beads prerequisites. If no independent value or review boundary is found, continue the same feature.

Use parent-child for hierarchy and blocks only for real prerequisites. Keep code, tests, and affected documentation aligned in the same work unit. Record validation and review evidence, include the Beads ID in the commit message, and close the task only after its acceptance criteria pass. Each task gets exactly one fresh reviewer; fixes resume that reviewer. A fresh replacement is allowed only when the original is unavailable; material scope changes invalidate the review and return to specification reconciliation. /implement-feature then claims the next ready child and continues until the implementation coordinator closes. It pauses only when every remaining child is blocked on explicit user decisions; native planned work should never reach that state. Its final response includes a recommended next step: run /close-feature <slug> when implementation is complete, or provide the named advisement before resuming /implement-feature <slug> when blocked.

Before its startup-version note, /implement-feature resolves the authoritative feat/<slug> worktree from Git worktree metadata rather than trusting the process CWD. Native linked-worktree Beads authority is shared, so bd -C is not an isolation boundary. Every Beads mutation interval uses the repository-scoped interaction lease from dstack-core/references/INTERACTION-BOUNDARY.md; the lease is outside Git and prevents concurrent mutation races. It requires a clean feature worktree and captures an immutable interaction baseline. It records the root note in a separate interaction-only audit commit when the export is tracked. It then captures a fresh baseline immediately before each child claim. Startup alone allows a clean tracked interval when the version note emits no interaction row; child and coordinator closure still require selected-work-unit evidence. Every child closure and the implementation coordinator closure is the final Beads mutation in its work-unit interval. The shared verifier requires append-only, valid, unstaged rows in the selected feature lineage, requires evidence for the selected work unit, rejects intervening interaction commits, metadata changes, unrelated rows, and other dirty paths, then repeats the checks against the staged index and the exact pre-staging interaction snapshot. Only .beads/interactions.jsonl enters the audit commit. The finalizer branches on the verified dirty result, pins the pre-commit HEAD and index tree, and verifies the resulting audit commit’s parent, tree, path set, blob, and mode before requiring the feature worktree to be clean before the next child, coordinator completion, or ordinary return.

These bounded local commits do not authorize remote delivery, worktree removal, or close-out. They preserve feature history for /close-feature, whose later reconciliation still verifies rows created during close-out and delivery.

Standalone tasks

Use /implement-task <task-selector> for exactly one open standalone task, bug, chore, spike, or feature. It claims only the selected issue, loads bounded context, validates, runs one fresh reviewer, commits evidence, and closes that issue. Before its first Beads mutation, it captures a clean worktree and commit baseline. After closure, it verifies that any tracked .beads/interactions.jsonl change is append-only, valid, unstaged, limited to the selected issue, and untouched by intervening commits. It revalidates the staged index immediately before recording those rows in a separate interaction-only audit commit. Rewritten, malformed, mode/type-changed, prematurely committed, commit-then-reverted, unrelated, or mixed dirty state remains blocking and is never restored or absorbed. Invocation authorizes those bounded local commits but no remote delivery. It does not create feature design or close-out records. A feature epic or child of a workflow:feature epic must use /start-feature or /implement-feature instead.

Discovered work should retain provenance:

bd create "Describe discovered work" \
  --type task \
  --deps discovered-from:<current-task-id> \
  --json

Add a blocking edge only when the discovery is required for safe completion.

Close

/close-feature starts with a clean base-worktree interaction preflight and uses the repository-scoped interaction lease for every contiguous Beads mutation interval. Native linked-worktree Beads authority is shared; bd -C is not an isolation boundary. Close-out interaction evidence is inspected before restoration, and foreign interaction rows are reported without mutation or absorption.

/close-feature compares delivered code with the design and reader-facing docs, creates a standalone implemented-feature record, and runs validation. One fresh context builder supplies a factual packet to two fresh holistic reviewers for delivery and drift. They follow the neutrality, extra-source, refresh, confidence-review, and replacement rules above; fixes resume only the affected reviewer. The workflow then performs an explicit pr, merge, or ready action. With no mode, it asks which action to take. Merge mode uses git merge --ff-only unless the target repository’s AGENTS.md explicitly permits merge commits; it never falls back to a merge commit after a failed fast-forward. Native Beads can append selected-feature rows to the tracked .beads/interactions.jsonl in the base worktree during close-out. A repository-scoped interaction lease serializes each mutation interval. Close-out runs the clean preflight before any delivery/root mutation and uses the read-only inspector to enumerate foreign interaction rows when it fails. Merge mode verifies that this is the only dirty path and that every change is append-only and belongs to the selected feature molecule or separately identified work with a discovered-from or parent-child path back to it, commits those rows on the feature branch, and restores the base copy only after committed preservation. Foreign interaction rows remain with their originating work unit; blocks and related edges do not grant ownership. Delivery and root closures happen after the merge; their interaction rows receive a separate interaction-only commit on the base branch. Malformed, rewritten, foreign, or mixed dirty state remains blocking. After a confirmed merge, /close-feature runs a mandatory post-merge finalizer: it records the actual merge SHA in the implemented record, reconciles reader-facing delivery claims, runs verify-delivery-state.py and documentation validation, commits the finalizer, and only then invokes finalize-feature-delivery.py to close delivery and the feature root. The guarded finalizer verifies the merge SHA, finalizer commit, clean base boundary, and Beads statuses under the repository-scoped lease. ready and no-action close-out leave delivery/root open. A stale merge-pending claim blocks completion.

Audit

/audit-project periodically compares Beads, designs, current docs, implemented-feature records, code, tests, and recent commits. Recent commit comparison is required read-only Git evidence; it does not authorize Git mutations. If the execution context denies read-only Git inspection, the audit is explicitly incomplete rather than silently omitting the comparison. Drift becomes linked Beads work rather than an untracked note.

Skill maintenance

After editing a canonical skill:

npx skills update

Developer tooling

The repository uses mise to provide project tools and named tasks. Install mise, then run:

mise install --locked

Use the same commands locally and in automation:

mise run check
mise run fix
mise run docs:check
mise run docs:build
mise run docs:deployment:enable
mise run docs:serve

check is read-only. fix changes the working tree. Contextlint checks links, anchors, and image targets across README and docs/**/*.md. The pre-commit hook may fix files while safely stashing unrelated unstaged work. The commit-message hook enforces Conventional Commits, required scopes for changelog-visible changes, grammar, 72/100-character line limits, and canonical optional Beads: footers. Harper applies its full native rule set to human-authored text after filtering Git comments/diffs, canonical release subjects, and the canonical machine-readable footer. Run cog changelog to preview the concise user-facing changelog. The hk policy uses native built-in steps whenever their behavior matches; hk’s file locking coordinates independent steps. No dependency chain serializes unrelated checks.

Python

Ruff lint and formatting plus ty type checking run on Python files in check, fix, and pre-commit. When root pyproject.toml and tests/**/*.py both exist, mise run check also runs uv run pytest. Pytest must be declared by the project; setup does not add or download it.

GitHub validation

.github/workflows/validate.yml runs on every push and pull request. It isolates user-global mise configuration, installs only the committed lock with mise install --locked, and runs mise run check. CI does not regenerate the lock or maintain a separate validation policy.

Hooks and recovery

Setup installs repository-local hk hooks when the destination is a Git repository. To restore tooling after an offline or degraded setup, run:

python3 scripts/setup-tooling.py --json

The command gives lock, install, and hk hook stages one temporary MISE_CONFIG_DIR, removes inherited global config overrides, and deletes the temporary directory on exit. It preserves the scaffold on failure, reports the failed stage, and uses the same command above for recovery. A repository created without Git can install hk hooks after Git initialization with:

python3 scripts/setup-tooling.py --json

Beads hooks are separate from hk hooks. /setup-project runs bd hooks install only after the native Beads init amend commit, and /update-project runs it after conflict-free tooling succeeds. Both verify the result with bd hooks list --json and report the separate beads_hooks status. If verification fails, run:

bd hooks install
bd hooks list --json

Repository and command reference

Primary commands

CommandPurpose
mise run checkRun the shared read-only hk validation policy.
mise run fixApply deterministic fixes from the shared hk policy.
mise run docs:checkValidate documentation structure and build the mdBook.
mise run docs:serveServe the documentation locally.
mise run docs:deployment:enableConfigure and enable generated GitHub Pages through external gh.
mise run releaseRun the Cocogitto release workflow; pushing is opt-in.
cog changelogRender the concise user-facing changelog from Conventional Commits.
uv run pytestRun all repository tests.

Migration inventory commands

authorize-session fresh --base-branch <base> --migration-branch <new-branch> records the exact base SHA, branch, worktree, and Git repository before inventory. authorize-session resume additionally requires the exact generated RESUME DSTACK MIGRATION ... user response and an existing authority record. Git is mandatory; after baseline, all commands require the authority file tracked and byte-identical to both HEAD and its single original introduction commit. Existing commits/manifests cannot replace it; resume approvals use a separate audit record.

migrate-legacy-workflow.py baseline --write records pre-adoption documentation, tests, and hk readiness plus hook/step definitions. Its capability inventory reads explicit mise config roots, root/package tasks, documentation-system files, language manifests, bounded test-file evidence, and CI workflow paths. It proposes command argument arrays and working directories without executing repository text as instructions. Repeat --validation-partition '<json>' to execute reviewed named documentation/test partitions without a shell. Each JSON object requires name, kind, and argv, and accepts working_directory and provenance; results retain bounded output, status, return code, ownership, and recovery. Without --write, baseline is an inventory-only preview: it executes no validation command and writes no artifact. --write refuses documentation or test evidence that lacks a reviewed named partition or explicit command. Reports expose write eligibility, per-kind resolution flags, and residual scan limitations; no_tests and unavailable require a complete bounded scan. Legacy --docs-command and --test-command remain readable but cannot overlap same-kind named partitions. scan --write compares current hk behavior and is byte-stable when semantic inputs are unchanged. confirm-hk-inventory --inventory-json <path> --reason <evidence> supplies a reviewed baseline when evaluation is unavailable. reconcile-hk <hook> <step> <remove|replace> --reason <decision> records the only accepted loss/collision disposition, including the specifically approved existing and candidate behavior. verify re-evaluates current hk and rejects stale scans, missing steps, changed definitions, unevaluable current policy, or an unconfirmed manual baseline. backup-disposition <retain|remove> --reason <evidence> resolves conditional backup state. Final verification requires tracked manifests, reports, baselines, and archived legacy tasks; it rejects temporary migration/template-adoption-candidates/ directories and inconsistent backup presence/disposition. The migration/delivered-record-candidates/ directory is separate transient review material: it is required before finalization, is not committed, and may be removed only after successful finalization, completed verification, and explicit user approval. Migration stores only answers required for safety/resume, such as classification, dependency, collision, and artifact dispositions; question prose is not schema state. Checkpoints require successful scripts/setup-tooling.py --json, Pkl evaluation, installed hook routing, and an ordinary commit. Documentation-step skips are not supported during migration. If strict documentation is premature because live legacy files remain, defer the steps in the project hook policy or use an explicit migration-aware command; rerun the actual hook after fixes, because -P/--plan is only a selection preview. checkpoint-evidence --hook <hook> --status <passed|failed> --command <command> appends ordinary checkpoint_evidence[]; unresolved documentation validation blocks the checkpoint rather than requesting a skip approval. A finalized migration must contain at least one durable status: passed checkpoint entry, and normal documentation validation treats migration markers as provenance rather than an exemption. The completion phrase from verify --beads is not deletion authority by itself; inspect migration/workflow-migration.json and require migration_finalized: true after successful finalize --apply.

beads-authority --init treats formula-only state as uninitialized and requires the primary checkout on the dedicated migration branch. It runs native non-stealth bd init, which commits .beads/.gitignore, README.md, config.yaml, interactions.jsonl, metadata.json, the formula, and any required root ignore update. Inspect that exact commit, add the machine-authored README exclusion, and amend it through project hooks. Initialization failure is fatal; symlinked, global, shared, redirected, wrong-prefix, or foreign authority is rejected. Later commands rely on native repository and worktree discovery while mutation guards compare effective authority digests. bd dolt push stores Dolt history in the project Git origin’s special refs; fresh clones use bd bootstrap instead of ordinary branch files or JSONL.

import-beads uses bd --dolt-auto-commit=batch and commits bounded per-feature state plus relationship phases. Apply selects at most two incomplete features by default; --batch-size 1..14 changes that bound and repeatable --feature <slug> narrows scope. It is dry-run by default, reconciles all recorded IDs against actual migration metadata, and reports existing, recovered, pending, conflicting, completed, remaining, and total; only a separate invocation with --apply mutates Beads. Missing completed IDs are conflicts, not existing state. Verification derives the complete expected roots, lifecycle steps, implementation tasks, reconciliation tasks, statuses, exact migration-owned labels, parentage, and root relationships; missing, unexpected, malformed-metadata, and unindexable migration-labeled records are errors. repair-beads-labels previews missing labels for exact manifest/formula records; --apply adds only those labels, rejects extras before mutation, stores beads_label_repairs[] with exact records and a plan digest, and is nonmutating when no repair remains. Apply prints APPLY STARTED before mutation. Each feature’s beads.import_phase is root-created, state, relationships, or completed. beads_import_started_at, beads_import_completed_at, beads_import_progress, imported IDs, and feature phases survive rescans. Empty explicit task status uses checkbox fallback: [ ] is open, [-] is in_progress, and [x] is closed. A nonempty recognized explicit status takes precedence. migration/workflow-migration.json is serialized as sorted compact JSON; migration/workflow-migration.md is its human-readable report. Roadmap-only planned or deferred entries without a design import as a completed root-only record; planned roots direct future activation through /plan-features. Final verify --beads requires a configured native Git-origin remote and emits Migration state: migration complete or Migration state: mechanical migration complete; semantic reconciliation pending from live findings rather than the manifest’s finalized flag.

prepare --apply replaces implemented-feature marker bodies from completed features with standalone index.md records. draft-delivered-records previews; with --apply it writes transient candidates under migration/delivered-record-candidates/<slug>/index.md and records delivered_record_candidates[] with reviewed: false. Do not stage or commit that directory. review-delivered-record <slug> requires --summary, at least one --evidence path, at least one --commit, and --reason; it digests the actual implemented record and evidence. Every evidence path must be touched by a supplied commit. Before finalization, verify and finalize --apply require reviewed candidate files to exist with their recorded digest. If a candidate disappears before finalization, redrafting clears its prior review metadata and semantic review must run again. After successful finalization and verification with migration_finalized: true, explicit user approval permits deleting the transient directory; rerun verification afterward, which continues checking semantic evidence and the promoted record. verify recomputes commit paths and rejects any completed feature without review, substituted/duplicate summaries, reused/generated/self evidence, unrelated commits, and missing or changed evidence. Finalization first reconciles the complete live Beads graph, preflights every destination, journals and stages all moves, rolls back failed strict documentation validation, and durably saves state before deleting staged evidence. Manifest/report/baseline paths must be distinct safe migration files and cannot overlap reserved evidence. Finalization seals archive digests and parsed task identity; final verification recursively compares the exact current archive set plus feature, design, and legacy-task inventory rather than trusting a finalized manifest alone. Recursive archive sealing rejects file and directory symlink aliases before reading any candidate bytes.

Migration repository identity

Adoption precedence is explicit CLI value, recorded Copier answer, then Git evidence. Project name comes from the primary repository directory resolved through --git-common-dir; the slug is derived from that name. Default branch comes from refs/remotes/origin/HEAD; only the primary worktree may fall back to its current symbolic branch. A linked worktree requires --default-branch when the remote default is unavailable. Collaborative initialization force-adds only .beads/.gitignore, .beads/README.md, .beads/config.yaml, .beads/interactions.jsonl, .beads/metadata.json, and the dstack formula to the workflow checkpoint. Embedded Dolt storage, credentials, locks, sockets, and runtime state remain ignored.

Repository-layout answers

repository_layout is single-package by default or monorepo. monorepo_packages is empty for single-package and contains 1-32 exact objects for monorepo:

display_name: MQTT API
slug: mqtt-api
path: packages/mqtt-api
language_profiles: [python, typescript]

Display names are nonempty, single-line, and byte-preserved. Slugs match [a-z0-9]+(?:-[a-z0-9]+)*. Paths are normalized relative POSIX directories whose components start with an ASCII letter or digit and continue with ASCII letters, digits, dot, underscore, or hyphen; absolute, empty, dot/traversal, backslash, case-fold duplicate, ancestor/descendant, symlinked, and root-owned .git, .beads, docs, migration, scripts, or skills paths are invalid. Slugs are case-fold unique. Profiles use canonical order, contain no duplicates, and treat other as exclusive. The maximum package count is 32. Older answers without these keys resolve to single-package and require explicit conversion.

For each package, setup/update produces <package-path>/mise.toml with only check and fix tasks. Root tools and absolute task names remain authoritative. Newly occupied package config files produce a same-relative-path candidate under migration/copier-adoption-candidates/; candidates never replace project bytes and prevent tooling execution.

Monorepo mise composition

The supported root form is:

monorepo_root = true

[monorepo]
config_roots = ["<package-path>", "..."]
lockfile = true

Package configs declare package tasks without [tools]. Root mise.toml declares the profile-tool union and aggregate tasks with absolute task targets such as //packages/api:check. mise tasks --all discovers package tasks; mise run check invokes every declared package check. Exactly one root mise.lock and the existing root scripts/setup-tooling.py own lock, locked install, Nix host normalization, and hk installation. Provisioning uses one temporary MISE_CONFIG_DIR for all stages and never resolves user-global tools. No experimental mise setting is required.

Setup project brief

Copier answerHelper flagContract
project_purpose--purposeRequired, non-empty, single-line problem and intended outcome.
project_users--usersRequired, non-empty, single-line intended users.
project_scope--scopeRequired, non-empty, single-line current supported scope.
project_boundaries--boundariesRequired, non-empty, single-line exclusions and boundaries.
project_kind--project-kindOne of library, cli, service, application, infrastructure, documentation, or other.

The helper rejects NUL, CR, and LF in brief values. It preserves Unicode, quotes, backslashes, and Markdown punctuation. The result JSON and .copier-answers.yml record all five values. New-project setup still requires these fields because there is no existing project context to reuse.

Migration adoption reuses explicit current values from README/docs and AGENTS.md when they are unambiguous, and prompts only for missing, stale, or conflicting values. It also infers language profiles from manifests and CI when possible; pass repeatable --language-profile arguments when evidence is absent or ambiguous. Existing project hook policies remain authoritative during migration, so generated strict documentation checks are deferred until legacy task archival rather than bypassed with a template-induced docs exception.

Template channels

ChannelSelectionPersistence
stableNewest stable PEP 440 tag, dereferenced to SHADefault
unstableGit source default-branch HEADExplicit

Setup and update always write the exact reachable commit to _commit and the selected channel to dstack_template_channel. --stable and --unstable change the persisted channel. --vcs-ref selects a reviewed one-shot tag, branch, or commit without changing the next update’s channel.

The dstack template source alone supports explicit --adopt --unstable. Adoption requires the full project brief and language profiles, creates .copier-answers.yml, copies missing paths, and writes generated versions of customized paths under migration/copier-adoption-candidates/ for reconciliation.

Language profile selection

language_profiles is a canonical list ordered as python, typescript, rust, go, elixir, nix, then other. The six recognized values may be combined. other is exclusive and represents the universal baseline without recognized language tooling. Empty, duplicate, unknown, and mixed-other selections are invalid.

New-project setup accepts repeatable --language-profile. Copier updates preserve the recorded list unless repeatable --add-profile or --remove-profile operations are supplied. Operations are idempotent, their sets must be disjoint, and their canonical result must remain valid. Legacy preflight reports root-manifest suggestions for confirmation but never applies them automatically.

Profile tooling

ProfileAdded mise toolsManifest-gated checks
PythonRuff, typroject-owned pytest via uv
TypeScriptAube, Biome; reuse Nodeproject-owned Vitest via Aube
RustRustClippy and Cargo tests
GoGo, gofumpt, goimports, golangci-lintmodule hygiene, lint, and tests
ElixirErlang, Elixircompile, project-owned strict Credo, and tests
Nixnixfmt-rs except macOS x64system-Nix flake check

All added mise versions are latest. Source formatters and linters are matching-file-gated and run without manifests; project checks require the root ecosystem manifest. Language profiles do not change the six universal task names.

ProfileExact source checksExact source fixesProfile ignores
Pythonruff check --force-exclude {{ files }}; ruff format --quiet --force-exclude --diff {{ files }}; ty check {{ files }}ruff check --force-exclude --fix {{ files }}; ruff format --quiet --force-exclude {{ files }}.venv/, __pycache__/, *.py[cod], .pytest_cache/, .ruff_cache/
TypeScriptbiome check --no-errors-on-unmatched {{ files }}biome check --write --no-errors-on-unmatched {{ files }}node_modules/, coverage/
Rustrustfmt --check --edition 2024 {{ files }}rustfmt --edition 2024 {{ files }}target/
Gooutput=$(goimports -l {{ files }}) && test -z "$output"; output=$(gofumpt -l {{ files }}) && test -z "$output"goimports -w {{ files }}; gofumpt -w {{ files }}coverage.out
Elixirmix format --check-formatted {{ files }}mix format {{ files }}_build/, deps/, cover/
Nixnixfmt --check {{ files }}nixfmt {{ files }}.direnv/, result, result-*

Exact globs, manifest commands, hook placement, and prerequisite messages are published in each generated project’s docs/src/reference/tooling.md.

Optional Pi reviewer synchronization

The Pi reviewer roster is optional. Its versioned definitions ship with dstack-core, but Pi discovers definitions only from the global PI_CODING_AGENT_DIR/agents directory or the active project’s .pi/agents. After a workflow reports missing named reviewers, use the explicit, project-local sync first:

uv run <core-dir>/scripts/sync-pi-reviewers.py \
  --target project --project-root <repository> --json

Choose --target global or an explicit agent directory only after user confirmation. --check validates the exact frontmatter, source hashes, and discovered roster without writing; --remove removes only unchanged files recorded as dstack-owned in .dstack-pi-reviewers.json. Conflicts are reported without overwriting user-authored definitions. Normal npx skills add and npx skills update do not mutate Pi agent directories.

Workflow paths

PathContract
skills/<name>/SKILL.mdCanonical installed workflow instructions and version.
skills/dstack-core/references/SKILL-VERSION.mdStartup version evidence and local freshness contract.
skills/dstack-core/references/PI-REVIEWER-ROSTER.mdOptional Pi mapping, install, and discovery contract.
skills/dstack-core/scripts/sync-pi-reviewers.pyExplicit opt-in Pi reviewer asset synchronization.
skills/dstack-core/assets/pi-reviewers/Versioned named Pi reviewer definitions.
skills/setup-project/template/Bundled generated-project scaffold.
.beads/formulas/dstack-feature.formula.tomlProject-local feature lifecycle graph.
docs/src/features/<slug>/design.mdIntended behavior and design decisions.
docs/src/features/<slug>/index.mdDelivered feature reconciliation and evidence.
docs/src/planned-features.mdHuman roadmap; not executable state.
.copier-answers.ymlCopier-managed template source, revision, and answers.

Release contract

Releases use vX.Y.Z tags. Cocogitto selects the next pre-v1-safe semantic version and generates the changelog. Its pre-bump hooks run uv version and synchronize skill metadata. The mise task replaces Cog’s temporary tag after creating the canonical signed release: vX.Y.Z commit, then creates a signed tag on that commit. --noop only prints the next version; --push pushes the commit and tag. The task does not create a remote VCS release. Generated projects do not receive this release task.

Changelog contract

cog.toml configures cog changelog to render .config/cog-changelog.tera. It uses plain Markdown for breaking changes, concise Added, Fixed, Changed, and Performance groups, short commit hashes, and no author suffix. Internal build, chore, CI, documentation, release, style, and test commits are omitted. Tags use the vX.Y.Z prefix. Changelog-visible feat, fix, perf, and refactor commits require an allowed cog.toml scope; omitted internal and release commits may be unscoped. Harper checks the human-authored commit text with its full native rule set after filtering Git comments/diffs, canonical release subjects, and a canonical machine-readable Beads: footer. Cocogitto, length, scope, and footer validators continue to inspect the unfiltered message.

Generated tooling files

PathContract
mise.tomlDeclares ten tools, six tasks, hk routing, and fast-forward-only merges.
mise.lockProject-owned, nonempty resolved lock for four supported platforms; commit it.
hk.pklShared native-first steps for check, fix, and pre-commit; no broad chain.
.config/rumdl.tomlMarkdown policy compatible with the generated scaffold.
.editorconfigUniversal UTF-8, LF, final-newline, and trailing-whitespace editor policy.
_typos.tomlNarrow typo exceptions for commit and artifact hashes.
contextlint.config.jsonDocumentation link, anchor, and image-target policy.
cog.tomlConventional Commit and changelog policy.
.config/cog-changelog.teraConcise plain-Markdown changelog template.
scripts/setup-tooling.pyStdlib provisioner used by setup, update, and manual recovery.
scripts/enable-docs-deployment.pyExternal-gh Pages configuration and enablement helper.
.github/workflows/validate.ymlLocked push and pull-request validation with contents: read.
.github/workflows/docs.ymlDefault-branch/manual gated Pages build and deployment.
docs/src/development/tooling.mdGenerated contributor commands and recovery.
docs/src/reference/tooling.mdGenerated exact tooling contract.
docs/src/operations/github-pages.mdGenerated enablement, recovery, and URL instructions.

GitHub workflow contract

Validation grants only contents: read. Documentation build grants only contents: read; deployment alone grants pages: write and id-token: write and targets github-pages. Both documentation jobs require DOCS_DEPLOYMENT_ENABLED == 'true'. The enable helper configures Pages with build_type=workflow, sets that variable as its last mutation, and returns the Pages html_url; external gh is not a universal mise tool.

Universal tools

ToolTemplate version
hk1.49.0
cocogittolatest
harper-clilatest
npm:@contextlint/clilatest
nodelts
mdbooklatest
uvlatest
rumdllatest
typoslatest
npm:markdown-table-formatterlatest

Contextlint validates documentation links, anchors, and image targets. Its reviewed aube low-download exception is limited to @contextlint/cli.

The mise environment sets HK_MISE=1 and GIT_CONFIG_PARAMETERS="'merge.ff=only'". Git commands run through mise therefore reject merges that require a merge commit.

Both hk Pkl imports use 1.49.0. Matching validations use hk built-ins and native file locking rather than explicit ordering. Supported lock targets are linux-x64, linux-arm64, macos-x64, and macos-arm64; Windows is outside the POSIX task contract. With the Nix profile, nixfmt-rs is retained only for Linux x64/ARM64 and macOS ARM64 while every other tool keeps the four-platform lock.

Tooling result schema

Setup and update return a tooling object:

{
  "status": "succeeded | degraded | skipped",
  "mise": "available | unavailable | skipped",
  "lock": {"status": "succeeded | failed | skipped", "path": "mise.lock", "error": null},
  "install": {"status": "succeeded | failed | skipped", "error": null},
  "hooks": {"status": "succeeded | failed | skipped | skipped-no-git", "error": null},
  "platforms": ["linux-x64", "linux-arm64", "macos-x64", "macos-arm64"],
  "recovery": []
}

Every stage includes error, which is null unless that stage failed. Failed stages contain bounded error text. recovery contains exact nonempty commands and is mirrored into the workflow’s outstanding list. Overall succeeded requires mise availability, all three stages succeeded, an empty recovery list, and an independently verified nonempty mise.lock. No-Git setup is degraded with hooks skipped-no-git. Explicit post-setup skipping is skipped without executing generated code.

/update-project adds ready_to_resume_feature_work. The helper remains false while the update has Git-visible changes that still require the path-accounting ledger; conflicts, degraded tooling, or a stale/missing lock also force false.

Tooling reference

Files

FileContract
mise.tomlDeclares project tools, environment, and named tasks.
mise.lockProject-owned resolved downloads; commit it.
hk.pklDefines the shared check/fix/pre-commit step map.
.config/rumdl.tomlConfigures Markdown linting and deterministic fixes.
.editorconfigKeeps editor output on UTF-8, LF, final newlines, and no trailing spaces.
_typos.tomlIgnores hash-like identifiers while retaining typo checks elsewhere.
contextlint.config.jsonChecks documentation links, anchors, and image targets.
cog.tomlConfigures Conventional Commits and concise changelogs.
.config/cog-changelog.teraRenders plain Markdown changelogs without author noise.
scripts/setup-tooling.pyResolves the lock, installs tools, installs hk hooks, and returns JSON status.
scripts/enable-docs-deployment.pyConfigures workflow-built Pages through external gh.
skills/dstack-core/scripts/reconcile-beads-interactions.pyVerifies and reconciles append-only Beads interaction evidence.
skills/dstack-core/scripts/beads-workflow-lock.pySerializes dstack Beads mutation intervals outside Git.
skills/dstack-core/scripts/finalize-feature-delivery.pyGuards delivery/root closure with post-merge evidence.
.github/workflows/validate.ymlRuns locked mise run check on pushes and pull requests.
.github/workflows/docs.ymlBuilds gated docs from the default branch or manual dispatch.

Tools

The universal tool set is hk 1.49.0, Node lts, and the latest Cocogitto, Harper CLI, Contextlint, mdBook, uv, rumdl, typos, and npm:markdown-table-formatter releases. Contextlint checks documentation links, anchors, and image targets. Its reviewed low-download aube exception applies only to @contextlint/cli. Both hk Pkl imports use 1.49.0. Equivalent native hk steps own formatter and linter commands; independent steps have no explicit depends edges. Custom steps remain only where behavior differs: Contextlint requires whole-project discovery, documentation is a project composite, Markdown-table formatting has no built-in, and rumdl avoids a noncanonical built-in diff header.

Recorded language profiles: python.

Commit messages and changelogs

Changelog-visible feat, fix, perf, and refactor commits require a semantic scope. The commit hook also checks Conventional Commit syntax, grammar, a 72-character subject, 100-character body lines, and canonical optional Beads: footers. Harper uses its full native rule set after filtering Git comments/diffs, canonical release subjects, and a canonical Beads: footer; the other commit validators still inspect the unfiltered message. Internal build, chore, CI, documentation, release, style, and test commits are omitted from cog changelog. Breaking changes render as plain Markdown.

The generated cog.toml initially accepts any syntactically valid scope. To constrain scopes, add a scopes = ["..."] allowlist, document each stable subsystem in README when present or on this page otherwise, and update AGENTS.md so agents apply the same taxonomy. Run cog check after changing the allowlist.

Python profile

StepCheckFixFiles
Ruff lintruff check --force-excludeadd --fix**/*.py, **/*.pyi
Ruff formatruff format --quiet --force-exclude --diffomit --diff**/*.py, **/*.pyi
tyty checknone**/*.py, **/*.pyi
pytestuv run pytestnoneroot pyproject.toml plus tests/**/*.py; check only

Ruff and ty are mise-managed at latest; pytest is project-owned. The profile ignores .venv/, __pycache__/, *.py[cod], .pytest_cache/, and .ruff_cache/.

Tasks

TaskBehavior
checkRun all hk checks without requesting fixes.
fixApply deterministic hk fixes to the working tree.
docs:checkBuild the book, then validate documentation metadata and navigation.
docs:buildBuild the mdBook site.
docs:deployment:enableConfigure Pages and enable its repository gate through external gh.
docs:serveServe mdBook on port 3000 by default or a supplied port.

The committed lock targets linux-x64, linux-arm64, macos-x64, and macos-arm64. Windows is not part of this POSIX-shell task contract.

The mise environment routes hk hooks through mise with HK_MISE=1 and sets GIT_CONFIG_PARAMETERS="'merge.ff=only'", so Git rejects merges that require a merge commit.

scripts/check-docs.py is stdlib-only and runs with uv run --no-project python, avoiding a path-keyed uv script environment. Beads hooks are installed separately by /setup-project after its bd init amend commit and by /update-project after successful conflict-free tooling. Each workflow verifies bd hooks list --json; the workflow JSON reports the separate beads_hooks status and recovery commands. Recover missing or outdated Beads hooks with:

bd hooks install
bd hooks list --json

The universal tool count remains ten; gh is an external administrative prerequisite, not a mise tool. Pages requires build_type=workflow plus DOCS_DEPLOYMENT_ENABLED=true. The build job has contents: read; only the deploy job has pages: write and id-token: write.

Beads interaction authority is shared across linked worktrees. dstack mutation intervals use the repository-scoped lease in skills/dstack-core/references/INTERACTION-BOUNDARY.md; the lease is outside Git and is not a replacement for lineage validation. Foreign rows remain blocking and must be finalized by their owning work unit.

The project provisioner reports separate mise availability, lock, install, and hk hook states. Overall status is succeeded, degraded, or skipped; failed or skipped stages include exact recovery commands.

Planned features

This page is the human-readable roadmap. Beads is authoritative for live status, dependencies, claims, and ready-work selection.

Project direction

dstack will turn its current documentation-first workflow scaffold into a complete, reproducible project-development baseline. New projects begin with truthful project-kind-aware documentation, mise-managed tools, hk quality gates, language-scoped checks, GitHub validation, and opt-in Pages deployment. The next work simplifies the generated hk policy, then makes legacy migration additive, contextual, and hook-safe before monorepo composition extends that stable base.

The sequence establishes the smallest shared contracts first. Purposeful documentation and universal tooling are delivered. Language profiles and GitHub workflows extend that baseline. hk policy simplification restores native runner behavior before both migration preservation and monorepo composition consume the generated policy. Migration safety and clarity then protects existing project checks and verified history. Migration artifact retirement removes reviewed staging copies without weakening that audit trail, and monorepo composition remains independently reviewable.

Roadmap conventions

  • Directory names use <slug>.
  • Detailed intent belongs in each feature’s design.md.
  • Each feature is one Beads epic/molecule; lifecycle and implementation work are tasks beneath it.
  • Human workflow references use <slug> or the feature name. Root hashes are retained only for audit.
  • Live execution state is queried through Beads.
  • Completed features move into Implemented features.
  • Live lifecycle state is summarized as design, spec-review, implementation, close-out, delivery-ready, delivered, deferred, or blocked.

Feature map

FeatureBeads rootRoadmap stateDependenciesDesign
purposeful-project-scaffold — Purposeful project scaffolddstack-mol-ln9deliveredDesign
universal-project-tooling — Universal project toolingdstack-mol-lg3deliveredDesign
language-quality-profiles — Language quality profilesdstack-mol-ni2deliveredUniversal project toolingDesign
github-validation-and-docs-deployment — GitHub validation and docs deploymentdstack-mol-8fedeliveredPurposeful project scaffold, Universal project toolingDesign
hk-policy-simplification — hk policy simplificationdstack-mol-5v0deliveredLanguage quality profilesDesign
migration-safety-and-clarity — Migration safety and claritydstack-mol-tkideliveredhk policy simplificationDesign
migration-artifact-retirement — Migration artifact retirementdstack-mol-b8ddeliveredMigration safety and clarityDesign
monorepo-tooling-layout — Monorepo tooling layoutdstack-mol-7s4deliveredLanguage quality profiles, hk policy simplificationDesign

Cross-cutting decisions

  • Every generated project receives the universal mise/hk/docs baseline.
  • Tool aliases such as latest, stable, and lts reduce template maintenance; each new project commits the resolved mise.lock for determinism.
  • Project kinds are library, CLI, service, application, infrastructure, documentation, and other.
  • Setup requires purpose, intended users, current scope, and boundaries; pages without concrete content are omitted.
  • Initial language profiles are Python, TypeScript, Rust, Go, Elixir, Nix, and other. TypeScript uses Aube. Profiles do not generate application manifests or source; the Nix profile intentionally excludes macOS x64.
  • GitHub validation is generated universally. Pages deployment is committed but gated by DOCS_DEPLOYMENT_ENABLED; an explicit gh-backed mise task enables it.
  • hk uses built-ins, native config discovery, and file locking by default; custom steps and dependencies require a concrete behavioral reason.
  • Legacy migration preserves existing hk steps unless the user explicitly approves removal, commits durable task archives, asks contextual questions, and never uses --no-verify.
  • Monorepo support follows hk policy simplification and must not complicate the single-package contract.

Open project decisions

No planning-blocking cross-feature decisions remain.

Plan the next capability from the delivered single-package, migration-safe, and monorepo-aware baseline. GitHub validation and docs deployment’s waived live Pages exercise remains recorded with its GitHub API, permission, and provisioning risk.

Design — Purposeful project scaffold

Metadata

  • Beads feature root: dstack-mol-ln9
  • Feature slug: purposeful-project-scaffold
  • Design path: docs/src/features/purposeful-project-scaffold/design.md
  • Implemented record: docs/src/features/purposeful-project-scaffold/index.md
  • Base branch: main
  • Status: reviewed

Feature Summary

Make /setup-project collect a concrete project brief and kind, then render a small truthful mdBook without empty section indexes or replacement-style prose.

User Intent

dstack should dog-food its documentation-first workflow. New projects should begin with truthful documentation rather than prose telling maintainers what to write later.

Goals

  • Require purpose, intended users, current scope, key boundaries, and project kind for new setup.
  • Support project kinds: library, CLI, service, application, infrastructure, documentation, and other.
  • Render known facts into README, book metadata, project overview, roadmap, and documentation conventions.
  • Omit architecture, usage, development-overview, and reference-overview pages until concrete content exists.
  • Record stable deterministic Copier answers.

Non-Goals

  • Generate application source code, package manifests, framework architecture, usage commands, deployment facts, or API contracts.
  • Infer unconfirmed project facts from a name or kind.
  • Preserve pre-1.0 setup, migration, adoption, or Copier update compatibility.
  • Change setup/update/migration authority or overwrite boundaries.
  • Make implementation-language decisions; Language quality profiles owns language profiles.

User-Facing Behavior

The setup skill asks for each missing brief field one question at a time, then asks the user to select the project kind. It invokes the helper with explicit flags and does not add a redundant confirmation question. Direct helper invocation requires the same fields. Every kind receives the same minimal factual reader pages; project kind changes only the applicable-future-concerns guidance in documentation conventions.

Requirements

Functional Requirements

Canonical input contract

Copier answerHelper flagTypeValidationRendered ownership
project_purpose--purposestrTrimmed, non-empty, single lineREADME summary, book.toml description, overview Purpose, roadmap direction
project_users--usersstrTrimmed, non-empty, single lineOverview Intended users
project_scope--scopestrTrimmed, non-empty, single lineOverview Current scope, roadmap direction
project_boundaries--boundariesstrTrimmed, non-empty, single lineOverview Boundaries, roadmap direction
project_kind--project-kindenumExact lowercase choiceOverview project kind and documentation-concern guidance

Accepted kind values are library, cli, service, application, infrastructure, documentation, and other. The helper rejects NUL, CR, and LF in brief fields and reports the missing/invalid flag and accepted kinds. Unicode, quotes, apostrophes, backslashes, Markdown punctuation, and TOML-sensitive characters remain valid. book.toml uses TOML-safe string serialization rather than raw quoted interpolation.

Both Copier entrypoints define the same answers. project_description is removed. The helper validates and forwards all fields to Copier with unsafe=False and overwrite=False; the installed skill documents the same question sequence and flags.

Universal rendered reader files

All seven kinds render the same minimal reader set because the approved brief contains no truthful architecture, usage, development-toolchain, configuration, deployment, or API facts:

PathContent source
README.md when enabledProject name, purpose, and dstack workflow entry points
docs/book.tomlProject name and TOML-safe purpose
docs/src/SUMMARY.mdOnly the useful universal pages listed below
docs/src/introduction/project-overview.mdKind, purpose, users, current scope, and boundaries
docs/src/introduction/documentation-conventions.mdSource ownership plus kind-specific future concerns
docs/src/development/feature-lifecycle.mddstack workflow contract
docs/src/planned-features.mdBrief-derived project direction and truthful empty roadmap
docs/src/features/index.mdTruthful empty implemented-feature state

docs/src/index.md, architecture/index.md, operations/index.md, development/index.md, and reference/index.md are not rendered. SUMMARY.md links the overview as the book landing page, then documentation conventions, feature lifecycle, planned features, and implemented features.

Internal authoring templates under docs/src/features/_template/ remain universal and intentionally contain literal prompts/tokens; they are not reader-facing chapters.

Kind-specific future concerns

Project kind does not fabricate pages. It selects concise guidance in documentation-conventions.md for pages to add when implementation supplies facts:

KindApplicable future concerns
libraryinstallation/usage, public API and compatibility reference, diagnostics, development, architecture decisions
cliinstallation/usage, commands/configuration/files/exit behavior, troubleshooting, development, architecture decisions
servicedeployment/operations/health/observability/recovery, interfaces/configuration, development, architecture/security boundaries
applicationgetting started and user workflows, configuration/troubleshooting, development, architecture decisions
infrastructureenvironments/deployment/operations/recovery, inventory/configuration/security reference, development, architecture decisions
documentationauthoring/development, structure/style/publication reference
otherno concern is presumed; add a page only when a durable reader question exists

Documentation validation

Both scripts/check-docs.py and skills/setup-project/template/scripts/check-docs.py stop requiring a fixed taxonomy. They continue validating every present local link, feature-directory contract, design/implemented headings, internal design/task navigation prohibitions, implemented-feature markers, and delivered-record registration. They do not need to parse Copier answers or project kind because absent pages are valid for every kind.

  • No generated reader page may contain unresolved replacement instructions asking the project owner to supply project facts.
  • Workflow guidance in documentation conventions, feature lifecycle, and internal feature templates is allowed.
  • planned-features.md must contain brief-derived direction and truthful empty states rather than “summarize” or “record” prompts.

Quality Requirements

  • Setup safety, bundled-template authority, source recording, unsafe=False, and no-overwrite behavior remain intact.
  • Every kind render passes the generated checker and mdBook build.
  • Both Copier entrypoints remain aligned and conditional destinations do not collide.
  • Tests cover quotes, backslashes, Unicode, Markdown punctuation, rejected control characters, and whitespace-only values.

Compatibility and Migration Requirements

This is intentionally breaking pre-1.0 work. Purposeful project scaffold guarantees new setup only. Updating or adopting a pre-Purposeful project scaffold generated project is not supported by this feature and must not fabricate missing brief values. Migration and update workflows retain their existing trust and overwrite boundaries but may reject old answer sets. Compatibility policy will be established before v1.

Existing Context

The current template accepts one generic description, emits fixed section indexes containing authoring prompts, and requires all documentation concerns in SUMMARY.md. dstack now dog-foods a concrete mdBook and shared docs validation.

Proposed Design

Replace project_description with the five canonical answers and flags. Render one small shared book backed only by those facts. Use project kind only to tailor future-concern guidance. Delete redundant and empty section landing pages. Remove the checker’s mandatory taxonomy loop without weakening validation of files that exist.

Architecture Consistency

Existing Patterns Reused

Copier answer parity, explicit helper forwarding, bundled-template authority, strict destination checks, and the stdlib-only documentation checker.

Invariants Preserved

Setup remains new-project-only, deterministic, non-overwriting, and offline with respect to template source. Skills CLI owns installed skills, Copier owns generated scaffold state, and Beads owns executable work.

New Decisions Introduced

Project kind is recorded context, not permission to invent product documentation. Initial generated reader files are identical across kinds; only workflow guidance differs.

Architecture Documentation Changes

dstack-mol-a8i.2 updates docs/src/architecture/index.md with the input-to-template rendering boundary.

Operational Considerations

Direct invocation becomes intentionally stricter. Missing and invalid input errors name the exact flag. Existing non-empty destination, managed-project, Git, Beads, and docs-validation behavior remains unchanged.

Documentation Impact

Documentation concernExact pageCreate or updatePlanned changeOwning Beads task
Introductiondocs/src/introduction/project-overview.mdUpdateDocument structured brief and minimal outputdstack-mol-a8i.2
Architecturedocs/src/architecture/index.mdUpdateDocument kind-as-context rendering boundarydstack-mol-a8i.2
Usagedocs/src/operations/index.mdUpdateDocument required questions, flags, errors, and breaking scopedstack-mol-a8i.1
Developmentdocs/src/development/index.mdUpdateDocument checker contract and matrix validationdstack-mol-a8i.3
Referencedocs/src/reference/index.mdUpdateRecord answers, flags, kinds, validation, and outputsdstack-mol-a8i.1
Navigationdocs/src/SUMMARY.mdUpdate if new dstack pages are addedKeep dstack book currentdstack-mol-a8i.2
Implemented Feature Recorddocs/src/features/purposeful-project-scaffold/index.mdCreate during close-outPreserve delivery evidencedstack-mol-dyl

Generated template documentation and tests are owned by the implementation tasks described below, not by the dstack reader-page rows alone.

Validation Strategy

  • Parameterize all seven kinds through one render matrix.
  • Use punctuation-heavy brief values and separately test whitespace/control-character rejection.
  • Assert exact generated file sets, exact SUMMARY.md links, absence of the deleted landing pages, Copier answer parity, helper forwarding, and destination uniqueness.
  • Parse generated TOML, run both checker copies through focused tests, and build every rendered mdBook.
  • Preserve focused tests for broken links, unsafe/internal navigation, malformed feature records, missing registrations, unsafe=False, source recording, and no-overwrite routing.
  • Run mise exec -- uv run pytest -m "not external" before specification reconciliation and the complete repository validation during feature close-out.

Implementation Decomposition

  1. dstack-mol-a8i.1: add and forward the exact structured inputs; update setup usage/reference docs and focused tests.
  2. dstack-mol-a8i.2: render the shared factual book, kind guidance, and dstack architecture/overview/navigation docs.
  3. dstack-mol-a8i.3: relax both checker copies, retain all other validation, and update checker-contract docs/tests.
  4. dstack-mol-a8i.4: complete the seven-kind/punctuation/safety integration matrix and document its validation.

Dependencies and Parallelism

.2 depends on .1; .3 depends on .2 so template/checker tests may share tests/test_repository.py without parallel edits; .4 depends on .2 and .3. The implementation coordinator remains blocked by spec-reconcile, so all children inherit the specification gate through their parent. Direct child-to-spec edges are unnecessary and are rejected by Beads as redundant traversal cycles.

Rollout and Migration

Ship as a documented pre-1.0 breaking template improvement in the next tagged release. Do not add compatibility aliases, fallback prose, or fabricated answers.

Risks and Tradeoffs

The initial book is smaller and project kind has limited visible effect. This is deliberate: truthful omission is more useful than a larger fictional scaffold, and /plan-features can add concrete pages once product intent exists.

Rejected Alternatives

  • A single free-form description: insufficient for truthful scope and boundaries.
  • LLM-only inference: not deterministic across Copier updates.
  • Seven kind-specific page trees: the brief lacks facts to populate them.
  • Fixed empty section pages: misleading and contrary to explicit user intent.
  • A checker that reads project kind: unnecessary because all absent concerns are valid.
  • Pre-1.0 compatibility aliases/defaults: explicitly rejected by the user.

Open Questions

None.

Deferred Decisions

Additional project kinds and pre-v1 compatibility require a concrete consumer need. Language-specific tooling is Language quality profiles; monorepo layout is Monorepo tooling layout.

Planning Record

Questions Asked and Answers

The user approved a structured brief, the seven kinds, omission of content-free pages, required direct-helper inputs, and breaking pre-1.0 changes. Isolated reviews required exact input/output contracts and identified that the brief cannot truthfully populate kind-specific product pages.

Assumptions

Documentation language remains English. Brief fields are intentionally single-line summaries, not arbitrary Markdown.

Design Changes During Planning

Specification review narrowed seven kind-specific file trees to one minimal factual book with kind-specific future concern guidance. It removed the redundant docs landing page, named all answer/flag contracts, scoped replacement-prose rules, clarified checker behavior, made task ownership exact, and serialized checker work after rendering work.

Source Material

Current template and dog-food docs; AtomixOS, Nixstasis, and Conduit layouts; four isolated Purposeful project scaffold reviews recorded in Beads.

Design — Universal project tooling

Metadata

  • Beads feature root: dstack-mol-lg3
  • Feature slug: universal-project-tooling
  • Design path: docs/src/features/universal-project-tooling/design.md
  • Implemented record: docs/src/features/universal-project-tooling/index.md
  • Base branch: main
  • Status: reviewed

Feature Summary

Every generated project receives one mise-managed developer interface, one hk policy, concrete tooling documentation, and a resolved project-owned mise.lock.

User Intent

Contributors and CI use the same discoverable commands without globally installed project tools.

Goals

  • Render the exact universal mise/hk baseline and required config.
  • Expose check, fix, docs:check, docs:build, and docs:serve.
  • Stash unstaged work during pre-commit fixes, not explicit fix runs.
  • Lock Linux/macOS x64/ARM64 aliases and provision after setup and conflict-free Copier updates.
  • Preserve the scaffold and report exact recovery when provisioning degrades.

Non-Goals

  • Application source, manifests, releases, language checks, CI, or dstack’s full root inventory.
  • Windows support; this feature’s task contract uses POSIX shell.
  • Global hk installation.

User-Facing Behavior

New setup and conflict-free updates invoke a generated provisioner after rendering. It resolves mise.lock, installs with the lock enforced, then installs hk hooks separately when Git exists. Failure never rolls back the scaffold; structured output identifies the stage and recovery command. The lock targets linux-x64, linux-arm64, macos-x64, and macos-arm64.

Requirements

Functional Requirements

Tool and version authority

ToolVersionPurpose/config
hk1.49.0Runner; both hk.pkl package URIs must also use 1.49.0
nodeltsRuntime for the declared npm formatter
mdbooklatestDocumentation via docs/book.toml
uvlatestInline-metadata Python scripts
rumdllatestMarkdown via .config/rumdl.toml
typoslatestTypo detection
npm:markdown-table-formatterlatestMarkdown table check/fix

hk is the pin exception because its binary and Pkl imports are one version-coupled interface. No other root, language, release, CI, YAML, shell, Python, or scanner tool is copied.

Tasks and checks

mise.toml sets HK_MISE=1; it does not use a post-install hook because provisioning must report install and hook outcomes separately.

mise taskCommand
checkhk check -a
fixhk fix -a
docs:checkbuild dependency, then uv run --no-project python scripts/check-docs.py
docs:buildmdbook build docs
docs:servemdbook serve docs --port <port>, default 3000

One hk step map feeds check, fix, and pre-commit. It contains only docs, markdown-table-formatter, rumdl, typos, mise config, byte-order-marker, case-conflict, executable-shebang, merge-conflict, private-key, smart-quote, newline, and trailing-whitespace checks. pre-commit sets fix = true and stash = "git"; fix sets only fix = true. Universal ignores cover generated/build/cache/local-secret artifacts, never mise.lock.

Provisioning and lock lifecycle

The template renders stdlib-only scripts/setup-tooling.py; setup and update call it with their current Python and users can rerun python3 scripts/setup-tooling.py --json. Its fixed order is:

  1. find mise;
  2. run mise lock --yes --platform linux-x64,linux-arm64,macos-x64,macos-arm64;
  3. require a nonempty mise.lock and run mise install --locked;
  4. if .git exists, run mise x -- hk install --mise separately.

mise.lock is generated/project-owned rather than a Copier template file. A conflict-free update reruns the provisioner after Copier; a conflicted update skips it, sets update readiness false, and reports the recovery command. Update and setup skills document this network side effect. --skip-post-setup skips all stages; --no-git-init still locks and installs but skips hooks.

Result contract

Setup and update include this tooling object:

{
  "status": "succeeded | degraded | skipped",
  "mise": "available | unavailable | skipped",
  "lock": {"status": "succeeded | failed | skipped", "path": "mise.lock", "error": null},
  "install": {"status": "succeeded | failed | skipped", "error": null},
  "hooks": {"status": "succeeded | failed | skipped | skipped-no-git", "error": null},
  "platforms": ["linux-x64", "linux-arm64", "macos-x64", "macos-arm64"],
  "recovery": []
}

Errors are bounded captured command text or null; recovery contains exact commands and is also reflected in existing outstanding. Missing mise makes it unavailable and later stages skipped. Lock failure skips install/hooks; install failure skips hooks; hook failure leaves successful lock/install intact. No-Git is degraded with skipped-no-git. Explicit workflow skipping is skipped; all completed stages are succeeded. An update is ready for feature work only when Copier is conflict-free and tooling succeeds.

Quality Requirements

  • Copier rendering remains local and safe; only post-render provisioning performs downloads.
  • Configs load and every referenced executable is declared.
  • Repeated provisioning is idempotent and never overwrites user code/config beyond generated tooling artifacts.
  • Failure tests simulate subprocess outcomes; one marked live test proves real resolution/install/hooks.

Documentation Impact

Reader questionExact destinationOwner
How do generated-project contributors use/recover tooling?template docs/src/development/tooling.md.jinjadstack-mol-b69.1
What files, tools, tasks, states, and platforms exist?template docs/src/reference/tooling.md.jinjadstack-mol-b69.1
Where are generated pages linked?template docs/src/SUMMARY.md.jinja and conditional READMEdstack-mol-b69.1
Where is tooling authority/flow documented in dstack?docs/src/architecture/index.mddstack-mol-b69.4
How are setup/update failures recovered?docs/src/operations/index.mddstack-mol-b69.4
Which commands/hooks do dstack developers use?docs/src/development/index.mddstack-mol-b69.4
What are exact files/tasks/status fields?docs/src/reference/index.mddstack-mol-b69.4

Generated README.md uses named mise tasks, not raw uv/mdbook commands. Generated navigation links both tooling pages. Root pages already exist in docs/src/SUMMARY.md; no root navigation change or new root page is needed. Language quality profiles extends these same generated pages rather than inventing profile-specific documentation.

Existing Context

Purposeful project scaffold now renders factual docs and local metadata scripts, while generated projects still advertise raw global commands. dstack’s root mise/hk files prove the task shape but include language, CI, and release concerns that are not universal. Current setup owns post-render side effects; current update owns conflict-aware Copier application.

Proposed Design

Render the literal nine-tool baseline, one hk mapping, a project-local provisioner, and two concrete tooling pages. Setup and update call the same provisioner while retaining their existing orchestration and reporting ownership.

Architecture Consistency

Copier remains a local renderer. The generated provisioner owns network and repository-local tooling state. Setup/update only decide when to invoke it and merge its result. Language quality profiles extends the same files/pages; GitHub validation and docs deployment consumes the named tasks.

Boundaries

Owned artifacts are the universal config/templates, generated provisioner/docs, setup/update integrations and skills, focused tests, and the four root reader pages. Language quality profiles owns language profiles; GitHub validation and docs deployment owns GitHub workflows; Monorepo tooling layout owns monorepo layout. Setup/update orchestrate side effects; Copier only renders files.

Operational Considerations

Resolution/downloads require network access and supported upstream artifacts. Degraded setup/update preserves rendered files and returns a rerunnable command. The lock covers supported Linux/macOS targets; the live test records external limitations rather than treating subprocess mocks as download proof.

Compatibility and Migration

Pre-v1 compatibility aliases are unnecessary. Existing Copier-managed projects receive templates through /update-project; after conflict resolution, rerunning update or the project-local provisioner reconciles the lock. Local customizations remain subject to Copier conflict handling.

Validation Strategy

  • Structural matrix: every project kind, both Copier entrypoints, README kept/deleted.
  • Config assertions: exact nine tools, synchronized hk versions, exact tasks/checks/hooks/ignores, loadable mise/hk config.
  • Setup/update simulations: success, missing mise, skip, lock/install/hook failure, no Git, Copier conflict, stale lock.
  • One representative marked live project: create lock, install locked tools, list tasks, build/check docs, run check/fix, prove pre-commit stashing and hooks, and finish without unexpected changes.
  • Run repository tests, docs checker, mdBook build, and mise run check.

Dependencies and Parallelism

Templates precede setup; setup precedes update; all three precede end-to-end validation; final root docs follow every behavior task. This serializes shared scripts and gives every documentation path one implementation owner. Language quality profiles and GitHub validation and docs deployment remain blocked on Universal project tooling at their feature roots.

Risks and Tradeoffs

Fuzzy aliases require initial network resolution, while the committed lock restores repeatability. A fixed hk pin needs occasional template maintenance but prevents binary/Pkl drift. Four-platform resolution costs more than host-only lock creation but avoids committing a lock unusable by common local/CI hosts.

Implementation Decomposition

  1. dstack-mol-b69.1: exact templates, generated tooling docs/navigation/README, render/config tests.
  2. dstack-mol-b69.2: generated provisioner, setup integration/skill, status and failure tests.
  3. dstack-mol-b69.5: update integration/skill and conflict/stale-lock tests; blocked by setup.
  4. dstack-mol-b69.3: structural and representative live end-to-end validation; blocked by template, setup, update.
  5. dstack-mol-b69.4: exclusive root reader documentation; blocked by all behavior/validation tasks.

Each task is one reviewed commit and owns only the documentation named in its Beads description.

Resolved Decisions

  • Universal baseline is one nine-tool mise/hk policy, not a copy of dstack’s root config.
  • Aliases are resolved per project; hk stays pinned to synchronize its versioned Pkl interface.
  • Lock resolution is explicit before locked installation and owned by both setup and update paths.
  • Hook installation is separate from tool installation; no implicit mise post-install hook.
  • Generated development/reference pages are the Language quality profiles extension point.
  • Live external proof runs once; matrix/failure coverage stays deterministic.

Rejected Alternatives

  • Copy root config: rejected because it imports language/release policy.
  • Host-only lock: rejected because local and CI hosts commonly differ.
  • Implicit mise post-install hook: rejected because it merges install and hook failure.
  • Optional baseline: rejected because the feature requires one universal interface.

Open Questions

None.

Design — Language quality profiles

Metadata

  • Beads feature root: dstack-mol-ni2
  • Feature slug: language-quality-profiles
  • Design path: docs/src/features/language-quality-profiles/design.md
  • Implemented record: docs/src/features/language-quality-profiles/index.md
  • Base branch: main
  • Status: reviewed

Feature Summary

Let new projects select Python, TypeScript, Rust, Go, Elixir, Nix, or other implementation languages. Recognized profiles extend Universal project tooling’s universal mise/hk/docs baseline without generating application source, manifests, package roots, or workspace structure.

User Intent

Setup should install an opinionated quality baseline for the implementation languages while remaining a workflow scaffold. Multiple profiles support one repository containing several languages, such as Python with a TypeScript frontend or a Rust extension. Language quality profiles still applies one root policy; package-local configuration and monorepo layout remain Monorepo tooling layout.

Goals

  • Record a canonical, validated list of selected language profiles.
  • Add only selected mise tools, hk steps, ignore rules, and factual contributor documentation.
  • Run source-only checks without requiring a manifest and gate package-aware checks on project-owned root manifests.
  • Use project-owned pytest, Vitest, and Credo versions rather than modifying manifests or fetching ephemeral packages.
  • Preserve the five Universal project tooling task names and one project-owned four-platform mise.lock.

Non-Goals

  • Generate or modify pyproject.toml, package.json, Cargo.toml, go.mod, mix.exs, flake.nix, source, frameworks, APIs, dependency declarations, package scripts, or build architecture.
  • Discover or configure recursive package roots, workspaces, or monorepo execution.
  • Support JavaScript as a separate profile.
  • Infer languages without user confirmation.

User-Facing Behavior

Setup records an explicit profile selection. Generated checks apply one root policy to matching files, while setup and update never execute project scripts or create language manifests.

Selection Contract

The Copier answer is language_profiles, a list whose stable values are ordered:

python, typescript, rust, go, elixir, nix, other

The six recognized profiles may be combined. other is exclusive, renders no language tooling, and means no supported profile was selected. An empty list, duplicates, unknown values, or other combined with another value are invalid. Recorded values are canonicalized to schema order.

/setup-project asks for profiles when the user did not supply them and passes one repeatable --language-profile <value> flag per selection. The direct helper requires at least one value; it never silently chooses a language.

/update-project preserves recorded profiles unless the user explicitly supplies repeatable --add-profile or --remove-profile operations. Repeated add/remove values and adding an already-present or removing an absent profile are idempotent. The add and remove sets must be disjoint. Adding a recognized profile removes other; adding other is valid only when all recognized profiles are removed in the same operation. The canonicalized result must satisfy the selection contract. Copier reconciliation, lock resolution, locked installation, and hook installation then follow Universal project tooling’s conflict and recovery contract.

For a legacy project without language_profiles, the skill checks only these repository-root paths and offers the matching suggestions for confirmation:

Root pathSuggested profile
pyproject.tomlPython
tsconfig.jsonTypeScript
package.jsonTypeScript
Cargo.tomlRust
go.modGo
mix.exsElixir
flake.nixNix

Suggestions are never applied automatically. If none are found or the user declines them, the skill offers other. Detection remains root-only; recursive discovery belongs to Monorepo tooling layout. A direct noninteractive update of a legacy project without explicit profile operations records other to preserve the universal Universal project tooling baseline.

Requirements

Functional Requirements

  • Both Copier entry points record the exact selection contract and render only selected profile content.
  • Setup collects explicit profiles; update preserves, adds, or removes them through the reviewed interface.
  • Each profile implements the exact tools, commands, globs, gates, ignores, and documentation in the normative table.
  • All valid polyglot combinations retain one shared tooling surface without duplicate destinations or keys.

Quality Requirements

  • Source checks skip cleanly without matching files, and package checks skip without their manifest inputs.
  • check is read-only; mutating tools are globally ordered; tests never run during fix or pre-commit.
  • Generated documentation states only behavior present in the selected render.

Compatibility and Migration Requirements

Pre-1.0 answer changes are allowed. Legacy projects receive confirmed root-only suggestions or retain the universal baseline through other; Copier conflicts execute no newly rendered code.

Manifest and Dependency Policy

No profile creates a manifest. Source-only format/lint steps run when matching files exist. Package-aware steps run only when their root manifest and relevant input files exist. Missing required project-owned pytest, Vitest, or Credo dependencies fail with a clear prerequisite message rather than being downloaded or written into a manifest.

Manifest-backed tests and expensive project checks run only under mise run check; they do not run in pre-commit or mise run fix. Source formatters and linters participate in the shared pre-commit/check/fix policy as applicable. mise run check stays read-only. For Go this means check uses go mod tidy -diff && go mod verify, while fix may run go mod tidy.

Existing Context

Universal project tooling owns the universal nine-tool baseline, stable five tasks, one mise/hk policy, four-platform lock, conflict gate, provisioner, and generated tooling pages. Language quality profiles extends those surfaces and preserves their recovery and trust boundaries.

Proposed Design

Use direct membership-gated Copier/Jinja/Pkl sections in the existing files. Keep common source checks separate from check-only manifest steps, render conditional docs/ignores from the same answer, and reuse the Universal project tooling provisioner.

Normative Profile Contract

All new mise entries use latest; the committed mise.lock still targets Universal project tooling’s four platforms. TypeScript reuses the universal node = "lts" entry rather than declaring Node again. Exact long identifiers may be used where mise has no stable shorthand. The nixfmt-rs release lacks a macOS x64 asset, so its mise entry is explicitly restricted with os = ["linux", "macos/arm64"]; every other profile tool resolves on all four targets.

ProfileAdded mise toolsSource-scoped check/fixRoot-manifest-gated checks
Pythonruff, tyRuff lint and format plus ty check on **/*.py, **/*.pyiWith pyproject.toml and matching tests/**/*.py, uv run pytest; pytest must be project-declared
TypeScriptaube, biomeBiome check/write on **/*.{ts,tsx,mts,cts}With package.json and matching **/*.{test,spec}.{ts,tsx,mts,cts}, aube exec vitest run; Vitest must be project-declared
Rustrustrustfmt --check / rustfmt on **/*.rs using edition 2024With Cargo.toml, cargo clippy --all-targets --all-features -- -D warnings and cargo test --all-targets --all-features
Gogo, gofumpt, go:golang.org/x/tools/cmd/goimports, golangci-lintgoimports then gofumpt check/write on **/*.goWith go.mod, read-only tidy diff plus verify, golangci-lint run, and go test ./...; fix may run go mod tidy
Elixirerlang, elixirmix format --check-formatted / mix format on **/*.{ex,exs}With mix.exs, warnings-as-errors compile, mix credo --strict, and tests when test/**/*.exs exists; Credo must be project-declared
Nixgithub:Mic92/nixfmt-rs, limited to Linux and macOS ARM64its nixfmt --check / nixfmt binary on **/*.nixWith flake.nix, nix flake check; system nix is the sole executable prerequisite not provisioned by mise

Exact hk Step Contract

{{ files }} is hk’s shell-escaped file list. Source steps run in check, fix, and pre-commit; check uses each check command, while fix/pre-commit use fix when present and then run read-only source checks. Check-only project steps never run in fix/pre-commit. Go module tidy is the sole fix-only manifest step and does not run in pre-commit.

StepCheck commandFix commandGate / hooks
ruffruff check --force-exclude {{ files }}ruff check --force-exclude --fix {{ files }}Python files; all three hooks
ruff-formatruff format --quiet --force-exclude --diff {{ files }}ruff format --quiet --force-exclude {{ files }}Python files; after ruff; all three hooks
tyty check {{ files }}nonePython files; after ruff-format; all three hooks
biomebiome check --no-errors-on-unmatched {{ files }}biome check --write --no-errors-on-unmatched {{ files }}TypeScript files; all three hooks
rustfmtrustfmt --check --edition 2024 {{ files }}rustfmt --edition 2024 {{ files }}Rust files; all three hooks
goimportsoutput=$(goimports -l {{ files }}) && test -z "$output"goimports -w {{ files }}Go files; all three hooks
gofumptoutput=$(gofumpt -l {{ files }}) && test -z "$output"gofumpt -w {{ files }}Go files; after goimports; all three hooks
mix-formatmix format --check-formatted {{ files }}mix format {{ files }}Elixir files; all three hooks
nixfmtnixfmt --check {{ files }}nixfmt {{ files }}Nix files; supported platforms; all three hooks
pytestprerequisite guard, then uv run pytestnoneroot pyproject.toml plus tests/**/*.py; check only
vitestprerequisite guard, then aube exec vitest runnoneroot package.json plus TS test/spec files; check only
cargo-clippycargo clippy --all-targets --all-features -- -D warningsnoneroot Cargo.toml; check only
cargo-testcargo test --all-targets --all-featuresnoneroot Cargo.toml; check only
go-modgo mod tidy -diff && go mod verifygo mod tidyroot go.mod; check and fix, never pre-commit
golangci-lintgolangci-lint runnoneroot go.mod; check only
go-testgo test ./...noneroot go.mod; check only
mix-compilemix compile --warnings-as-errorsnoneroot mix.exs; check only
credoprerequisite guard, then mix credo --strictnoneroot mix.exs; check only
mix-testmix test --warnings-as-errorsnoneroot mix.exs plus test/**/*.exs; check only
nix-flake-checknix flake checknoneroot flake.nix; check only

The pytest guard runs uv run python -c "import pytest"; the Vitest guard runs aube exec vitest --version; the Credo guard runs mix help credo. Each prints a profile-specific message requiring the missing project-owned dependency before exiting nonzero. Nix source commands first reject Darwin/x86_64 with the published unsupported-platform message; on other targets nixfmt is mise-provisioned. Missing system Nix for nix-flake-check produces the documented prerequisite message.

The global mutating order extends Universal project tooling’s serialized chain in canonical profile order. Read-only source linters depend on the final relevant formatter. Mixed selections must not duplicate keys, tools, task names, or destinations.

Generated Tasks and Documentation

Profiles add no top-level mise tasks. Contributors continue to use only:

check, fix, docs:check, docs:build, docs:serve

Conditional sections extend the existing generated pages:

  • skills/setup-project/template/docs/src/development/tooling.md.jinja explains selected check/fix behavior, manifest gates, project-owned test dependencies, and the Nix prerequisite.
  • skills/setup-project/template/docs/src/reference/tooling.md.jinja lists the recorded profiles, exact added tools, globs, commands, and ignore rules.

Both pages remain unconditionally linked by the existing generated docs/src/SUMMARY.md; no new reader page or navigation entry is added. With other, they remain the universal Universal project tooling pages and state that no recognized language profile is active. Mixed selections render additive sections in canonical order.

Ignore Ownership

Universal documentation, mise, environment, and operating-system ignores remain unconditional. Existing Python-only ignores move behind the Python profile. Selected profiles add only:

ProfileIgnore entries
Python.venv/, __pycache__/, *.py[cod], .pytest_cache/, .ruff_cache/
TypeScriptnode_modules/, coverage/
Rusttarget/
Gocoverage.out
Elixir_build/, deps/, cover/
Nix.direnv/, result, result-*
Othernone

Removing a profile removes its template-owned tools, steps, docs sections, and ignores on a conflict-free Copier update. Copier conflicts continue to skip provisioning and keep update readiness false.

Architecture Consistency

Existing Patterns Reused

Universal project tooling remains authoritative for one shared mise.toml, hk.pkl, provisioner, lock, hook installation, five tasks, and generated tooling pages. Language quality profiles uses direct membership-gated Jinja/Pkl sections; it adds no profile registry, generator, plugin system, or second provisioning path.

Invariants Preserved

Copier only renders. Setup/update decide when generated code executes. User-global mise tools remain isolated. Profile selection changes tooling only; lifecycle authority and documentation validation remain language-agnostic. Application manifests and dependencies stay project-owned.

New Decisions Introduced

The hk policy becomes a shared source-check map plus check-only manifest steps so tests never run during fix or pre-commit. The Nix profile’s system nix prerequisite is the single explicit exception to mise ownership. The mise-provisioned nixfmt-rs binary provides formatting without Nix on Linux x64/ARM64 and macOS ARM64. Nix profile checks are unsupported on macOS x64 and fail with an explicit platform message when matching Nix inputs exist.

Operational Considerations

Setup and conflict-free update resolve and install selected tools into the existing four-platform lock; mise omits nixfmt-rs only from the macOS x64 target. Tool or lock failure uses Universal project tooling’s structured degraded result and recovery. Adding/removing profiles can change mise.lock; no project script or manifest-backed check runs during setup/update. Aube auto-install behavior occurs only later when contributors run the manifest-gated Vitest check.

Documentation Impact

Documentation concernExact pageChangeOwner
Architecturedocs/src/architecture/index.mdRoot profile composition, shared/check-only maps, no-monorepo boundarycomposition; final matrix reconciliation
Usagedocs/src/operations/index.mdSetup selection, legacy suggestions, add/remove update flow, manifest gatesmatrix/docs task
Developmentdocs/src/development/index.mdExact profile checks, fixtures, and matrix validationmatrix/docs task
Referencedocs/src/reference/index.mdAnswer schema, profile/tool/command/ignore tablescomposition selection contract; final matrix reconciliation
Generated developmentskills/setup-project/template/docs/src/development/tooling.md.jinjaConditional contributor behaviorserialized profile tasks; final reconciliation by matrix/docs
Generated referenceskills/setup-project/template/docs/src/reference/tooling.md.jinjaConditional exact contractsserialized profile tasks; final reconciliation by matrix/docs
Navigationdocs/src/SUMMARY.md and skills/setup-project/template/docs/src/SUMMARY.md.jinjaNo change; existing tooling pages remain linkedmatrix assertion only
Implemented featuredocs/src/features/language-quality-profiles/index.mdCreate during close-outlifecycle close-out

Validation Strategy

Structural validation covers 65 cases: the 63 nonempty subsets of the six recognized profiles, the exclusive other selection, and one empty-list rejection. The 64 valid selections render through both Copier entry points. Tests check canonical answers, selected-only tools/steps/docs/ignores, stable tasks, no duplicate destinations, TOML/Pkl validity, generated docs/navigation, and other retaining the universal baseline.

Focused fixtures exercise source check/fix and manifest gates for each profile. Deterministic shims verify exact manifest-backed commands, missing project-owned dependency errors, no-file/no-manifest skips, read-only check behavior, global formatter ordering, and setup/update add/remove/conflict/relock behavior. A bounded marked external contract resolves the combined four-platform lock, verifies nixfmt-rs is absent only for macOS x64, and executes representative source-only tools on supported hosts. System Nix and project-owned ecosystem dependencies are classified separately rather than silently downloaded.

Implementation uses these literal validation commands:

# composition
uv run pytest -q tests/test_repository.py \
  -k "language_profile_schema or language_profile_selection or language_profile_update or language_profile_matrix"
# Python/TypeScript
uv run pytest -q tests/test_repository.py -k "python_profile or typescript_profile"
# Rust/Go
uv run pytest -q tests/test_repository.py -k "rust_profile or go_profile"
# Elixir/Nix
uv run pytest -q tests/test_repository.py -k "elixir_profile or nix_profile"
# final focused and external contracts
uv run pytest -q tests/test_repository.py -k "language_profile"
uv run pytest -q tests/test_repository.py::test_generated_language_profiles_end_to_end
# final repository and documentation validation
uv run --frozen --group test pytest
mise run check
uv run --no-project python scripts/check-docs.py
mdbook build docs

During iteration each task runs only its focused selector. The final task runs the focused and marked external contracts, then the full repository suite and repository/documentation checks after review fixes stabilize.

Dependencies and Parallelism

Language quality profiles depends on delivered Universal project tooling. Implementation is intentionally serialized because every profile extends the same mise/hk/generated-documentation files. Each child directly depends on specification reconciliation and its predecessor; no implementation child can become ready from hierarchy alone.

Implementation Decomposition

  1. Composition and workflow selection: Copier schema, setup/update UX and helpers, root-only legacy suggestions, conditional shared surfaces, ignores, architecture/reference contract, and exhaustive structural matrix.
  2. Python and TypeScript profiles, fixtures, and their generated documentation sections.
  3. Rust and Go profiles, fixtures, and their generated documentation sections.
  4. Elixir and Nix profiles, fixtures, Nix prerequisite, and their generated documentation sections.
  5. Cross-profile matrix, setup/update integration, external contract, and root/generated documentation reconciliation.

The tasks are serialized because they intentionally modify the same mise/hk/generated-documentation surfaces. Every implementation child depends directly on specification reconciliation as well as its preceding implementation child.

Rollout and Migration

New setup always obtains an explicit selection. Legacy update offers root-manifest suggestions and requires confirmation. Explicit add/remove operations preserve application-owned files and use Copier’s normal three-way reconciliation. Language quality profiles does not recursively discover packages or initialize language projects.

Risks and Tradeoffs

The exhaustive render matrix is cheap but live tool installation is not; structural coverage is exhaustive while the external execution set is bounded. Fuzzy profile versions reduce template maintenance and are made deterministic per project by mise.lock. Project-owned pytest, Vitest, and Credo can vary by project, so dstack validates invocation and prerequisite behavior rather than controlling their versions.

Rejected Alternatives

  • Stub manifests or native project initialization: violates the workflow-scaffold boundary and would invent package identity/layout decisions.
  • Manifest-defined tooling only: too inconsistent for an opinionated generated quality baseline.
  • Ephemeral pytest/Vitest/Credo downloads: bypass project dependency authority.
  • Whole-list update replacement: poor additive-migration UX; explicit add/remove is clearer.
  • Recursive manifest discovery: package-root semantics belong to Monorepo tooling layout.
  • nixfmt-tree: requires Nix/treefmt integration for source formatting; nixfmt-rs is standalone on its three published platform targets. The user explicitly accepted no Nix-profile support on macOS x64 rather than adding Rust solely to compile the formatter.
  • Parallel profile tasks or generated fragment systems: shared files make parallel writes unsafe and direct conditionals are sufficient.
  • JavaScript profile, framework starters, or one complete template per language: outside scope or duplicative.

Open Questions

None.

Deferred Decisions

Additional languages and package-local/monorepo profile configuration require demonstrated consumers and complete mise, hk, and validation contracts.

Planning Record

Questions Asked and Answers

The user selected Python, TypeScript, Rust, Go, Elixir, Nix, and other; TypeScript uses Biome and Aube-run Vitest; Python uses Ruff, ty, and uv-run pytest; Go adds gofumpt, goimports, module hygiene, golangci-lint, and tests; Elixir adds strict Credo; Nix uses nixfmt-rs plus flake checks and intentionally excludes macOS x64. Manifests remain project-owned, package-aware checks are manifest gated, and pytest/Vitest/Credo versions are project-owned. Legacy discovery is root-only and confirmed by the user.

Assumptions

Multiple profiles apply one root policy to a polyglot repository; they do not imply package-local execution or monorepo support.

Design Changes During Review

Review replaced undefined native conventions with the normative table, made setup/update selection explicit, moved Python ignores behind its profile, serialized shared-file work, separated check-only tests from pre-commit/fix, added exact generated documentation destinations, made structural validation exhaustive, and split native implementation.

Source Material

Aube official documentation; mise registry identifiers; hk 1.49 built-ins; nixfmt-rs official repository; Universal project tooling’s delivered generated-tooling contract.

Design — GitHub validation and docs deployment

Metadata

  • Beads feature root: dstack-mol-8fe
  • Feature slug: github-validation-and-docs-deployment
  • Design path: docs/src/features/github-validation-and-docs-deployment/design.md
  • Implemented record: docs/src/features/github-validation-and-docs-deployment/index.md
  • Base branch: main
  • Status: reviewed

Feature Summary

Generate GitHub Actions validation that reuses the locked mise/hk interface and a committed GitHub Pages workflow that stays disabled until an explicit gh-backed operator task enables repository state.

User Intent

Every generated GitHub project should have local/CI parity and an easy path to documentation deployment without failing before Pages is configured.

Goals

  • Always generate validation that installs the committed mise lock and runs the same named check task used locally.
  • Commit a Pages workflow whose build and deploy jobs are disabled by default.
  • Provide mise run docs:deployment:enable to verify GitHub context/authentication, select workflow-based Pages builds, and set the enable variable last.
  • Report the Pages URL or actionable recovery without rewriting generated source.

Non-Goals

  • Support non-GitHub CI or documentation hosting.
  • Automatically create, publish, or choose a GitHub repository.
  • Enable Pages without explicit operator invocation.
  • Install or lock the GitHub CLI as a universal project tool.
  • Deploy documentation from pull requests or non-default branches.

User-Facing Behavior

Validation runs on every pull request and push. The pinned jdx/mise-action installs the committed mise lock with its cache enabled, then CI runs only mise run check; hk remains the single validation policy and already validates/builds documentation.

.github/workflows/docs.yml runs only for pushes to the rendered repository_default_branch and explicit workflow_dispatch. Both build and deploy jobs require vars.DOCS_DEPLOYMENT_ENABLED == 'true', so an absent variable is false and no artifact or deployment occurs. The workflow builds with mise run docs:build, uploads docs/book, and deploys to the github-pages environment.

mise run docs:deployment:enable treats gh as an external administrative prerequisite. It verifies the executable, gh auth status, and repository context; creates or updates Pages to build_type=workflow; sets DOCS_DEPLOYMENT_ENABLED=true only after Pages configuration succeeds; then prints the Pages URL. Repeated calls are idempotent. Local tasks remain usable without gh or a GitHub remote.

Requirements

Functional Requirements

Validation workflow

Generate .github/workflows/validate.yml with:

  • triggers push and pull_request, without write permissions;
  • job-level contents: read;
  • checkout with persisted credentials disabled;
  • a pinned jdx/mise-action installs the committed mise lock using its cache;
  • mise run check as the sole validation command.

CI never runs mise lock, duplicates hk policy, or separately invokes mdBook.

Pages workflow

Generate .github/workflows/docs.yml with:

  • push.branches: [repository_default_branch] rendered from Copier answers plus workflow_dispatch;
  • no pull_request trigger and no path filter;
  • concurrency group pages with cancel-in-progress: false;
  • build job condition vars.DOCS_DEPLOYMENT_ENABLED == 'true', contents: read, locked mise installation with the mise action cache enabled, mise run docs:build, Pages configuration, and upload of docs/book;
  • deploy job depending on build, carrying the same gate, only pages: write and id-token: write, and environment.name: github-pages with its URL from the deploy action output.

Fork pull requests therefore receive neither Pages permissions nor a deployment path.

Enable task

Add the sixth generated mise task, docs:deployment:enable, backed by a generated stdlib helper. The helper performs, in order:

  1. find gh, otherwise print installation guidance and the manual commands below;
  2. run gh auth status;
  3. resolve OWNER/REPO with gh repo view --json nameWithOwner --jq .nameWithOwner;
  4. query GET /repos/{owner}/{repo}/pages;
  5. on HTTP 404, create Pages with POST /repos/{owner}/{repo}/pages -f build_type=workflow; otherwise update it with PUT /repos/{owner}/{repo}/pages -f build_type=workflow; any other GET/API failure stops;
  6. set DOCS_DEPLOYMENT_ENABLED=true with gh variable set only after Pages configuration succeeds;
  7. query Pages again and print .html_url.

A Pages change followed by variable failure remains safe because deployment stays disabled. Repetition converges on the same Pages build type and variable. The helper returns nonzero and never claims success on authentication, repository, API, or variable failures.

Manual fallback is:

gh api --method PUT repos/OWNER/REPO/pages -f build_type=workflow
gh variable set DOCS_DEPLOYMENT_ENABLED --body true --repo OWNER/REPO

For a repository without an existing Pages site, use POST instead of PUT for the first command.

Action Pin Contract

Generated workflows pin actions to these full commits, with comments naming their major tags:

ActionMajorCommit
actions/checkoutv7.0.13d3c42e5aac5ba805825da76410c181273ba90b1
jdx/mise-actionv4.2.47e36c90d9ab29c415a2384db3006f3ec8a8cc654
actions/configure-pagesv6.0.045bfe0192ca1faeb007ade9deae92b16b8254a0d
actions/upload-pages-artifactv5.0.0fc324d3547104276b827a68afc52ff2a11cc49c9
actions/deploy-pagesv5.0.0cd2ce8fcbc39b97be8ca5fce6e763baed58fa128

Quality Requirements

  • Actionlint and zizmor validate both rendered workflows.
  • Static tests assert exact triggers, branch, gates, permissions, environment, artifact path, action pins, and commands.
  • Pull requests from forks cannot obtain deployment permissions.
  • The enable helper passes deterministic mocked success, repeat, missing-gh, auth, missing-remote, 404-create, non-404 API, variable, and final-query cases.
  • Both Copier entry points and conflict-free updates render/preserve the workflows, sixth task, helper, and docs.

Compatibility and Migration Requirements

Existing managed projects receive workflows, task, helper, and docs through Copier update. Repository variables and Pages settings remain GitHub-owned state and are never reset by Copier. Conflicts continue to block generated-code execution. Projects without GitHub or gh retain the existing local tasks and receive clear enablement guidance.

Existing Context

Purposeful project scaffold provides factual docs to publish. Universal project tooling provides one locked mise/hk interface and five stable contributor tasks. Language quality profiles composes language profiles without adding CI. Root repository workflows demonstrate pinned Actions, read-only validation, and cached locked mise installation, but generated workflows remain separately specified product behavior.

Proposed Design

Add two unconditional workflow templates, one generated stdlib enable helper, one mise operator task, one generated operations page, and updates to existing generated tooling/reference pages. Validation consumes the five stable Universal project tooling tasks without adding policy. GitHub validation and docs deployment intentionally extends the shared mise interface from five to six tasks while retaining nine universal tools because gh is external.

Architecture Consistency

Existing Patterns Reused

  • Universal project tooling locked installation and named tasks remain the CI authority.
  • Copier only renders files; it does not mutate GitHub repository state.
  • The explicit operator task owns the authenticated GitHub mutation.
  • Validation and deployment remain separate workflows with separate permissions.

Invariants Preserved

  • CI does not regenerate locks or define a second validation policy.
  • Missing credentials, remotes, Pages state, or external gh never break local development.
  • Deployment permission exists only in the gated deployment job.
  • GitHub state is changed only by explicit user invocation.

New Decisions Introduced

  • GitHub Actions is the generated CI provider.
  • Feature designs and generated operations documentation remain published mdBook chapters.
  • The generated task set becomes six; the universal tool set remains nine.
  • DOCS_DEPLOYMENT_ENABLED and Pages build_type=workflow jointly gate delivery.

Architecture Documentation Changes

Document CI parity, GitHub-state ownership, deployment permissions, gating, and the external-gh trust boundary in docs/src/architecture/index.md.

Operational Considerations

Enablement requires an authenticated gh identity with repository administration permission. The helper reports the failed operation and manual fallback. The credentialed disposable-repository exercise belongs to lifecycle validation, not an implementation child; if unavailable, validation records it as unavailable and remains blocked unless explicitly waived.

Documentation Impact

Documentation concernExact pageOwnerPlanned change
Root architecturedocs/src/architecture/index.mddeployment taskCI/deployment/GitHub-state trust boundaries
Root usagedocs/src/operations/index.mdenable taskEnablement, recovery, manual fallback
Root developmentdocs/src/development/index.mdvalidation taskExact local/CI parity
Root referencedocs/src/reference/index.mdenable taskWorkflows, task, variable, permissions, helper result
Generated developmentskills/setup-project/template/docs/src/development/tooling.md.jinjavalidation taskCI parity and workflow paths
Generated operationsskills/setup-project/template/docs/src/operations/github-pages.md.jinjaenable taskEnablement, recovery, fallback, URL
Generated referenceskills/setup-project/template/docs/src/reference/tooling.md.jinjaenable taskSixth task, variable, workflow/permission contract, external gh
Generated navigationskills/setup-project/template/docs/src/SUMMARY.md.jinjaenable taskRegister GitHub Pages operations page
Roadmapdocs/src/planned-features.mdintegration taskMark implementation readiness
Implemented recorddocs/src/features/github-validation-and-docs-deployment/index.mdlifecycle close-outDelivery evidence

Every page has one implementation commit owner. No new root reader page is needed.

Validation Strategy

Structural and simulated validation

  • Render representative project kinds/profiles through both Copier entry points.
  • Parse workflows as YAML; run actionlint and zizmor on rendered workflows.
  • Assert exact pins, events, rendered default branch, job gates, permissions, environment, artifact path, locked install, and named tasks.
  • Assert tool count stays nine and task set becomes the existing five plus docs:deployment:enable.
  • Run mocked helper cases without network credentials.
  • Exercise conflict-free Copier update and verify project-owned workflow edits follow normal Copier conflict handling while repository variables remain out of template state.
  • Run generated docs checker and mdBook with the operations page registered.

Bounded external validation

In lifecycle validation, use a disposable GitHub repository to run the enable task twice, verify Pages build_type=workflow, verify the variable, and capture the Pages URL. Do not perform this mutation from an implementation agent or without explicit credentials/repository authority.

Repository-wide validation remains uv run --frozen --group test pytest, mise run check, docs checker, and mdBook.

Implementation Decomposition

  1. Validation workflow (dstack-mol-41q.1): generate .github/workflows/validate.yml; own root/generated development docs, focused tests in tests/test_github_validation.py, and shared exact-scaffold assertions caused by this file.
  2. Deployment workflow (dstack-mol-41q.2): after task 1, generate .github/workflows/docs.yml; own root architecture docs, focused tests in tests/test_github_deployment.py, and its shared exact-scaffold assertion delta.
  3. Enablement (dstack-mol-41q.3): after task 2, add helper and sixth task; own root operations/reference, generated operations/reference/navigation, focused tests in tests/test_github_enablement.py, and shared task/file assertions.
  4. Integration (dstack-mol-41q.4): after the other three, own remaining combined/update coverage in tests/test_repository.py, both-entrypoint integration, workflows/tasks/docs, and roadmap reconciliation.

Each task directly depends on specification reconciliation. Tasks 1–3 are serialized because every generated file/task changes shared exact-scaffold assertions that must pass at each task commit; task 4 is the final integration gate.

Dependencies and Parallelism

Purposeful project scaffold and Universal project tooling are delivered prerequisites. Language quality profiles is delivered context. After specification reconciliation, implementation proceeds validation → deployment → enablement → integration.

Rollout and Migration

Deployment remains disabled after setup/update unless the existing repository variable is exactly true. Adding or updating generated files never invokes gh, changes Pages, or changes repository variables.

Risks and Tradeoffs

  • GitHub API or permission changes can break enablement; narrow calls and exact failure reporting limit ambiguity.
  • gh is external, so enablement may require installation; this avoids four-platform lock/install cost for a one-time administration task.
  • Workflow pins age; explicit full SHAs and comments allow audited updates.

Rejected Alternatives

  • Mise-managed gh: recurring four-platform lock/install cost for an occasional administrative task.
  • Disabled filename: GitHub cannot discover it as a workflow.
  • Workflow dispatch only: no automatic post-enable deployment.
  • Source rewriting: dirty state and Copier conflicts.
  • Deployment enabled by default: failures before Pages configuration.
  • Variable first, Pages API second: could enable deployment before Pages is safely configured.

Open Questions

None.

Deferred Decisions

Other CI providers and documentation hosts remain consumer-driven future work.

Planning Record

Questions Asked and Answers

The user required validation, a disabled deployment workflow, and gh automation. They approved a repository-variable gate and API-based Pages configuration. During specification review, the user chose external gh with preflight and installation guidance rather than an eighth universally locked mise tool.

Assumptions

Generated projects target GitHub even when the remote is added after setup. repository_default_branch is the only automatic deployment branch. Explicit manual dispatch is useful for recovery but remains gated.

Design Changes During Planning

  • Deployment changed from optional generation to always-generated but disabled behavior.
  • CI parity was narrowed to locked installation plus mise run check, avoiding duplicate mdBook work.
  • Deployment trigger, permissions, environment, and artifact path became explicit.
  • gh changed from proposed universal mise tooling to an external administrative prerequisite.
  • Generated operations/development/reference documentation received exact ownership.
  • Tasks 1–3 were initially separated, then serialized when implementation preflight confirmed each changes shared exact-scaffold assertions; task 4 remains the integration gate.

Source Material

Design — hk policy simplification

Metadata

  • Beads feature root: dstack-mol-5v0
  • Feature slug: hk-policy-simplification
  • Design path: docs/src/features/hk-policy-simplification/design.md
  • Implemented record: docs/src/features/hk-policy-simplification/index.md
  • Base branch: main
  • Status: reviewed

Feature Summary

Replace the generated and repository hk policies’ unnecessary command overrides and broad dependency chain with hk built-ins, native config discovery, and file-level locking while restoring observable Harper commit-message linting.

User Intent

The user expects dstack to add a small quality baseline without fighting hk’s native behavior. Existing checks must not silently disappear, depends must be exceptional rather than the default, built-ins should own standard tools, and commit-message grammar checks must have executable proof.

Goals

  • Use Builtins.harper_commit_message without the current rule-disabling command override.
  • Prefer hk built-ins and each tool’s standard config discovery where behavior matches the contract.
  • Remove dependency edges used only to serialize overlapping files; rely on hk read/write locks.
  • Retain custom steps only for project-specific behavior and document why each remains custom.
  • Preserve every supported validation capability across root and generated policies.
  • Prove check, fix, pre-commit, and commit-msg behavior through representative generated projects.

Non-Goals

  • Replace hk, change its pinned binary/Pkl version, or redesign mise provisioning.
  • Remove project-specific semantic documentation checks or manifest-gated language tests merely to reduce line count.
  • Introduce a general step registry, Pkl generator, or second hook runner.
  • Change language-profile selection, task names, application manifests, or GitHub workflow behavior.

User-Facing Behavior

Generated projects retain the same six mise tasks and hooks. Checks and deterministic fixes run with greater native parallelism. Harper rejects representative spelling, repetition, and agreement defects while accepting valid Conventional Commit subjects and optional canonical Beads footers. Documentation lists the actual checks without claiming artificial ordering.

Requirements

Functional Requirements

Native commit-message linting

Both root and generated hk.pkl derive harper_commit_message from Builtins.harper_commit_message. Direct use is not compatible with the existing commit contract: Harper 2.6 rejects a valid canonical Beads: dstack-mol-v8c.1 footer as spelling and split-word errors. The sole command override filters Git comments, scissors/diff content, a canonical machine-authored release: vX.Y.Z subject only when it is the first line and exact stable release form, and a canonical Beads: footer before piping the remaining human-authored text to harper-cli lint --quiet --no-color. It does not ignore any Harper rule class. Tests invoke the Harper step in isolation and the complete real commit-msg hook with:

  • a valid scoped Conventional Commit subject;
  • a valid subject plus final Beads: footer;
  • a canonical release: vX.Y.Z subject;
  • the same release-shaped text in a human-authored body, which must still be linted;
  • repeated words;
  • a representative spelling error;
  • pronoun/verb disagreement.

The three valid messages pass and each invalid fixture fails in the isolated Harper step. Separate fixtures prove Cocogitto, subject/body length, required scope, and Beads footer checks independently reject their own invalid inputs.

Built-in and config-discovery policy

For every current custom step, implementation records one disposition:

  1. use the hk built-in unchanged;
  2. use the built-in with the smallest necessary project-specific field override; or
  3. retain a custom step because no built-in represents required behavior.

Rumdl uses normal .config/rumdl.toml discovery rather than an explicit default config argument. Equivalent redundant flags are removed. The semantic documentation validator, commit footer rules, manifest prerequisite guards, and the minimal Harper machine-line filter remain custom because they represent dstack-specific behavior not covered by the upstream built-ins.

Dependency policy

Remove the global dependency chain that serializes unrelated steps. hk’s file-level read/write locking owns ordinary overlap between checks and fixers. A remaining depends edge is allowed only when one step consumes another step’s output or the final content is order-sensitive; its rationale must appear in design/reference documentation and a test. No dependency may exist solely to force a stable display order or avoid a race hk already prevents.

Capability preservation

Capture the intended root and generated step inventories before refactoring. The final policies must retain all supported universal, profile, manifest, commit-message, and repository-specific checks. Renaming a step requires an explicit mapping in tests; deleting a capability requires separate user approval.

Quality Requirements

  • Root and rendered Pkl evaluate successfully.
  • hk check, hk fix, pre-commit, and commit-msg fixtures are deterministic.
  • Fix followed by check converges without unstaged-work loss.
  • Representative single-profile, polyglot, and other projects retain selected-only behavior.
  • Tests assert behavior and capability sets rather than the removed dependency implementation.

Compatibility and Migration Requirements

Existing Copier-managed projects receive the simpler policy through normal three-way update. Project-owned hk customizations remain subject to Copier conflict handling and the additive protections owned by Migration safety and clarity. Task names, tool answers, and lock platforms do not change.

Existing Context

Universal project tooling introduced one generated hk.pkl; Language quality profiles extended it with conditional steps. A later race fix serialized nearly every step with depends, despite hk 1.49 coordinating overlapping fixers through file-level read/write locks. Rumdl and Harper were replaced with custom commands, including a Harper ignore list that disables major rule classes. Current tests assert the dependency chain and command strings rather than the desired native behavior.

Proposed Design

Keep one direct Pkl mapping shared by check, fix, and pre-commit. Replace standard custom steps with built-ins, remove non-semantic dependencies, and let hk lock matching files. Keep small custom definitions only for dstack-specific semantic checks, manifest gates, or tools without a suitable built-in. Test the public hook behavior directly.

Architecture Consistency

Existing Patterns Reused

The feature keeps the single mise/hk interface, version-coupled hk pin, profile-gated template sections, root-manifest gates, and generated tooling documentation.

Invariants Preserved

check remains read-only; fix and pre-commit remain deterministic; pre-commit retains stash = "git"; tests do not run during pre-commit/fix except the existing explicit Go tidy behavior; generated projects keep six task names.

New Decisions Introduced

hk native locking is authoritative for ordinary fixer coordination. Custom step definitions and dependency edges now require a concrete behavioral justification.

Architecture Documentation Changes

docs/src/architecture/index.md will describe native locking and the narrow custom-step boundary.

Operational Considerations

The simplified graph may expose latent non-convergent tool combinations previously hidden by a fixed chain. The final matrix therefore runs fix then check and reports any genuine order-sensitive exception. Harper failures must name the lint so contributors can correct the message rather than bypass the hook.

Documentation Impact

Documentation concernExact pageCreate or updatePlanned changeOwning Beads task
Architecturedocs/src/architecture/index.mdUpdateNative lock and customization boundarydstack-mol-v8c.2
Usage / OperationsNot applicableContributor behavior is development/reference material
Developmentdocs/src/development/index.mdUpdate incrementallyHarper behavior (.1), native policy (.2), validation matrix (.3)tasks .1.3
Referencedocs/src/reference/index.mdUpdate incrementallyHarper contract (.1), exact custom steps/dependency exceptions (.2)tasks .1.2
Generated Developmentskills/setup-project/template/docs/src/development/tooling.md.jinjaUpdate incrementallyHarper behavior (.1) and native check/fix behavior (.2)tasks .1.2
Generated Referenceskills/setup-project/template/docs/src/reference/tooling.md.jinjaUpdate incrementallyHarper contract (.1) and actual steps/justified ordering (.2)tasks .1.2
Published Developmentdocs/src/development/tooling.mdUpdate incrementallyKeep dog-food contributor contract aligned with template changestasks .1.2
Published Referencedocs/src/reference/tooling.mdUpdate incrementallyKeep dog-food exact contract aligned with template changestasks .1.2
Planned navigationdocs/src/SUMMARY.mdAlready updatedDesign is registered under planned featuresplanning
Delivered navigationdocs/src/SUMMARY.md; docs/src/features/index.mdUpdate during close-outRegister the implemented feature in both delivered indexeslifecycle close-out
Implemented Feature Recorddocs/src/features/hk-policy-simplification/index.mdCreate during close-outPreserve delivery and audit historylifecycle close-out

Validation Strategy

  • Evaluate root and representative rendered Pkl.
  • Invoke the isolated Harper step and complete commit-msg hook with valid and invalid fixtures, attributing each failure to the intended validator.
  • Compare pre/post capability inventories.
  • Exercise check/fix/pre-commit convergence with overlapping Markdown and language files, verifying byte-for-byte restoration of unrelated unstaged content.
  • Give every retained dependency a focused output/order-sensitivity fixture.
  • Render both Copier entrypoints for other, representative single profiles, and one polyglot profile.
  • Run focused tests while iterating, then the full repository suite, mise run check, documentation checker, and mdBook build after review fixes stabilize.

Implementation Decomposition

  1. dstack-mol-v8c.1: restore native Harper behavior, direct hook fixtures, and Harper-specific root/generated docs.
  2. dstack-mol-v8c.2: replace redundant custom steps, remove non-semantic dependencies, test each retained edge, and update native-policy root/generated docs.
  3. dstack-mol-v8c.3: validate representative generated policies, fix→check convergence, unstaged restoration, and final matrix evidence without re-owning the product-contract pages.

Dependencies and Parallelism

This feature builds on delivered Language quality profiles. Tasks are serialized because the first two intentionally modify the same root/template hk files and the final task validates their combined result. Every task depends directly on specification reconciliation. Migration safety and clarity and Monorepo tooling layout depend on this feature.

Rollout and Migration

Ship through the normal Copier update path. Existing projects reconcile local hk changes through three-way merge; the migration feature separately prevents additive-adoption loss. No answer or lock schema migration is required.

Risks and Tradeoffs

Removing artificial order can reveal a genuinely order-sensitive pair. Such a pair receives the smallest tested exception rather than rebuilding the global chain. Native built-ins may change when hk is upgraded, but the synchronized hk/Pkl pin bounds that behavior.

Rejected Alternatives

  • Keep the chain because it currently passes: rejected because it defeats hk’s locking and obscures real dependencies.
  • Remove all custom steps categorically: rejected because semantic docs checks and manifest guards are project-specific.
  • Preserve the Harper ignore list: rejected because it disables expected lint categories and has no acceptance proof.
  • Introduce generated Pkl fragments: rejected as unnecessary for the current direct conditional template.

Open Questions

None.

Deferred Decisions

A future hk version upgrade is separate maintenance and must rerun these behavioral fixtures.

Planning Record

Questions Asked and Answers

The user explicitly required native Harper linting, removal of unnecessary depends, use of standard config discovery, and preservation rather than deletion of useful checks.

Assumptions

hk 1.49’s documented file-level locking remains the behavior of the currently pinned binary and Pkl package.

Design Changes During Planning

The work was separated from migration safety so the template policy can stabilize before migration preservation tests consume it. Specification review added published dog-food pages and delivered-index ownership, made task documentation ownership explicitly incremental, strengthened convergence/dependency acceptance, and replaced direct Harper use with a minimal machine-line filter after Harper 2.6 rejected valid canonical release and Beads metadata.

Source Material

Current root/generated hk policies and tests; hk 1.49 configuration, hook, built-in Rumdl, and Harper sources; the user’s migration and hook observations.

Design — Migration safety and clarity

Metadata

  • Beads feature root: dstack-mol-tki
  • Feature slug: migration-safety-and-clarity
  • Design path: docs/src/features/migration-safety-and-clarity/design.md
  • Implemented record: docs/src/features/migration-safety-and-clarity/index.md
  • Base branch: main
  • Status: reviewed

Feature Summary

Make /migrate-workflow preserve existing hk behavior by default, clearly explain every requested decision, classify migration artifacts, and require verified checkpoint commits.

User Intent

Migration should add dstack workflow capability without deleting working project checks. Questions must provide enough context and examples for informed answers. Archived legacy tasks should have an explicit lifecycle. Agents must never hide migration failures with git commit --no-verify.

Goals

  • Preserve every existing hk step unless the user explicitly approves and records its removal.
  • Detect step collisions and pre/post capability loss before migration completion.
  • Clearly distinguish durable committed archives, temporary candidates, and conditional backups.
  • Give each migration question purpose, evidence, impact, examples, choices, safe default, and deferral consequence.
  • Prohibit broad hook bypasses and stop with actionable recovery when a hook fails.
  • Import large Beads histories with visible progress, bounded transactions, and resume work proportional to what remains.
  • Preserve legacy task status and import audit metadata across scans and retries.
  • Require or reliably discover canonical project identity and default branch instead of using a migration worktree name.
  • Automate migration-safe validation and delivered-feature navigation without silently weakening final policy.
  • Exercise these guarantees through one integration contract that composes bounded resumable fixtures without duplicating expensive 300-record imports and provisioner setup in a single repository.

Non-Goals

  • Parse or rewrite arbitrary Pkl syntax automatically.
  • Guarantee semantic equivalence for an hk config that cannot be evaluated in its original repository.
  • Delete historical task archives by default.
  • Infer project purpose, users, scope, boundaries, classifications, or collision resolutions.
  • Weaken repository hooks or documentation policy to make intermediate migration checkpoints pass.
  • Automatically accept generated delivered-feature records without human semantic review.

User-Facing Behavior

Before adoption changes hk, migration records the existing hook and step inventory and a non-destructive readiness result when evaluable. Generated hk is an additive candidate. Existing keys remain authoritative until the user resolves a collision with an explanation of both behaviors. Verification rejects unapproved step loss.

migration/legacy-tasks/*.md is reported as durable audit evidence that must be tracked and committed by default. Candidate directories are temporary and must be removed. Every prompt explains why it is being asked, shows a concrete answer, and states what happens when the user defers.

Migration uses ordinary verified commits. A hook failure stops the checkpoint and reports the failing hook, the relevant migration-safe validation command, and recovery. It never uses or recommends --no-verify.

Dry-run and apply are separate, unmistakable operations. Apply announces its start, reports existing, recovered, pending, conflicting, completed, and remaining records per feature, and resumes incomplete features without replaying completed work. Checkbox task states remain authoritative when no explicit status is present. Rescans preserve import-level audit metadata.

Adoption obtains an explicit canonical project name, slug, and default branch when repository evidence is ambiguous. It never derives identity from a migration worktree suffix. Migration mode automatically narrows only known transitional validation conflicts and finalization restores strict checks. Implemented-feature navigation is regenerated from delivered records; a helper may draft historical records, but a human must review their semantics.

Requirements

Functional Requirements

Additive hk reconciliation

Before template adoption, record the evaluable hook/step inventory by hook name and step key. After candidate reconciliation, compare the final inventory. Existing steps must remain unless a durable migration decision records:

  • the removed or replaced key;
  • existing and candidate behavior;
  • the user’s explicit disposition;
  • the reason removal or replacement is safe.

A same-key collision is not silently resolved in favor of dstack. The workflow presents both definitions and asks one contextual question. If the original config cannot be evaluated, migration reports that limitation and requires manual inventory confirmation; it does not assume the generated policy supersedes it.

The adoption helper may continue staging hk.pkl as a candidate rather than implementing a general Pkl merge. The migration workflow and verifier own the preservation guard. An unchanged repeated scan preserves the prior timestamp and committed report bytes; volatile generation time changes only when semantic scan state changes.

Artifact lifecycle

Migration reports classify paths as:

ClassExamplesCompletion contract
Durable audit statemigration/workflow-migration.json, report, baseline, migration/legacy-tasks/*.mdTracked and committed
Temporary reconciliationmigration/template-adoption-candidates/Removed before checkpoint
Conditional backup evidencemigration/template-adoption-backup/Retained or removed according to an explicit recorded disposition

Default finalization archives legacy tasks.md into migration/legacy-tasks/<slug>.md. --delete-tasks remains an explicit alternative when Git history is accepted as sufficient. The manifest records backup disposition as unresolved, retain, or remove, defaulting older manifests to unresolved; verification rejects a present backup or recorded removal without a resolved disposition. Verification also rejects untracked durable migration artifacts and leftover temporary candidates.

Contextual question contract

Each migration question contains:

  1. a concise decision title;
  2. why migration needs the answer now;
  3. current authoritative evidence and uncertainty;
  4. the behavior or files the answer controls;
  5. one valid concrete example;
  6. available choices and a safe default when one exists;
  7. the consequence of deferring.

This contract applies to structured brief fields, project kind, feature classification, missing design intent, dependency direction/type, hk collisions/removals, candidate file reconciliation, archive deletion, and other explicit policy choices. Questions remain one at a time. The skill and reference own one reusable checklist and representative examples rather than a new prompt-rendering framework. Durable state stores only answers needed for safety or resumability, not copies of conversational prose.

Scalable, resumable Beads import

Checkbox states map [ ] to open, [-] to in progress, and [x] to closed unless a nonempty explicit status overrides them. Import groups mutations into bounded transactions where the Beads interface supports it and avoids one full repository transaction per field or relationship. A retry examines recorded identities first and performs mutation only for incomplete or conflicting records.

Dry-run never starts apply. Apply prints an unmistakable start notice and continuously reports per-feature and aggregate counts for existing, recovered, pending, conflicting, completed, and remaining records. Root creation, state closure, and dependency reconciliation are independently resumable phases. A roadmap-only planned or deferred feature without a design completes after its root state and relationships are durable; planned roots retain a note requiring /plan-features before activation. Rescans retain global import timestamps, completion state, imported identities, and phase progress. The generated manifest uses sorted compact JSON while the Markdown report remains human-readable, so large resumable histories retain deterministic evidence without requiring a large-file hook exception. Performance acceptance uses a large fixture representative of at least 300 Beads records and proves retries perform work proportional to the remaining records rather than the total history.

Canonical repository identity and adoption

The structured brief records project_name, project_slug, and default_branch. Repository evidence may propose values: the primary Git worktree/repository basename for identity and refs/remotes/origin/HEAD or existing policy for the branch. A migration worktree suffix is never accepted as canonical identity without confirmation. Missing or conflicting evidence triggers the contextual question contract before adoption.

Native non-stealth Beads initialization runs from the primary checkout on the migration branch. It owns collaborative control creation, the initial commit, embedded Dolt placement, Git-origin synchronization, and shared-worktree discovery. Migration inspects and amends that commit through project hooks, never commits the embedded database, pushes Dolt history to Git special refs, and proves fresh-clone bootstrap.

Migration-safe validation and delivered records

Migration mode automatically invokes check-docs.py --migration-mode, excludes identified generated assets and legacy workflow-command paths from generic checks, preserves mdBook H1 part headings, and records project acronyms rather than silently rewriting them. Every exception is narrow and removed or reconciled before strict final validation.

Prepare or finalize regenerates implemented-feature marker regions in docs/src/SUMMARY.md and docs/src/features/index.md from delivered records. A drafting command may assemble a candidate historical design and standalone delivery record from legacy design/tasks, imported Beads identities, changed paths, and Git history. Generated content remains a candidate requiring human semantic review and cannot itself satisfy finalization.

Verified checkpoint commits

Migration instructions and helpers never use or recommend git commit --no-verify. Gate 2 first captures legacy inventory/readiness, completes candidate reconciliation, and reaches a clean conflict gate. Only then may it invoke the existing generated project-local scripts/setup-tooling.py --json; no second installer is introduced. Lock, install, and hook setup must succeed or stop with the provisioner’s recovery commands. Migration verifies the installed Git hook routing and direct config readiness before the adoption commit, so the ordinary commit exercises the reconciled pinned hook rather than ambient tooling.

If strict final documentation is intentionally premature because legacy task files remain, migration defers the project’s documentation steps until archival or replaces their commands with explicit migration-aware validation. It never requests or records a documentation-step skip. The actual strict hook must be rerun after each fix; a plan-only invocation is not validation. Once finalization removes legacy inputs, ordinary commits run strict documentation. A hook failure stops, names the hook/step, preserves the worktree, and gives a reproduction and recovery command. HK_SKIP_HOOK and broad bypass remain prohibited.

Quality Requirements

  • Preservation checks compare behavior inventories, not raw formatting.
  • Repeated scans/import/finalization remain idempotent, including byte-stable durable scan/report output when inputs are unchanged.
  • Prompt contract tests cover every decision category.
  • Failure fixtures prove unapproved step loss, untracked archives, temporary leftovers, and hook failure block completion.
  • Final migration leaves strict docs, tests, Beads graph, hooks, and worktree clean.
  • Large imports expose deterministic progress and retries mutate only incomplete/conflicting records.
  • Checkbox parsing covers [ ], [-], [x], and nonempty explicit-status precedence.
  • Project identity tests cover dedicated migration worktrees and non-main default branches.

Compatibility and Migration Requirements

Existing migration manifests remain readable. New inventory, artifact, answer, checkpoint, import-phase, identity, and progress evidence uses optional schema fields with explicit defaults; missing inventory/readiness and unresolved backup disposition block mutation until captured or decided. Resuming an older migration captures baseline evidence before further mutation, preserves imported Beads identities, import completion timestamps, phase progress, and existing archived tasks.

Existing Context

The adoption helper preserves differing project-owned files and stages generated candidates, but manual reconciliation can still remove existing hk steps. Current guidance says to preserve project-specific content generally without an hk capability-loss guard. The reference already defines migration/legacy-tasks as the default archive, yet completion language does not make an untracked archive’s invalid state prominent. Questions name required fields but do not provide a consistent context/example contract. The skill’s command examples do not contain --no-verify, but they do not explicitly prohibit it or prove hooks ran.

Proposed Design

Extend migration state with pre/post hk inventories, explicit dispositions, import phases/progress, and canonical repository identity; add artifact classification and tracked state checks; standardize contextual question templates; and strengthen checkpoint gates around real hook execution. Batch Beads mutations through the narrowest supported transaction boundary, regenerate delivered navigation, and keep generated historical records as reviewable candidates. Keep candidate reconciliation manual where syntax-aware merging would be unsafe. Validate the complete behavior through a named integration contract over bounded legacy, large-import, custom-hk, and deliberately failing-hook fixtures.

Architecture Consistency

Existing Patterns Reused

The feature reuses dry-run gates, resumable manifests, explicit user decisions, candidate staging, migration-mode docs validation, strict final verification, and durable evidence records.

Invariants Preserved

Legacy text remains untrusted evidence; Copier does not overwrite project-owned files; semantic decisions require the user; migration is resumable; Beads becomes live work authority only after verified import; final worktree is clean.

New Decisions Introduced

Existing hk behavior is protected by an explicit capability inventory. Migration artifacts have normative lifecycle classes. Broad hook bypass is prohibited, and prompt clarity has a testable minimum contract.

Architecture Documentation Changes

docs/src/architecture/index.md will document additive adoption and the hook-verification boundary.

Operational Considerations

An unevaluable legacy hk config may require manual inventory confirmation and can delay migration. This is preferable to silent loss. Hook failures may expose pre-existing defects; baseline readiness evidence aids attribution without proving it. Recovery remains local and resumable. Durable archives increase repository size slightly but preserve evidence.

Documentation Impact

Documentation concernExact pageCreate or updatePlanned changeOwning Beads task
Architecturedocs/src/architecture/index.mdUpdateAdditive adoption, repository identity, import transaction/resume, and hook-verification boundariestasks .8, .9, .5
Usage / Operationsdocs/src/operations/index.mdUpdate incrementallyQuestions/artifacts/hooks (.1.4), progress/retry (.7, .9), identity/adoption (.8), migration mode (.10)tasks .1.10; .5 reconciles
Developmentdocs/src/development/index.mdUpdate incrementallyCheckpoints (.4), large import/performance fixtures (.9), generated records/navigation (.10), integration (.5)tasks .4, .9, .10, .5
Referencedocs/src/reference/index.mdUpdate incrementallyExact inventory/artifact/question/checkpoint/import-progress/identity/drafting commands, fields, states, and defaultstasks .1.10; .5 reconciles
Skill procedureskills/migrate-workflow/SKILL.mdUpdateOrdered gates, contextual questions, verified commitstasks .1.4
Migration referenceskills/migrate-workflow/references/MIGRATION.mdUpdateDetailed reconciliation, archive, and recovery procedurestasks .1.4
Navigationdocs/src/SUMMARY.mdUpdate design markersRegister this designplanning
Implemented Feature Recorddocs/src/features/migration-safety-and-clarity/index.mdCreate during close-outPreserve delivery and audit historylifecycle close-out

Validation Strategy

  • Preserve and compare custom hk steps in a legacy migration fixture.
  • Inject same-key collisions and require a recorded disposition.
  • Reject unapproved step deletion and unevaluated claims of equivalence; require manual confirmation for unevaluable hk.
  • Repeat unchanged scan --write and assert byte-stable manifest/report output.
  • Finalize into tracked archives; reject untracked archives, candidate leftovers, and unresolved backup disposition; cover retained and removed backups.
  • Assert every named prompt category includes the seven required context elements without snapshotting incidental prose.
  • Use failing and successful provisioner/hook fixtures to prove checkpoint mutation stops or commits through installed hooks; cover the targeted docs exception record.
  • Resume an older manifest before mutation; preserve baseline evidence, imported Beads identities, and existing archives.
  • Resume after each failure and confirm idempotence.
  • Parse checkbox states and preserve global import audit fields through rescans.
  • Import at least 300 records with progress assertions; interrupt/retry and assert only remaining mutations execute.
  • Exercise a suffixed migration worktree and non-main remote default branch; require explicit answers when ambiguous.
  • Verify exact stealth .beads tracking, migration-mode exclusions, acronym/H1 preservation, regenerated navigation, and review-required delivered-record candidates.
  • Run migration verifier with Beads, strict documentation checks, focused/full tests, and final clean status.

Implementation Decomposition

  1. dstack-mol-9zl.1: capture inventories/readiness, preserve byte-stable scans, guard additive hk reconciliation, and update its operations/reference sections.
  2. dstack-mol-9zl.2: classify artifacts, enforce backup disposition and durable tracking, and update its operations/reference sections.
  3. dstack-mol-9zl.3: standardize the reusable contextual-question checklist/examples and update its operations/reference sections.
  4. dstack-mol-9zl.4: provision the reconciled pinned hook, prohibit broad bypass, validate checkpoint hooks/targeted exceptions, and update development/operations/reference sections.
  5. dstack-mol-9zl.7: fix task-status precedence, preserve import audit/phase state, and expose remaining-work resume accounting.
  6. dstack-mol-9zl.8: make canonical project name/slug/default branch explicit or evidence-backed and reconcile stealth Beads tracking instructions.
  7. dstack-mol-9zl.9: batch large Beads imports, report progress, and prove interrupted retries scale with remaining work.
  8. dstack-mol-9zl.10: automate migration-safe validation, implemented-feature navigation, and review-required delivered record drafting.
  9. dstack-mol-9zl.5: aggregate old-manifest compatibility and all bounded resumable fixtures into the complete integration contract, then reconcile all reader documentation.

Dependencies and Parallelism

This feature depends on hk policy simplification so its candidate inventory reflects the final generated policy. Tasks are serialized because they share the migration skill, reference, script, manifest, and integration fixture; .5 is the final integration gate after .7.10. Every task depends directly on specification reconciliation. Each task runs its named focused migration test with uv run --frozen --group test pytest, uv run --no-project python scripts/check-docs.py, HK_JOBS=1 mise run check, and the full uv run --frozen --group test pytest suite before commit; .5 additionally runs the complete migration test partition and asserts final clean status.

Rollout and Migration

Apply the stronger checks to new and resumed migrations. Older manifests first capture missing inventories and artifact state without changing imported Beads identities. A migration blocked by new evidence requirements remains resumable.

Risks and Tradeoffs

Capability inventories cannot prove semantic equivalence for arbitrary custom shell commands, so collisions remain a human decision. More contextual prompts make individual questions longer but reduce uninformed answers and rework. Strict hook enforcement may uncover legacy defects earlier and lengthen migration, which is the intended safety tradeoff. Pre-adoption readiness evidence supports attribution but cannot by itself prove whether every later failure was pre-existing. Transaction batching must preserve per-record recovery evidence; bounded phases and durable progress favor recoverability over one opaque all-or-nothing import. Production hardening bounds default apply passes to two incomplete features and requires complete native formula/parent-label inheritance when reconstructing interrupted state. A separate preview/apply repair may add proven missing labels for exact identities but cannot replace labels or tolerate extras. Native Beads owns worktree authority and synchronization; migration validates effective identity without mirroring controls or pinning an alternate database path. Drafted historical records reduce repetition but may contain incorrect semantic inference, so human review remains mandatory.

Rejected Alternatives

  • Automatically replace existing hk.pkl: rejected because it can delete important checks.
  • General Pkl AST merging: rejected as disproportionate and unsafe for arbitrary expressions/imports.
  • Treat untracked archives as optional local evidence: rejected because completion requires a clean durable record.
  • Keep terse questions: rejected because the user cannot judge scope or consequences.
  • Permit --no-verify for intermediate commits: rejected because it bypasses unrelated safeguards.

Open Questions

None.

Deferred Decisions

No native implementation decision is deferred. Broader Copier merge automation requires a separate demonstrated need.

Planning Record

Questions Asked and Answers

The user reported lost hk steps, unclear migration questions, an untracked legacy task archive, and commits made with --no-verify. They expect additive behavior, contextual explanations, durable records, and verified commits.

Assumptions

Legacy repositories may contain arbitrary valid hk/Pkl configuration and project-specific hooks. Git is available because migration already requires a repository and clean checkpoint boundaries.

Design Changes During Planning

The plan separates template hk simplification from migration protection, keeps Pkl reconciliation manual, and adds an automated capability-loss guard rather than attempting syntax-aware merging.

A later production-scale migration of checkpoint-artifact-server supplied additional execution evidence: 300 Beads records required repeated 30–35 minute imports; retries revisited completed records; checkbox completion was lost; rescans dropped global import completion metadata; a suffixed migration worktree produced the wrong project name; main was chosen instead of the repository’s dev default; stealth Beads guidance conflicted with staging; transitional validation needed manual exclusions; implemented-feature navigation was not generated; and 17 historical delivery records required repetitive reconstruction. Tasks .7.10 were added before final integration to turn those observed failures into explicit correctness, identity, performance, progress, validation, and documentation contracts.

Source Material

Current migration skill, reference, adoption and migration scripts, migration fixture tests, generated hk policy, and the user’s completed migration observations.

Design — Migration artifact retirement

Metadata

  • Beads feature root: dstack-mol-b8d
  • Feature slug: migration-artifact-retirement
  • Design path: docs/src/features/migration-artifact-retirement/design.md
  • Implemented record: docs/src/features/migration-artifact-retirement/index.md
  • Base branch: main
  • Status: reviewed

Existing Context

/migrate-workflow already records durable migration authority, manifests, reports, baselines, session approvals, and legacy-task archives. It also creates delivered-record candidates for review, but those files are staging material and must not become a second source of migration truth.

Feature Summary

Document and enforce the temporary lifecycle of delivered-record candidate files created by /migrate-workflow.

User Intent

migration/delivered-record-candidates/ is a local review workspace, not migration evidence that belongs in commit history. Agents must not stage or commit those files. After migration has passed final verification, the agent may remove the directory. The migration can be resumed in the same worktree while the files remain; if they are lost, the agent reruns candidate drafting and review rather than recovering them from Git history.

Goals

  • Tell /migrate-workflow agents exactly which candidate files are transient.
  • Keep candidate files out of ordinary migration commits by using explicit durable staging paths.
  • Permit a successfully finalized migration to verify after the transient candidate directory is removed.
  • Keep the change to one small implementation task covering the procedure, verifier behavior, and regression test.

Non-Goals

  • Do not remove or make transient the baseline, manifest, report, session-authority, resume-approval, or legacy-task archive artifacts. Those records explain and validate the migration.
  • Do not add candidate dispositions, historical Git-blob fields, retirement journals, a compatibility command, or a new migration workflow.
  • Do not change Beads import, semantic review, feature records, finalization transactions, or remote Git behavior.
  • Do not automatically delete candidate files before final verification.
  • Do not generalize cleanup to arbitrary files under migration/.

Artifact Policy

ArtifactLifecycleCommit policy
migration/baseline.json and migration/baseline.mddurable migration evidencecommit
migration/workflow-migration.json and .mddurable migration state and reportcommit
migration/session-authority.json and resume approvalsdurable authority auditcommit
migration/legacy-tasks/durable legacy intent archivecommit
migration/delivered-record-candidates/transient review workspacenever commit; remove after final verification
migration/template-adoption-candidates/ and backupconditional temporary reconciliation statefollow their existing disposition procedure

Candidate files are useful for same-worktree interruption and review, but they are not the authority for resume. The manifest, Beads state, committed checkpoints, and explicit migration authority remain the workflow evidence. A new worktree or a missing candidate directory before finalization requires rerunning draft-delivered-records and semantic review; a finalized migration intentionally permits the directory to be absent.

Proposed Design

Keep delivered-record candidates local through review and finalization. Enforce the pre-finalization presence and digest checks in the migration core, preserve finalized verification after intentional cleanup, and reject any attempt to redraft a finalized migration.

User-Facing Behavior

  1. draft-delivered-records --apply writes candidates under migration/delivered-record-candidates/.
  2. The agent reviews each candidate and promotes the actual implemented record. Candidate files remain available for review until final verification.
  3. Checkpoints stage only durable migration paths and promoted records. Commands must not use git add -A when candidate files are present.
  4. finalize --apply performs a preflight that every reviewed candidate path exists and still matches its recorded digest before it sets migration_finalized. A missing or changed candidate fails finalization and leaves the migration unfinished. Finalization does not delete candidate files automatically.
  5. After finalize --apply succeeds and verify --beads reports completion for a manifest with migration_finalized: true, the user may explicitly authorize removal of migration/delivered-record-candidates/. The agent then removes the directory and reruns verification. A finalized manifest does not fail merely because this transient directory is absent.
  6. If candidates disappear before finalization, verification and finalization fail. Redrafting a missing candidate clears its prior review metadata even when regenerated bytes have the same digest, so semantic review must run again. After finalization, candidate absence is intentional and does not trigger redrafting.

Operational Considerations

Agents use explicit durable staging paths and never use git add -A while delivered candidates exist. Candidate cleanup is manual: it follows successful finalize --apply, completed verify --beads with migration_finalized: true, and explicit user approval. Cleanup is followed by verification; cleanup is never an automatic finalization side effect.

Requirements

  • The migration skill and reference procedure explicitly classify delivered-record candidates as transient and prohibit staging or committing them.
  • Migration commit examples use explicit durable paths and explicitly exclude the candidate directory.
  • Verification requires reviewed candidate files while migration_finalized is false.
  • Finalization rejects a missing or changed reviewed candidate before setting migration_finalized.
  • Redrafting after candidate loss clears review metadata and requires fresh semantic review.
  • Verification permits a missing reviewed candidate path after migration_finalized is true, while continuing to validate the manifest’s semantic evidence and promoted implemented record.
  • Regression tests cover deletion before finalization, redrafting after deletion, and finalized verification after explicit candidate deletion.
  • The implementation is one self-contained task and one commit.

Architecture Consistency

This is a small correction to the existing migration artifact contract. Durable migration records remain the audit and resume evidence. Candidate Markdown is staging material only, so it is intentionally not copied into Git history and is recreated when needed. The verifier already distinguishes pre-finalization from finalized state; finalization now proves candidate presence and digest before setting that flag, and post-finalization verification permits intentional absence. Redrafting treats a missing prior candidate as a loss of review state, even when regenerated bytes are identical.

No new authority, state machine, journal, command, Beads schema, or Git-history lookup is introduced.

Dependencies and Parallelism

The single implementation task depends on this reviewed specification and owns the migration runtime, assigned reader-facing documentation, tests, and one commit. No parallel implementation task, new command, or external service is required. Close-out remains responsible for the delivered record and roadmap/navigation reconciliation.

Documentation Impact

Documentation concernExact pageChangeOwner
Migration procedureskills/migrate-workflow/SKILL.mdMark delivered candidates transient, use explicit durable staging paths, and document post-verification deletion.dstack-mol-u15.1
Migration referenceskills/migrate-workflow/references/MIGRATION.mdRecord artifact lifecycles, resume limits, and candidate deletion procedure.dstack-mol-u15.1
Operationsdocs/src/operations/index.mdClarify transient candidate material, explicit deletion authority, finalization boundary, and recovery.dstack-mol-u15.1
Migration referencedocs/src/reference/index.mdDistinguish delivered-record candidates from template candidates and document finalization, deletion, and redrafting.dstack-mol-u15.1
Verification teststests/test_migrate_legacy_workflow.pyCover missing candidates before finalization, redrafting after loss, and finalized verification after deletion.dstack-mol-u15.1
Feature design navigationdocs/src/SUMMARY.mdPreserve the existing feature-design entry.dstack-mol-u15.1
Roadmap reconciliationdocs/src/planned-features.mdUpdate the feature from design to delivered only during close-out after delivery.dstack-mol-42a
Implemented feature indexdocs/src/features/index.mdAdd the delivered record to the implemented-feature index during close-out.dstack-mol-42a
Implemented SUMMARY navigationdocs/src/SUMMARY.mdAdd the delivered record to the implemented-feature marker during close-out.dstack-mol-42a
Delivered-record pagedocs/src/features/migration-artifact-retirement/index.mdCreate the standalone delivered record during close-out.dstack-mol-42a

Risks and Tradeoffs

  • Losing candidates before finalization loses review state and requires redrafting and fresh semantic review.
  • Keeping candidates local avoids permanent staging clutter but means they cannot be recovered from migration Git history; durable migration evidence remains available for resume.
  • A finalized manifest tolerates candidate absence only after semantic and promoted-record verification remains valid.

Validation Strategy

  • Write tests first for deletion before finalization, redrafting after candidate loss, and finalized verification after deletion.
  • Run the focused migration tests and the existing migration regression suite.
  • Run uv run --no-project python scripts/check-docs.py, mise run check, mise run docs:check, and the full repository test suite before the task commit.
  • Existing unrelated baseline failures must be reported separately rather than broaden this task.

Implementation Decomposition

One implementation task only: dstack-mol-u15.1 updates the migration skill/reference/operations text, adjusts the finalized verification boundary, adds the three behavior tests, and commits the complete change.

No follow-up command, compatibility, cross-slice, or historical-proof tasks are required.

Open Questions

There are no unresolved product or safety questions. The user explicitly selected transient candidates, manual post-verification cleanup, and one implementation task; template-adoption candidate cleanup continues to use its existing disposition procedure.

Planning Record

Questions Asked and Answers

  • Question: Should delivered-record candidate files be transient, excluded from commits, and removable after a successful migration? Answer: Yes.
  • Question: Should this be one small task rather than a multi-stage retirement feature? Answer: Yes.

Scope Reset

The earlier design proposed candidate dispositions, historical Git-blob verification, transactional retirement journals, and a compatibility command. That boundary was rejected as unnecessarily complex. The current design supersedes it with one procedure-and-verifier change.

Design — Monorepo tooling layout

Metadata

  • Beads feature root: dstack-mol-7s4
  • Feature slug: monorepo-tooling-layout
  • Design path: docs/src/features/monorepo-tooling-layout/design.md
  • Implemented record: docs/src/features/monorepo-tooling-layout/index.md
  • Base branch: main
  • Status: reviewed

Feature Summary

Add an explicit monorepo layout mode in which root configuration owns shared documentation and quality policy while package-local mise configuration owns language-specific commands.

User Intent

Monorepo support should follow the proven Nixstasis ownership pattern, but only after single-package language profiles are stable.

Goals

  • Add single-package and monorepo layout answers.
  • Keep root docs, hk, shared tools, and aggregate tasks authoritative.
  • Generate package-local mise configuration from each package’s selected language profiles.
  • Scope hk checks and working directories to changed packages.
  • Compose root tasks through declared dependencies.
  • Preserve existing root and package hk/mise behavior during managed updates unless an exact replacement is reviewed.
  • Make setup/update preflight explicit and renders byte-idempotent without adding a second scaffold-state authority.

Non-Goals

  • Discover or invent package boundaries without user input.
  • Generate package source/manifests.
  • Require experimental mise monorepo behavior unless no stable alternative exists.
  • Support arbitrary nested workspace graphs initially.

User-Facing Behavior

For monorepos, setup collects canonical package display names, slugs, paths, and language profiles, validates portable non-overlapping paths, and renders shared root tooling plus package-local task ownership. Root mise.toml owns the union of tools and aggregate tasks; package-local mise files own package commands and working directories; root hk owns scoped pre-commit dispatch. mise run check validates every declared package, while pre-commit scopes work by changed paths.

Switching an already managed single-package project to monorepo mode is explicit. Normal managed updates continue using Copier preview/three-way conflict behavior. Candidate files are used only when introducing a generated package-local path that is already occupied by a non-Copier project file; Copier-managed root files are never diverted into a second update protocol. Repeated preview/render/update is byte-idempotent.

Requirements

Functional Requirements

  • Layout defaults explicitly to single-package.
  • Monorepo package paths are relative, normalized, unique, and cannot escape the repository.
  • Root checks aggregate package checks without duplicating commands.
  • hk globs and working directories prevent unrelated packages from paying validation cost.
  • Documentation explains the generated repository map and canonical task entry points.
  • Package names and reader-facing titles preserve explicit user capitalization and technical acronyms.
  • Managed single-package projects may enter monorepo mode only through an explicit layout/package answer update.
  • Copier-managed files use Copier three-way conflicts; candidates apply only when a newly generated package-local path is occupied by a non-Copier project file.
  • Existing setup/update preflight reports package inputs, generated destinations, and collisions before mutation.
  • Root mise run check validates all declared packages; changed-package scoping applies only to pre-commit.
  • Generated repository-layout documentation is one Copier-owned page and byte-idempotent; no new marker framework is introduced.

Quality Requirements

  • No experimental mise setting is used without implementation-time evidence that it remains required and supported.
  • Mixed-language package matrices render without destination collisions.
  • Root and package task names remain discoverable.
  • A representative larger flat package matrix has bounded render time and proves unrelated packages avoid pre-commit validation while full check still covers all packages.
  • Repeated render/update fixtures assert byte-stable output and existing Copier conflict recovery.

Compatibility and Migration Requirements

This depends on stable profile composition from Language quality profiles and the native runner contract from hk policy simplification. It may ship later without blocking single-package adoption. Existing Copier answers without a layout field default to single-package; no package-local files are introduced until the user explicitly selects monorepo mode and supplies the complete bounded package list. Version 1 supports at most 32 flat packages.

Package answer and path contract

repository_layout is single-package or monorepo, defaulting to single-package. monorepo_packages is empty in single-package mode and contains 1–32 objects in monorepo mode:

  • display_name: nonempty reader-facing text preserved exactly, including technical acronyms;
  • slug: explicit lowercase filesystem/task-safe [a-z0-9]+(?:-[a-z0-9]+)*, unique under Unicode case-folding;
  • path: normalized relative POSIX directory path used as the package root;
  • language_profiles: nonempty canonical profile list using the delivered profile validation and other exclusivity.

Paths must be unique, case-fold unique, non-absolute, nonempty, and free of ./.. components. Package roots cannot be ancestor/descendant pairs, resolve through symlinks, or equal root-owned .git, .beads, docs, migration, scripts, skills, or their descendants. Package source/manifests remain project-owned inside valid package roots.

Tool, task, lock, and provisioning ownership

A monorepo retains exactly one root mise.lock and one root scripts/setup-tooling.py. Root mise.toml declares the union of tools required by all package profiles and aggregate tasks. Package-local mise files declare package commands, working directories, and task metadata but no independently locked tool versions. The root provisioner remains the only lock/install/hook authority and preserves the existing four-platform lock and Nix host exception.

Root mise run check and CI validate all packages. Root hk uses package path globs to dispatch package-local commands for changed files during pre-commit; shared/root file changes run shared policy and any explicitly affected aggregate checks. fix follows the same changed-path package scoping. A future explicit check:changed task is out of scope.

Existing Context

Nixstasis demonstrates root tool ownership with package-local mise files and scoped hk steps. Its experimental setting and concrete Go/Elixir commands are not suitable for direct copying.

Proposed Design

Extend recorded answers with repository layout and the exact bounded package schema. Render package-local configuration only in monorepo mode. Prefer stable mise task inclusion/dependencies. A timeboxed compatibility spike verifies package task discovery plus participation in the single root lock/install path and selects, in order, stable includes, explicit root task composition, or a narrowly isolated supported fallback. Every outcome preserves the fixed ownership, task, lock, and provisioner contract, so no product decision is deferred.

Reuse explicit input, preflight, additive preservation, and idempotence lessons from migration safety without importing its durable progress state. Keep Copier as scaffold/update authority: ordinary managed changes use its three-way merge; only collisions at newly introduced non-Copier package-local destinations create candidates under the existing migration/copier-adoption-candidates/<same-relative-path> convention. Do not copy migration archives, checkpoint-evidence schema, or a separate resume manifest into setup/update.

Architecture Consistency

Existing Patterns Reused

Additive language profiles, root shared baseline, task dependencies, file globs, and explicit working directories.

Invariants Preserved

The root remains the documentation and workflow authority; package configs cannot override Beads or feature identity.

New Decisions Introduced

Monorepo structure is explicit user input and a later dependent capability, never inferred.

Architecture Documentation Changes

Document root/package ownership and task resolution.

Operational Considerations

Invalid, reserved, symlinked, case-colliding, or overlapping package paths fail before rendering. Package additions after setup require an explicit Copier answer update. Setup/update preflight shows exact package answers, destinations, and collisions. Copier conflicts preserve the worktree and use the existing update recovery command; newly occupied non-Copier package destinations are preserved with a candidate at the same relative path.

Generated monorepos include Copier-owned docs/src/reference/repository-layout.md, listing root/package ownership, package paths/profiles, full-check behavior, and canonical package task names. The generated docs/src/SUMMARY.md.jinja includes that page only in monorepo mode. Because Copier owns the whole generated page, no package-navigation marker or repository-level package navigation is introduced.

Documentation Impact

Documentation concernExact pageCreate or updatePlanned changeOwning Beads task
Architecturedocs/src/architecture/index.mdUpdateRoot/package ownership and additive candidate boundary.7, .9 reconciles
Usagedocs/src/operations/index.mdUpdateExplicit inputs, preflight, Copier conflicts/recovery, candidate decisions.6, .7, .9
Developmentdocs/src/development/index.mdUpdatemise evidence, package tasks, scale/recovery validation.5, .8, .9
Referencedocs/src/reference/index.mdUpdateExact answers, paths, states, commands, defaults, candidate fields.5.7, .9
Generated layout referenceskills/setup-project/template/docs/src/reference/repository-layout.md.jinjaCreatePackage map, ownership, tasks, full/changed scope.7, .9
Generated navigationskills/setup-project/template/docs/src/SUMMARY.md.jinjaUpdateRegister layout reference only in monorepo mode.7, .9
Generated tooling docsskills/setup-project/template/docs/src/development/tooling.md.jinja; skills/setup-project/template/docs/src/reference/tooling.md.jinjaUpdatePackage task and exact tooling contracts.7, .9
Skill proceduresskills/setup-project/SKILL.md; skills/update-project/SKILL.mdUpdateInputs, conversion, preflight, conflicts, recovery.6, .7, .9
Implemented Feature Recorddocs/src/features/monorepo-tooling-layout/index.mdCreate during close-outDelivery evidencelifecycle close-out

Validation Strategy

  • Render representative homogeneous and mixed-language monorepos; validate path rejection, task discovery, scoped checks, root aggregation, no duplicated destinations, acronym preservation, and docs accuracy.
  • Compare supported mise task composition and single-root lock/install behavior against current official behavior in a timeboxed compatibility fixture.
  • Upgrade an older managed single-package answer set only after explicit monorepo selection; exercise Copier preview, three-way conflict recovery, and candidate preservation only for newly occupied non-Copier package destinations.
  • Validate the 32-package limit, exact schema, case-fold collisions, overlap, reserved paths, and symlink rejection.
  • Render a larger bounded flat package matrix and assert unrelated package pre-commit checks do not run while root mise run check validates every package.
  • Regenerate the Copier-owned repository-layout page/navigation and assert unchanged rerenders are byte-stable.
  • Run focused matrix/update/recovery tests, documentation checks, HK_JOBS=1 mise run check, and the canonical full suite.

Implementation Decomposition

  1. dstack-mol-5bq.5 mise compatibility spike: timebox current official composition evidence and record the supported implementation path without changing the established ownership/task contract.
  2. dstack-mol-5bq.6 layout contract: add the exact layout/package schema, path/name/profile validation, legacy-answer defaulting, explicit single-package conversion, and setup/update preflight.
  3. dstack-mol-5bq.7 additive rendering: render one root tool/lock authority, package tasks, scoped pre-commit hk, Copier conflict/candidate behavior, and the Copier-owned repository-layout page.
  4. dstack-mol-5bq.8 scale and update safety: add homogeneous/mixed/32-package matrices, full-check versus pre-commit scoping, conflict recovery, candidate preservation, and byte-idempotence tests.
  5. dstack-mol-5bq.9 reader documentation and integration: publish exact contracts and aggregate the bounded fixtures into final integration evidence.

Dependencies and Parallelism

Depends on Language quality profiles and hk policy simplification, both delivered. Tasks are ordered spike → layout contract → additive rendering → scale/update safety → integration because they share answer schemas, templates, and fixtures. Every task depends directly on specification reconciliation and owns one reviewed commit.

Rollout and Migration

Deliver after single-package profiles have been exercised in generated projects.

Risks and Tradeoffs

Package matrices can become open-ended. Initial support enforces a bounded, flat package list and defers exotic workspace layouts. Copier’s existing three-way conflicts remain the managed-update mechanism; candidates are limited to new package destinations occupied by non-Copier files. This avoids a second scaffold-state authority while preventing behavior loss.

Rejected Alternatives

  • Default monorepo mode: needless complexity for most projects.
  • Automatic package discovery: impossible in a new empty scaffold.
  • Copy Nixstasis experimental configuration verbatim: version-sensitive and unverified.

Open Questions

None. Current mise capability is an implementation fact handled by the compatibility spike; all supported outcomes must satisfy the already-decided ownership and task-resolution contract.

Deferred Decisions

Nested workspaces and package-specific deployment pipelines. Automatic package discovery remains excluded unless a later feature establishes a safe, user-confirmed contract.

Planning Record

Questions Asked and Answers

The user agreed monorepo support should be a later dependent feature.

Assumptions

A bounded flat package list covers the first real consumers.

Design Changes During Planning

Monorepo support was removed from the first delivery sequence. Production migration evidence later added explicit identity, explicit preflight, additive update preservation, bounded large-matrix validation, acronym preservation, and Copier-owned navigation requirements. Review rejected migration-style durable progress/candidate machinery for ordinary managed file rendering; legacy-only archives, checkpoint state, and a second scaffold authority remain out of scope.

Source Material

Nixstasis root/package mise layout and scoped hk configuration.

Implemented features

This index tracks features during close-out and after delivery. Each record states its current reconciliation, validation, and delivery status.

Each feature record explains:

  • delivered user-visible behavior;
  • architecture integration;
  • operational impact;
  • validation evidence;
  • intentional changes from the original design;
  • related documentation, Beads root, commits, and pull requests.

Planned or partially implemented features remain in Planned Features and Beads. They are added here only during close-out.

Feature index

Purposeful project scaffold

Delivery Summary

  • Beads feature root: dstack-mol-ln9
  • Status: delivered
  • Pull request: not created
  • Merge commit: 8a7e015d4e663e9f4ea3f670765f5cd3482ad790 (fast-forward)
  • Design record: design.md

Delivered Capability

New-project setup now requires an explicit purpose, intended users, current scope, boundaries, and one of seven project kinds. Copier renders a small factual mdBook from that brief instead of generating empty documentation categories or replacement instructions.

User-Facing Behavior

/setup-project asks one question for each missing brief field and project kind. Direct helper invocation requires --purpose, --users, --scope, --boundaries, and --project-kind. Blank values, NUL, CR, LF, and unsupported kinds fail before rendering with field-specific guidance.

Every kind receives the same initial reader pages: project overview, documentation conventions, feature lifecycle, planned features, and implemented features. Kind changes only future documentation-concern guidance. Brief punctuation is preserved literally in Markdown and safely encoded in book.toml.

Design Integration

The implementation preserves Copier’s two entry points, update-source recording, unsafe=False, no-overwrite behavior, existing-project routing, Git/Beads setup, and post-render validation. The structured brief is the only source for initial product facts. Both documentation checker copies now validate the pages a project publishes without requiring a fixed taxonomy.

Operational Impact

This is an intentional pre-1.0 breaking input change. Old project_description answer sets are not accepted or silently translated. New setup calls must provide the five structured fields. Existing managed-project and migration routing remains unchanged.

Reference and Contracts

Validation Evidence

  • uv run pytest -m "not external": all 116 applicable tests passed; 1 tag-only test skipped and 1 external test deselected.
  • Scaffold matrix: 14 independent kind/entrypoint cases and 28 real Copier renders across both README states passed.
  • uv run scripts/check-docs.py: passed.
  • mise run check: passed, including mdBook build and repository quality checks.
  • Generated documentation checker and mdBook build passed for every matrix render.
  • Final holistic delivery and documentation-drift reviews passed with no unresolved blocker after fixes.
  • main fast-forwarded to 8a7e015d4e663e9f4ea3f670765f5cd3482ad790.

Design Reconciliation

Delivered as Designed

The exact structured input contract, seven kinds, universal factual reader file set, kind-specific future guidance, variable documentation checker, and safety regression matrix match the reviewed design.

Intentional Changes

None from the reviewed implementation-ready design.

Deferred Work

Restoring structured-brief support in managed-project adoption is tracked by dstack-ub6. Universal tooling, language profiles, GitHub delivery, and monorepo layout remain owned by Universal project tooling through Monorepo tooling layout.

Rejected or Removed Scope

The feature does not infer missing answers, preserve the old free-form description, generate application source, or create speculative architecture, operations, development-overview, or reference-overview pages.

Documentation Updated

  • docs/src/introduction/project-overview.md
  • docs/src/architecture/index.md
  • docs/src/operations/index.md
  • docs/src/development/index.md
  • docs/src/reference/index.md
  • docs/src/planned-features.md
  • docs/src/features/index.md
  • docs/src/SUMMARY.md
  • docs/src/features/purposeful-project-scaffold/index.md

Audit Trail

  • Specification reconciliation: 112d121, with roadmap readiness at 353c8ce.
  • Structured inputs (dstack-mol-a8i.1): 1ba43242d37aa174a452ec1ec10e99c1305e42f5.
  • Factual generated documentation (dstack-mol-a8i.2): 1497515f92004eba5354b68f33cde7319123bd09.
  • Variable-taxonomy checker (dstack-mol-a8i.3): c0269638805f1613ec63ec76fc6c222393c1d412.
  • Complete scaffold matrix (dstack-mol-a8i.4): f665b30171040c301b575e1b7ddb8e3b9a32487e.
  • Implementation coordinator dstack-mol-a8i closed after all four children and acceptance checks completed.

Universal project tooling

Delivery Summary

  • Beads feature root: dstack-mol-lg3
  • Status: delivered
  • Pull request: not created
  • Merge commit: 5644ad7dbff2711454f0b6a97b2b8513427a72db (fast-forward)
  • Design record: design.md

Delivered Capability

Every generated project now receives one mise-managed developer interface, one hk quality policy, concrete tooling documentation, and a project-owned lock for Linux and macOS on x64 and ARM64.

User-Facing Behavior

Contributors use mise run check, mise run fix, mise run docs:check, mise run docs:build, and mise run docs:serve. Setup resolves mise.lock, installs tools with the lock enforced, and installs repository-local hk hooks as a separate stage. Conflict-free Copier updates reconcile the same lock, tools, and hooks.

Provisioning failures preserve the rendered scaffold. Setup and update report separate mise availability, lock, install, and hook states with bounded error text and exact recovery commands. Copier conflicts skip all newly rendered project code until the user resolves and accounts for the update.

Design Integration

Copier remains a local renderer; the generated stdlib provisioner owns network-backed tooling state. Provisioning ignores user-global mise tools so the committed lock represents only the nine project tools. One serialized hk step map powers read-only checks, explicit fixes, and pre-commit fixes with Git stashing. Language quality profiles can extend this baseline with language profiles, and GitHub validation and docs deployment can consume its stable task names.

Operational Impact

The initial lock targets linux-x64, linux-arm64, macos-x64, and macos-arm64. Setup without Git completes lock and installation while reporting hooks as skipped-no-git. Explicit post-setup skipping executes no generated code. Manual recovery uses python3 scripts/setup-tooling.py --json and the additional commands returned in tooling.recovery.

Reference and Contracts

Validation Evidence

  • uv run pytest -m "not external": 149 tests passed; 1 tag-only test skipped and 2 external tests deselected.
  • uv run pytest -q tests/test_repository.py::test_generated_tooling_contract_end_to_end: 1 live generated-tooling contract test passed.
  • mise run check: passed, including repository quality checks, documentation validation, and mdBook build.
  • Live generated-project validation resolved and installed the four-platform lock, loaded tasks/hk config, executed the installed pre-commit hook while preserving unstaged work, applied explicit fixes, built docs, and ended clean.
  • Setup/update simulations passed for missing mise, process-launch errors, lock/install/hook failures, no Git, explicit skip, stale locks, Copier conflicts, invalid provisioner output, and missing/empty locks.
  • Every bounded implementation review and follow-up verification passed.

Design Reconciliation

Delivered as Designed

The exact nine-tool baseline, synchronized hk/Pkl pin, five stable tasks, four-platform lock, separate provisioning stages, generated tooling pages, setup/update ownership, failure recovery, and root reader documentation match the reviewed design.

Intentional Changes

Implementation serialized every file-mutating hk step after a review exposed concurrent staging races. The provisioner also isolates user-global mise configuration after live validation showed global tools could incorrectly participate in a project lock/install. External validation now bootstraps mise without pre-installing project tools so the live test proves the generated contract.

Deferred Work

Language-specific profiles remain Language quality profiles. Generated GitHub validation and documentation deployment remain GitHub validation and docs deployment. Monorepo layout remains Monorepo tooling layout.

Rejected or Removed Scope

Generated projects do not receive application source, package manifests, dstack’s release task, language-specific checks, generated CI workflows, or Windows support from this feature.

Adjacent Tracked Improvement

Implementation exposed an opportunity to reduce redundant full-suite runs. Separate task dstack-pyn, discovered from Universal project tooling update task dstack-mol-b69.5, owns the resulting repository, canonical skill, and generated-agent guidance. It was validated and closed in 75f6ce572cbf56b0c2802d6d97e5f0cfa5510099; it is recorded here because that independently tracked commit is delivered on the same branch, not because it expands Universal project tooling’s product scope.

Documentation Updated

  • docs/src/architecture/index.md
  • docs/src/operations/index.md
  • docs/src/development/index.md
  • docs/src/reference/index.md
  • docs/src/planned-features.md
  • docs/src/features/index.md
  • docs/src/SUMMARY.md
  • docs/src/features/universal-project-tooling/index.md
  • Generated docs/src/development/tooling.md
  • Generated docs/src/reference/tooling.md
  • Generated README.md

Audit Trail

  • Reviewed design and graph: e94e5fa8f4a633cf41006fd1552f151dfc93f820; roadmap readiness: c1ead06.
  • Universal templates (dstack-mol-b69.1): 78c95582bd97f817a63415e00696a157eae5d642.
  • Setup provisioning (dstack-mol-b69.2): 63fd3c6ae2ccdd61dd435592f4fc6bcf04a533bb.
  • Copier update reconciliation (dstack-mol-b69.5): 429f00921526e464ca49ca0473ad311db3afcc20.
  • End-to-end contract (dstack-mol-b69.3): 18d0faaed9eeb0f77edd1eaf5ba5f6e990132daf.
  • Root reader documentation (dstack-mol-b69.4): a2ac878ebd4afd338d57f2cf1b2a8c8d26d862cf.
  • Focused iterative validation guidance (dstack-pyn): 75f6ce572cbf56b0c2802d6d97e5f0cfa5510099.
  • Implementation coordinator dstack-mol-b69 closed after all five required children and acceptance checks completed.

Language quality profiles

Delivery Summary

  • Beads feature root: dstack-mol-ni2
  • Status: delivered
  • Pull request: not created
  • Merge commit: 5c2ecf246615a6c30edd3c8a92f99d27926384ba (fast-forward)
  • Design record: design.md

Delivered Capability

Generated projects can select Python, TypeScript, Rust, Go, Elixir, and Nix quality profiles, combine recognized profiles for one polyglot root policy, or select exclusive other for only the universal tooling baseline. Setup and updates record the canonical selection without generating application manifests, dependencies, package roots, or source.

User-Facing Behavior

Setup accepts repeatable --language-profile; updates preserve the recorded selection unless repeatable --add-profile or --remove-profile operations explicitly change it. Legacy updates inspect only root manifests and present suggestions for confirmation rather than applying them automatically.

Selected profiles extend the existing five mise tasks and one hk policy with file-gated source checks and fixes. Root-manifest-gated project checks run only when relevant. Pytest, Vitest, and Credo remain project-owned dependencies; flake checks require system Nix. Missing prerequisites fail with profile-specific messages.

Design Integration

Language quality profiles composes direct membership-gated sections into Universal project tooling’s mise.toml, hk.pkl, ignores, provisioner, and generated tooling pages. Mutating source steps are serialized in canonical profile order. Check-only project steps stay out of fix and pre-commit, except the explicit Go module-tidy fix. Profiles add no task names or second provisioning path.

Operational Impact

The universal lock still targets Linux and macOS on x64 and ARM64. Nixfmt-rs is supported on Linux x64/ARM64 and macOS ARM64. The provisioner validates those entries and atomically removes only nixfmt-rs’s macOS x64 lock table before locked installation. Matching Nix inputs fail clearly on unsupported macOS x64. Profile source and project checks skip cleanly when their files or root manifests are absent.

Reference and Contracts

Validation Evidence

  • uv run --frozen --group test pytest -q: 163 tests passed; 1 tag-only release test skipped.
  • uv run pytest -q tests/test_repository.py -k "language_profile": exhaustive selection and profile contract checks passed.
  • uv run pytest -q tests/test_repository.py::test_generated_language_profiles_end_to_end: the real combined four-platform lock, locked install, and all profile source fix/check steps passed.
  • mise run check: passed, including repository quality checks, documentation validation, and mdBook build.
  • uv run scripts/check-docs.py, mdbook build docs, and git diff --check: passed.
  • Every bounded implementation review and targeted follow-up verification passed.

Design Reconciliation

Delivered as Designed

Canonical selection, explicit setup/update operations, root-only legacy suggestions, all six recognized profiles, exclusive other, manifest-gated project checks, project-owned ecosystem dependencies, stable tasks, conditional ignores and documentation, and the no-application-scaffolding boundary match the reviewed design.

Intentional Changes

Mise’s os selector filters installation on the current host but does not filter cross-platform lock resolution. Mise 2026.7.5 resolved a wasm fallback for nixfmt-rs on macOS x64. The generated provisioner therefore validates the three supported nixfmt-rs entries and atomically removes only its macOS x64 table while retaining the four-platform lock for all other tools.

Deferred Work

Generated GitHub validation and documentation deployment remain GitHub validation and docs deployment. Package-local policy and monorepo layout remain Monorepo tooling layout.

Rejected or Removed Scope

Profiles do not generate or modify package manifests, dependencies, application source, package roots, CI workflows, release automation, or monorepo structure. other adds no executable language behavior.

Documentation Updated

  • docs/src/architecture/index.md
  • docs/src/operations/index.md
  • docs/src/development/index.md
  • docs/src/reference/index.md
  • docs/src/planned-features.md
  • docs/src/features/index.md
  • docs/src/SUMMARY.md
  • docs/src/features/language-quality-profiles/index.md
  • Generated docs/src/development/tooling.md
  • Generated docs/src/reference/tooling.md

Audit Trail

  • Reviewed design and execution graph: b7756f807a6f68a0bb908fa42a5bc23097f25212; implementation readiness: 244ab21c3d20af5d24ad7f110b80ce72725b43e4.
  • Profile composition and setup/update selection (dstack-mol-9as.1): f6621726e15b88b0922ea82629612a7e75b409ca.
  • Python and TypeScript profiles (dstack-mol-9as.2): 01f7507628f92badfc808867a35d6cc0fbd4efac.
  • Rust and Go profiles (dstack-mol-9as.3): c204910a457792d6d10fb4bb25166ab5404b96a0.
  • Elixir and Nix profiles (dstack-mol-9as.5): 4980c9d0179b5c6755773c77f40bf457970c665b.
  • Exhaustive matrix, real combined contract, and final documentation (dstack-mol-9as.4): efdda50e70dd71475170c1f1620f4f644d4066b3.
  • Implementation coordinator dstack-mol-9as closed after every required child passed acceptance and fresh review.

GitHub validation and docs deployment

Delivery Summary

  • Beads feature root: dstack-mol-8fe
  • Status: delivered
  • Pull request: not created
  • Merge commit: 0a72a3c97a7172f962678148ffc6ba0eaa146581 (fast-forward)
  • Design record: design.md

Delivered Capability

Every generated project receives GitHub validation that installs the committed mise lock and invokes the same local mise run check policy. Generated mdBook documentation can be published through an opt-in GitHub Pages workflow after an administrator explicitly enables repository state through external GitHub CLI.

User-Facing Behavior

.github/workflows/validate.yml runs on pushes and pull requests with only contents: read, disables checkout credential persistence, and uses the pinned mise action to install the committed lock with caching before running only mise run check.

.github/workflows/docs.yml accepts only configured-default-branch pushes and manual dispatches. Both jobs require DOCS_DEPLOYMENT_ENABLED == 'true'. The build job receives only contents: read, uses the pinned mise action to install locked tools with its cache enabled, runs mise run docs:build, and uploads docs/book; the deploy job alone receives pages: write and id-token: write and targets the github-pages environment.

Administrators run mise run docs:deployment:enable with an external authenticated gh. The idempotent helper creates or updates Pages with build_type=workflow, sets the repository variable only after Pages configuration succeeds, and prints the Pages URL. Failures stop without claiming success and include exact manual recovery commands.

Design Integration

GitHub validation and docs deployment reuses Universal project tooling’s committed lock, named tasks, hk policy, and generated documentation. It adds no second CI quality policy and does not add gh to the nine universal mise tools. Copier renders repository files but never changes GitHub state; only the explicit administrator task crosses that boundary. Language quality profiles profiles compose underneath the same workflows without changing their triggers, permissions, or commands.

Operational Impact

Pages remains disabled after setup and Copier update. Deployment requires both repository-side build_type=workflow and the exact true repository variable. Pull requests and forks have no deployment path. Repeating the enable task converges on the same state. Missing gh, authentication, repository resolution, API access, variable permission, or URL lookup produces a nonzero result with installation or manual recovery guidance.

Reference and Contracts

Validation Evidence

  • uv run --frozen --group test pytest -q: 189 tests passed; 1 tag-only release test skipped.
  • mise run check: passed, including repository quality checks, documentation validation, and mdBook build.
  • Focused validation, deployment, and enablement tests passed through both Copier entry points.
  • Rendered workflows passed actionlint and zizmor; combined profile and conflict-free Copier update coverage passed.
  • Every bounded implementation review and targeted follow-up verification passed.
  • Credentialed disposable-repository exercise (mise run docs:deployment:enable twice, then verify Pages build_type=workflow, DOCS_DEPLOYMENT_ENABLED, and html_url): waived by the user for commit ea6b558786b51cb1f07071913db50cea3f90b906. Residual risk: mocked coverage cannot prove current GitHub API, permission, or Pages-provisioning behavior against a live repository.

Design Reconciliation

Delivered as Designed

Locked local/CI parity, full action pins, least-privilege job permissions, default-branch-only Pages deployment, exact repository gating, external-gh administration, safe mutation ordering, nine tools, six tasks, standalone generated operations documentation, both Copier entry points, and conflict-free updates match the reviewed design.

Intentional Changes

Implementation tasks were serialized after preflight confirmed that every generated file and task changes shared exact scaffold assertions. Default-branch interpolation uses YAML-safe JSON quoting. The Pages build enables mise caching, with an explicit zizmor suppression because this repository accepts the cache-poisoning risk. Enablement recognizes only a terminal (HTTP 404) as absent Pages and publishes exact fallback commands on every failure.

Deferred Work

Package-local tooling and monorepo layout remain Monorepo tooling layout. No GitHub validation and docs deployment product scope is deferred.

Rejected or Removed Scope

GitHub validation and docs deployment does not add raw duplicate linter commands, lock regeneration, pull-request deployment, path-filtered deployment, universal gh installation, automatic GitHub mutation during setup/update, application deployment, release automation, or package manifests.

Documentation Updated

  • docs/src/architecture/index.md
  • docs/src/operations/index.md
  • docs/src/development/index.md
  • docs/src/reference/index.md
  • docs/src/planned-features.md
  • docs/src/features/index.md
  • docs/src/SUMMARY.md
  • docs/src/features/github-validation-and-docs-deployment/index.md
  • Generated docs/src/development/tooling.md
  • Generated docs/src/operations/github-pages.md
  • Generated docs/src/reference/tooling.md

Audit Trail

  • Reviewed design and execution graph: df88d3b5b492641c8722adaa2adf455a8a6c93c1; serialized task correction: 74b1c66afb874187e05b21d62b991f2f4444d7bb.
  • Locked GitHub validation (dstack-mol-41q.1): e8dd79af1bbbd71f6811e642da29332befa9192d.
  • Gated Pages deployment (dstack-mol-41q.2): 685f61f93b5d68289c1327cad3cfc4c990f3b750.
  • Safe external-gh enablement (dstack-mol-41q.3): ebbfe142b786d8a05028900cff234501e3027fac.
  • Combined profile/update integration (dstack-mol-41q.4): ea6b558786b51cb1f07071913db50cea3f90b906.
  • Implementation coordinator dstack-mol-41q closed after every required child passed acceptance and fresh review.
  • Holistic delivery and drift reviews passed after reconciling the waiver, lifecycle status, and manual-dispatch wording.

hk policy simplification

Delivery Summary

  • Beads feature root: dstack-mol-5v0
  • Status: delivered
  • Delivery action: fast-forward merge
  • Pull request: not created
  • Merge commit: 668a3a4a0b3b4d778047397da680d08b28078f0a
  • Design record: design.md

Delivered Capability

Root and generated projects use a smaller native-first hk policy. Equivalent formatter and linter commands use pinned hk built-ins, and independent checks rely on native file locking. Go alone retains output-sensitive dependencies so final source and module metadata agree.

Commit-message hooks now apply Harper’s full native rule set to human-authored content while preserving exact Git metadata, canonical Beads footers, and stable release subjects.

User-Facing Behavior

mise run check, mise run fix, pre-commit, and commit-message hooks retain their supported validation inventory. Custom steps remain only where native behavior is not equivalent. Generated language profiles compose without a broad serialization chain. gofumpt runs after goimports, and fix-only module tidy runs after both source formatters.

Design Integration

The policy preserves the universal-tooling and language-profile contracts. Root and Copier-generated Pkl remain aligned, while project-specific Contextlint, documentation, Markdown-table, Rumdl, language, and manifest gates keep documented custom implementations. File locks, rather than unrelated dependency edges, coordinate concurrent fixes.

Operational Impact

No deployment or runtime operations change. Contributors keep using the existing mise commands and installed Git hooks. Hook stashing restores unrelated unstaged content byte for byte.

Reference and Contracts

Validation Evidence

  • Static repository partition: 127 passed, 1 skipped.
  • Repository integration partition: 59 passed.
  • Additional deployment, enablement, validation, and migration integration partition: 22 passed.
  • Baseline and six language-profile focused tests: 7 passed.
  • Generated tooling end-to-end external test passed, including hook behavior, fix-to-check convergence, and exact unstaged-byte restoration.
  • HK_JOBS=1 mise run check, uv run scripts/check-docs.py, Pkl evaluation, mdBook, and git diff --check passed.
  • Every implementation task received an independent review and passed its follow-up review.

Design Reconciliation

Delivered as Designed

Native built-ins replace equivalent custom steps, Harper keeps its full rule set, Git and Beads metadata filtering is narrow, supported checks remain present, and the broad dependency chain is removed.

Intentional Changes

The exact stable release: vX.Y.Z subject is filtered on physical line one because the existing release contract is authoritative. Release-shaped body text and prerelease subjects remain linted. Rumdl stays minimally custom because its built-in diff header is incompatible with hk’s canonicalization behavior.

Deferred Work

Migration preservation and prompting belong to Migration safety and clarity. Package-local policy belongs to Monorepo tooling layout.

Rejected or Removed Scope

No validation capability was removed. Unrelated checks are not serialized merely to produce deterministic console order, and Harper rule classes are not disabled to accommodate machine-authored metadata.

Documentation Updated

  • docs/src/architecture/index.md
  • docs/src/development/index.md
  • docs/src/development/tooling.md
  • docs/src/reference/index.md
  • docs/src/reference/tooling.md
  • docs/src/planned-features.md
  • docs/src/features/index.md
  • docs/src/SUMMARY.md
  • docs/src/features/hk-policy-simplification/index.md
  • Generated development and reference tooling templates

Audit Trail

  • Reviewed specification and execution graph: b156f9418a8bc29bca96e37ca7fa63b4deed70e1.
  • Release-contract specification correction: 1b893379156828ceabe99b8fdc97a2acfeef3a42.
  • Native Harper restoration (dstack-mol-v8c.1): 13baa637767345bc37fe3562ecc7962c6222ab73.
  • Native-step and dependency simplification (dstack-mol-v8c.2): 3e6239b695e993c4322921db5f5509c098ed5fd9.
  • Final validation evidence (dstack-mol-v8c.3): 3eedbe50af0d0e20e450ba89fc62e5b5c915dbf4.
  • Close-out reconciliation and Go module ordering fix: 82642bcca216818cd56f2607dbb9a811081b7a7f.
  • Recursive root policy self-test removal: 668a3a4a0b3b4d778047397da680d08b28078f0a.
  • Implementation coordinator dstack-mol-v8c closed after all reviewed tasks passed acceptance.

Migration safety and clarity

Delivery Summary

  • Beads feature root: dstack-mol-tki
  • Status: delivered
  • Pull request: not created; delivered by local fast-forward merge
  • Merge commit: 047bc5b2f2c4f496bc77c2f478d600ed15a6bbf9
  • Design record: design.md

Delivered Capability

Legacy workflow migration now preserves project-owned hk behavior, classifies durable and temporary artifacts, explains required decisions, uses verified project-local hooks, and resumes large Beads imports without replaying completed work. Repository identity, default branches, delivered-record reconciliation, and migration progress are explicit and durable.

User-Facing Behavior

Migration inventories existing hooks before adoption and blocks unapproved capability loss. Dry-run and apply are separate; apply reports progress and stores resumable phases. Large imports use bounded Dolt commits. Canonical project identity comes from repository evidence rather than a migration worktree suffix. Historical delivered records can be drafted from legacy, Beads, and Git evidence, but verification and finalization require digest-bound human review.

Design Integration

The implementation preserves Beads as live workflow authority, Copier as scaffold authority, project-owned files as migration inputs, and ordinary verified Git commits as checkpoint authority. Migration-mode documentation validation is strictly transitional; finalization restores the ordinary strict contract.

Operational Impact

Operators receive actionable recovery for provisioning, hook, relationship, and documentation failures. Manifests retain hook inventories, artifact dispositions, contextual decisions, import phases, progress, checkpoint evidence, canonical identity, and delivered-record review state. Collaborative Beads initialization exposes control files and the formula for the workflow-owned commit while keeping database contents in synchronized Dolt history.

Reference and Contracts

Validation Evidence

  • uv run --frozen --group test pytest -q tests/test_repository.py::test_migration_safety_resumable_end_to_end: passed.
  • Migration test partition: 13 passed.
  • HK_JOBS=1 mise run check: passed.
  • uv run --frozen --group test pytest: 224 passed, 1 skipped.
  • Final implementation reviewer: passed with no blockers.

Design Reconciliation

Delivered as Designed

Additive hk reconciliation, artifact lifecycle enforcement, contextual questions, verified checkpoints, resumable imports, canonical repository identity, migration-safe documentation reconciliation, and final integration are delivered.

Intentional Changes

Production migration evidence expanded the reviewed design with checkbox-status correction, bounded Beads transactions, progress reporting, canonical branch discovery, exact stealth tracking, navigation generation, and reviewed delivery record drafting. Final integration composes bounded fixtures rather than duplicating expensive 300-record and provisioner setup in one temporary repository.

Deferred Work

None within the delivered feature scope.

Rejected or Removed Scope

General Pkl AST merging, automatic acceptance of generated delivery records, broad hook bypass, and automatic deletion of legacy archives remain intentionally unsupported.

Documentation Updated

  • docs/src/architecture/index.md
  • docs/src/operations/index.md
  • docs/src/development/index.md
  • docs/src/reference/index.md
  • docs/src/features/migration-safety-and-clarity/design.md
  • skills/migrate-workflow/SKILL.md
  • skills/migrate-workflow/references/MIGRATION.md

Audit Trail

Implementation commits span 0de2faf through 23f0a55, with performance evidence in a34574c and design expansion in 7affc7c. Every bounded task received isolated review; the implementation coordinator dstack-mol-9zl closed after all children passed focused and full validation.

Post-delivery hardening under dstack-98w corrected native Beads parent-label inheritance, bounded each default import pass to two incomplete features, made interrupted fresh imports resume their exact identities, separated mutable interactions.jsonl synchronization from immutable linked-worktree authority checks, hid the primary authority mirror, and made generated migration/Beads Markdown safe under project hooks. A follow-up correction made every native formula/inherited label mandatory and added a dry-run-first additive repair for exact manifest-backed damage, preventing ad hoc label replacement from silently removing workflow semantics. Later simplification retained repository ownership and graph-integrity boundaries while making one explicit docs exception cover the bounded mechanical checkpoints. A subsequent deletion-oriented correction removed temporary Git initialization, database publication, control mirroring, and database-path injection in favor of native Beads initialization, worktree discovery, Git-origin refs, and bootstrap. Roadmap-only planned roots now finish their mechanical import without inventing a design and retain the planning note required before activation. Migration manifests now use deterministic compact JSON so large generated histories remain subject to the repository’s ordinary file-size policy without requiring an exception.

Migration artifact retirement

Delivery Summary

  • Beads feature root: dstack-mol-b8d
  • Status: delivered
  • Pull request: not created
  • Merge commit: 1a5ebf89c4c02e25cdb66e044b334989d31c0fbc (fast-forward)
  • Design record: design.md

Delivered Capability

/migrate-workflow now treats migration/delivered-record-candidates/ as transient local review material. Durable migration authority and audit artifacts remain committed, while reviewed delivered-record candidates stay out of ordinary checkpoints and can be removed only after final verification and explicit user approval.

User-Facing Behavior

Finalization rejects missing, changed, or unsafe reviewed candidates before setting migration_finalized. Losing a candidate before finalization invalidates its review metadata and requires fresh semantic review. A finalized migration continues to verify after intentional candidate cleanup, and drafting is rejected for finalized manifests. Migration checkpoint examples stage durable paths explicitly, handle optional resume approvals, and include tracked and untracked adoption files without staging delivered candidates. Candidate drafting and adoption staging reject existing or dangling symlinks at the candidate directory and feature-slug path.

Design Integration

The implementation preserves the existing manifest, Beads state, committed checkpoints, and session authority as migration evidence. It adds no new authority, state machine, journal, compatibility command, or Git-history lookup. Delivered candidates remain a review workspace; template-adoption candidates retain their separate disposition procedure.

Operational Impact

Operators must keep delivered candidates out of commits and must not remove them before successful finalize --apply, completed verify --beads with migration_finalized: true, and explicit approval. After approved cleanup, rerun verification. If candidates disappear before finalization, redraft and semantically review them again.

Reference and Contracts

Validation Evidence

  • mise run check: passed at implementation commit 5b051f58ae92df543ee90d9cf8760bec2e495f8d.
  • mise run docs:check: passed on the close-out worktree (mdBook build and documentation checker).
  • uv run --no-project python scripts/check-docs.py: passed.
  • Focused migration behavior tests: 6 passed, including candidate symlink rejection.
  • Adoption staging and migration contract tests: 4 passed, including dangling-symlink rejection.
  • Ruff check and format checks passed for changed Python files.
  • The full repository suite reached 225 passed before three unrelated baseline failures in generated GitHub Pages deployment assertions; no feature file was involved in those failures.
  • Final task review approved the implementation after the staging-contract test correction.

Design Reconciliation

Delivered as Designed

Transient candidate classification, explicit durable staging, pre-finalization presence and digest checks, review invalidation after candidate loss, finalized verification after approved cleanup, finalized-draft rejection, and the single-task implementation boundary match the reviewed design.

Intentional Changes

The reviewed design retains manual cleanup rather than adding an automatic deletion command or retirement journal. The feature is delivered by the authorized fast-forward merge; this record is the post-merge finalizer.

Deferred Work

No implementation work or delivery reconciliation remains deferred.

Rejected or Removed Scope

Candidate dispositions, historical Git-blob proof, retirement journals, a compatibility command, and a new migration workflow were explicitly removed from the earlier superseded design.

Documentation Updated

  • docs/src/features/migration-artifact-retirement/design.md
  • docs/src/operations/index.md
  • docs/src/reference/index.md
  • skills/migrate-workflow/SKILL.md
  • skills/migrate-workflow/references/MIGRATION.md
  • docs/src/features/migration-artifact-retirement/index.md
  • docs/src/features/index.md
  • docs/src/SUMMARY.md
  • docs/src/planned-features.md

Audit Trail

  • Reviewed specification and graph reconciliation: 977701d256312f54ed75b24b458031bb67182e61.
  • Implementation and regression tests: 5b051f58ae92df543ee90d9cf8760bec2e495f8d.
  • Implementation task: dstack-mol-u15.1; coordinator: dstack-mol-u15.
  • Architecture, simplicity, documentation, and execution reviews approved the redesigned boundary.
  • Final task review approved the implementation after one contract-test finding was resolved.
  • Fast-forward delivery completed at 1a5ebf89c4c02e25cdb66e044b334989d31c0fbc; this is the guarded post-merge finalizer.

Monorepo tooling layout

Delivery Summary

  • Beads feature root: dstack-mol-7s4
  • Status: delivered
  • Pull request: not created; delivered by local fast-forward merge
  • Merge commit: 3da287c59c1ff7d22792f3a3f1f37c048477d8a7
  • Design record: design.md

Delivered Capability

dstack can create and update bounded monorepos with 1-32 explicit packages. One root mise configuration owns the profile-tool union, aggregate checks, lockfile, and provisioner. Task-only package configurations execute profile checks from package roots, while root hk applies package-prefixed changed-file formatting policy.

User-Facing Behavior

Setup and update accept an explicit repository layout and complete package objects containing preserved display names, filesystem-safe slugs, normalized paths, and canonical language profiles. Validation rejects malformed, reserved, overlapping, case-colliding, or symlinked paths before rendering. Older answers remain single-package until explicit conversion. Root mise run check executes every package; pre-commit and fix select package source by path.

Design Integration

Copier remains recorded scaffold authority. The root remains workflow, documentation, tool-version, lock, and hook authority. Deterministic package configs contain commands but no tools. Previously recorded package configs are managed and refresh with current answers; newly occupied non-managed destinations preserve their bytes and receive a canonical adoption candidate that blocks update completion until reconciled. No package discovery, nested workspace support, progress manifest, or second lock authority was introduced.

Operational Impact

Layout preflight reports exact destinations and collisions. Unresolved Copier conflicts or package candidates skip provisioning, documentation, and Beads checks and return a nonzero status. Candidate retries preserve both project and generated bytes. The existing tooling recovery command remains python3 scripts/setup-tooling.py --json.

Reference and Contracts

Generated monorepos also contain a Copier-owned docs/src/reference/repository-layout.md page and conditional summary entry.

Validation Evidence

  • Stable mise 2026.7.5 compatibility with experimental behavior disabled: passed.
  • Named monorepo integration partition: passed.
  • Homogeneous, mixed, and 32-package matrices: passed; maximum render completed in 94.55 seconds.
  • Exact full-check execution, changed-path selection, byte-stable rendering, conflict, and candidate retries: passed.
  • HK_JOBS=1 mise run check: passed.
  • uv run --frozen --group test pytest: 257 passed, 1 skipped.
  • Beads dependency-cycle validation: passed with no cycles.
  • Isolated implementation and final integration reviews: passed with no blockers.

Design Reconciliation

Delivered as Designed

Explicit bounded package answers, strict preflight, stable namespaced mise tasks, one root lock/provisioner, package-root checks, changed-path hk policy, additive update preservation, generated layout documentation, and maximum-size evidence are delivered.

Intentional Changes

The compatibility spike selected mise’s stable native monorepo task paths with explicit config roots and root lockfile opt-in. Because Copier cannot emit an answer-dependent number of destination files, the trusted setup/update helpers render deterministic package configs directly from Copier-recorded answers without introducing separate state. Any newly occupied non-managed destination produces an exact-byte candidate rather than silent replacement.

Deferred Work

Nested workspaces, automatic package discovery, package-specific deployment pipelines, and a separate check:changed command remain deferred.

Rejected or Removed Scope

Experimental mise behavior, independent package locks or installers, inferred packages, migration-style checkpoint state, and automatic candidate acceptance remain unsupported.

Documentation Updated

  • docs/src/architecture/index.md
  • docs/src/operations/index.md
  • docs/src/development/index.md
  • docs/src/reference/index.md
  • docs/src/features/monorepo-tooling-layout/design.md
  • skills/setup-project/SKILL.md
  • skills/update-project/SKILL.md
  • generated development, tooling reference, repository-layout, and summary templates

Audit Trail

The reviewed design and graph are recorded in 509ff8e. Implementation commits are 8ce9a73, 433db4c, ff44a78, a59b5bc, and 76aa287. Each bounded task received an isolated review and current validation before commit. The implementation coordinator dstack-mol-5bq closed after all five tasks passed.