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.mdfiles store intended feature behavior and design decisions. - Reader-facing pages under
docs/src/describe current supported behavior. - Implemented-feature
index.mdfiles preserve feature-specific delivery and audit history. planned-features.mdprovides 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 question | Documentation 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:
- record the mismatch in Beads;
- determine whether the divergence was intentional;
- correct the implementation or update the appropriate authoritative artifact;
- preserve the rationale and validation evidence;
- 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.ymlexposes the same scaffold for repository development and integration tests. - Beads stores live feature state and dependencies;
.beads/formulas/dstack-feature.formula.tomldefines the lifecycle graph. docs/src/features/<slug>/design.mdowns intended feature behavior.- Reader pages under
docs/src/own supported current behavior. - Implemented-feature
index.mdpages 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 updaterefreshes installed skill definitions and scripts./update-projectapplies the newest revision from the recorded stable or unstable channel to a managed repository. Pass--stableor--unstableto change the preserved channel. Repeat--add-profileand--remove-profilefor explicit idempotent profile changes; their sets must be disjoint and the result nonempty./update-project --adopt --unstableexplicitly bootstraps dstack itself as an unstable template consumer; reconcile every generated candidate before validation or commit./migrate-workflowadopts 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:
| Profile | Source check/fix | Root-manifest checks |
|---|---|---|
| Python | Ruff lint/format and ty | pytest through uv |
| TypeScript | Biome check/write | Vitest through Aube |
| Rust | rustfmt edition 2024 | Clippy and Cargo tests |
| Go | goimports, then gofumpt | tidy diff/verify, golangci-lint, tests; fix may tidy |
| Elixir | Mix format | warnings-as-errors compile, strict Credo, tests |
| Nix | nixfmt on supported hosts | system-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-onlydiscovered//:check,//packages/api:check, and//packages/web:checkfrom the two explicitconfig_roots;MISE_EXPERIMENTAL=0 mise run checkexecuted both package checks from the root aggregate;mise lock --dry-run --platform linux-x64targeted the rootmise.lockand 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:
- architecture consistency;
- simplicity and maintainability;
- documentation readiness;
- 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 role | Pi agent definition |
|---|---|
context-builder | dstack-context-builder |
architecture | dstack-architecture-reviewer |
simplicity | dstack-simplicity-reviewer |
documentation | dstack-documentation-reviewer |
execution | dstack-execution-reviewer |
task | dstack-task-reviewer |
delivery | dstack-delivery-reviewer |
drift | dstack-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
| Command | Purpose |
|---|---|
mise run check | Run the shared read-only hk validation policy. |
mise run fix | Apply deterministic fixes from the shared hk policy. |
mise run docs:check | Validate documentation structure and build the mdBook. |
mise run docs:serve | Serve the documentation locally. |
mise run docs:deployment:enable | Configure and enable generated GitHub Pages through external gh. |
mise run release | Run the Cocogitto release workflow; pushing is opt-in. |
cog changelog | Render the concise user-facing changelog from Conventional Commits. |
uv run pytest | Run 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 answer | Helper flag | Contract |
|---|---|---|
project_purpose | --purpose | Required, non-empty, single-line problem and intended outcome. |
project_users | --users | Required, non-empty, single-line intended users. |
project_scope | --scope | Required, non-empty, single-line current supported scope. |
project_boundaries | --boundaries | Required, non-empty, single-line exclusions and boundaries. |
project_kind | --project-kind | One 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
| Channel | Selection | Persistence |
|---|---|---|
stable | Newest stable PEP 440 tag, dereferenced to SHA | Default |
unstable | Git source default-branch HEAD | Explicit |
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
| Profile | Added mise tools | Manifest-gated checks |
|---|---|---|
| Python | Ruff, ty | project-owned pytest via uv |
| TypeScript | Aube, Biome; reuse Node | project-owned Vitest via Aube |
| Rust | Rust | Clippy and Cargo tests |
| Go | Go, gofumpt, goimports, golangci-lint | module hygiene, lint, and tests |
| Elixir | Erlang, Elixir | compile, project-owned strict Credo, and tests |
| Nix | nixfmt-rs except macOS x64 | system-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.
| Profile | Exact source checks | Exact source fixes | Profile ignores |
|---|---|---|---|
| Python | ruff 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/ |
| TypeScript | biome check --no-errors-on-unmatched {{ files }} | biome check --write --no-errors-on-unmatched {{ files }} | node_modules/, coverage/ |
| Rust | rustfmt --check --edition 2024 {{ files }} | rustfmt --edition 2024 {{ files }} | target/ |
| Go | output=$(goimports -l {{ files }}) && test -z "$output"; output=$(gofumpt -l {{ files }}) && test -z "$output" | goimports -w {{ files }}; gofumpt -w {{ files }} | coverage.out |
| Elixir | mix format --check-formatted {{ files }} | mix format {{ files }} | _build/, deps/, cover/ |
| Nix | nixfmt --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
| Path | Contract |
|---|---|
skills/<name>/SKILL.md | Canonical installed workflow instructions and version. |
skills/dstack-core/references/SKILL-VERSION.md | Startup version evidence and local freshness contract. |
skills/dstack-core/references/PI-REVIEWER-ROSTER.md | Optional Pi mapping, install, and discovery contract. |
skills/dstack-core/scripts/sync-pi-reviewers.py | Explicit 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.toml | Project-local feature lifecycle graph. |
docs/src/features/<slug>/design.md | Intended behavior and design decisions. |
docs/src/features/<slug>/index.md | Delivered feature reconciliation and evidence. |
docs/src/planned-features.md | Human roadmap; not executable state. |
.copier-answers.yml | Copier-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
| Path | Contract |
|---|---|
mise.toml | Declares ten tools, six tasks, hk routing, and fast-forward-only merges. |
mise.lock | Project-owned, nonempty resolved lock for four supported platforms; commit it. |
hk.pkl | Shared native-first steps for check, fix, and pre-commit; no broad chain. |
.config/rumdl.toml | Markdown policy compatible with the generated scaffold. |
.editorconfig | Universal UTF-8, LF, final-newline, and trailing-whitespace editor policy. |
_typos.toml | Narrow typo exceptions for commit and artifact hashes. |
contextlint.config.json | Documentation link, anchor, and image-target policy. |
cog.toml | Conventional Commit and changelog policy. |
.config/cog-changelog.tera | Concise plain-Markdown changelog template. |
scripts/setup-tooling.py | Stdlib provisioner used by setup, update, and manual recovery. |
scripts/enable-docs-deployment.py | External-gh Pages configuration and enablement helper. |
.github/workflows/validate.yml | Locked push and pull-request validation with contents: read. |
.github/workflows/docs.yml | Default-branch/manual gated Pages build and deployment. |
docs/src/development/tooling.md | Generated contributor commands and recovery. |
docs/src/reference/tooling.md | Generated exact tooling contract. |
docs/src/operations/github-pages.md | Generated 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
| Tool | Template version |
|---|---|
hk | 1.49.0 |
cocogitto | latest |
harper-cli | latest |
npm:@contextlint/cli | latest |
node | lts |
mdbook | latest |
uv | latest |
rumdl | latest |
typos | latest |
npm:markdown-table-formatter | latest |
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
| File | Contract |
|---|---|
mise.toml | Declares project tools, environment, and named tasks. |
mise.lock | Project-owned resolved downloads; commit it. |
hk.pkl | Defines the shared check/fix/pre-commit step map. |
.config/rumdl.toml | Configures Markdown linting and deterministic fixes. |
.editorconfig | Keeps editor output on UTF-8, LF, final newlines, and no trailing spaces. |
_typos.toml | Ignores hash-like identifiers while retaining typo checks elsewhere. |
contextlint.config.json | Checks documentation links, anchors, and image targets. |
cog.toml | Configures Conventional Commits and concise changelogs. |
.config/cog-changelog.tera | Renders plain Markdown changelogs without author noise. |
scripts/setup-tooling.py | Resolves the lock, installs tools, installs hk hooks, and returns JSON status. |
scripts/enable-docs-deployment.py | Configures workflow-built Pages through external gh. |
skills/dstack-core/scripts/reconcile-beads-interactions.py | Verifies and reconciles append-only Beads interaction evidence. |
skills/dstack-core/scripts/beads-workflow-lock.py | Serializes dstack Beads mutation intervals outside Git. |
skills/dstack-core/scripts/finalize-feature-delivery.py | Guards delivery/root closure with post-merge evidence. |
.github/workflows/validate.yml | Runs locked mise run check on pushes and pull requests. |
.github/workflows/docs.yml | Builds 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
| Step | Check | Fix | Files |
|---|---|---|---|
| Ruff lint | ruff check --force-exclude | add --fix | **/*.py, **/*.pyi |
| Ruff format | ruff format --quiet --force-exclude --diff | omit --diff | **/*.py, **/*.pyi |
| ty | ty check | none | **/*.py, **/*.pyi |
| pytest | uv run pytest | none | root 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
| Task | Behavior |
|---|---|
check | Run all hk checks without requesting fixes. |
fix | Apply deterministic hk fixes to the working tree. |
docs:check | Build the book, then validate documentation metadata and navigation. |
docs:build | Build the mdBook site. |
docs:deployment:enable | Configure Pages and enable its repository gate through external gh. |
docs:serve | Serve 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, orblocked.
Feature map
| Feature | Beads root | Roadmap state | Dependencies | Design |
|---|---|---|---|---|
purposeful-project-scaffold — Purposeful project scaffold | dstack-mol-ln9 | delivered | — | Design |
universal-project-tooling — Universal project tooling | dstack-mol-lg3 | delivered | — | Design |
language-quality-profiles — Language quality profiles | dstack-mol-ni2 | delivered | Universal project tooling | Design |
github-validation-and-docs-deployment — GitHub validation and docs deployment | dstack-mol-8fe | delivered | Purposeful project scaffold, Universal project tooling | Design |
hk-policy-simplification — hk policy simplification | dstack-mol-5v0 | delivered | Language quality profiles | Design |
migration-safety-and-clarity — Migration safety and clarity | dstack-mol-tki | delivered | hk policy simplification | Design |
migration-artifact-retirement — Migration artifact retirement | dstack-mol-b8d | delivered | Migration safety and clarity | Design |
monorepo-tooling-layout — Monorepo tooling layout | dstack-mol-7s4 | delivered | Language quality profiles, hk policy simplification | Design |
Cross-cutting decisions
- Every generated project receives the universal mise/hk/docs baseline.
- Tool aliases such as
latest,stable, andltsreduce template maintenance; each new project commits the resolvedmise.lockfor 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.
Recommended next work
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 answer | Helper flag | Type | Validation | Rendered ownership |
|---|---|---|---|---|
project_purpose | --purpose | str | Trimmed, non-empty, single line | README summary, book.toml description, overview Purpose, roadmap direction |
project_users | --users | str | Trimmed, non-empty, single line | Overview Intended users |
project_scope | --scope | str | Trimmed, non-empty, single line | Overview Current scope, roadmap direction |
project_boundaries | --boundaries | str | Trimmed, non-empty, single line | Overview Boundaries, roadmap direction |
project_kind | --project-kind | enum | Exact lowercase choice | Overview 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:
| Path | Content source |
|---|---|
README.md when enabled | Project name, purpose, and dstack workflow entry points |
docs/book.toml | Project name and TOML-safe purpose |
docs/src/SUMMARY.md | Only the useful universal pages listed below |
docs/src/introduction/project-overview.md | Kind, purpose, users, current scope, and boundaries |
docs/src/introduction/documentation-conventions.md | Source ownership plus kind-specific future concerns |
docs/src/development/feature-lifecycle.md | dstack workflow contract |
docs/src/planned-features.md | Brief-derived project direction and truthful empty roadmap |
docs/src/features/index.md | Truthful 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:
| Kind | Applicable future concerns |
|---|---|
library | installation/usage, public API and compatibility reference, diagnostics, development, architecture decisions |
cli | installation/usage, commands/configuration/files/exit behavior, troubleshooting, development, architecture decisions |
service | deployment/operations/health/observability/recovery, interfaces/configuration, development, architecture/security boundaries |
application | getting started and user workflows, configuration/troubleshooting, development, architecture decisions |
infrastructure | environments/deployment/operations/recovery, inventory/configuration/security reference, development, architecture decisions |
documentation | authoring/development, structure/style/publication reference |
other | no 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.mdmust 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 concern | Exact page | Create or update | Planned change | Owning Beads task |
|---|---|---|---|---|
| Introduction | docs/src/introduction/project-overview.md | Update | Document structured brief and minimal output | dstack-mol-a8i.2 |
| Architecture | docs/src/architecture/index.md | Update | Document kind-as-context rendering boundary | dstack-mol-a8i.2 |
| Usage | docs/src/operations/index.md | Update | Document required questions, flags, errors, and breaking scope | dstack-mol-a8i.1 |
| Development | docs/src/development/index.md | Update | Document checker contract and matrix validation | dstack-mol-a8i.3 |
| Reference | docs/src/reference/index.md | Update | Record answers, flags, kinds, validation, and outputs | dstack-mol-a8i.1 |
| Navigation | docs/src/SUMMARY.md | Update if new dstack pages are added | Keep dstack book current | dstack-mol-a8i.2 |
| Implemented Feature Record | docs/src/features/purposeful-project-scaffold/index.md | Create during close-out | Preserve delivery evidence | dstack-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.mdlinks, 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
dstack-mol-a8i.1: add and forward the exact structured inputs; update setup usage/reference docs and focused tests.dstack-mol-a8i.2: render the shared factual book, kind guidance, and dstack architecture/overview/navigation docs.dstack-mol-a8i.3: relax both checker copies, retain all other validation, and update checker-contract docs/tests.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, anddocs:serve. - Stash unstaged work during pre-commit fixes, not explicit
fixruns. - 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
| Tool | Version | Purpose/config |
|---|---|---|
hk | 1.49.0 | Runner; both hk.pkl package URIs must also use 1.49.0 |
node | lts | Runtime for the declared npm formatter |
mdbook | latest | Documentation via docs/book.toml |
uv | latest | Inline-metadata Python scripts |
rumdl | latest | Markdown via .config/rumdl.toml |
typos | latest | Typo detection |
npm:markdown-table-formatter | latest | Markdown 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 task | Command |
|---|---|
check | hk check -a |
fix | hk fix -a |
docs:check | build dependency, then uv run --no-project python scripts/check-docs.py |
docs:build | mdbook build docs |
docs:serve | mdbook 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:
- find
mise; - run
mise lock --yes --platform linux-x64,linux-arm64,macos-x64,macos-arm64; - require a nonempty
mise.lockand runmise install --locked; - if
.gitexists, runmise x -- hk install --miseseparately.
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 question | Exact destination | Owner |
|---|---|---|
| How do generated-project contributors use/recover tooling? | template docs/src/development/tooling.md.jinja | dstack-mol-b69.1 |
| What files, tools, tasks, states, and platforms exist? | template docs/src/reference/tooling.md.jinja | dstack-mol-b69.1 |
| Where are generated pages linked? | template docs/src/SUMMARY.md.jinja and conditional README | dstack-mol-b69.1 |
| Where is tooling authority/flow documented in dstack? | docs/src/architecture/index.md | dstack-mol-b69.4 |
| How are setup/update failures recovered? | docs/src/operations/index.md | dstack-mol-b69.4 |
| Which commands/hooks do dstack developers use? | docs/src/development/index.md | dstack-mol-b69.4 |
| What are exact files/tasks/status fields? | docs/src/reference/index.md | dstack-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
dstack-mol-b69.1: exact templates, generated tooling docs/navigation/README, render/config tests.dstack-mol-b69.2: generated provisioner, setup integration/skill, status and failure tests.dstack-mol-b69.5: update integration/skill and conflict/stale-lock tests; blocked by setup.dstack-mol-b69.3: structural and representative live end-to-end validation; blocked by template, setup, update.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 path | Suggested profile |
|---|---|
pyproject.toml | Python |
tsconfig.json | TypeScript |
package.json | TypeScript |
Cargo.toml | Rust |
go.mod | Go |
mix.exs | Elixir |
flake.nix | Nix |
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.
checkis 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.
| Profile | Added mise tools | Source-scoped check/fix | Root-manifest-gated checks |
|---|---|---|---|
| Python | ruff, ty | Ruff lint and format plus ty check on **/*.py, **/*.pyi | With pyproject.toml and matching tests/**/*.py, uv run pytest; pytest must be project-declared |
| TypeScript | aube, biome | Biome 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 |
| Rust | rust | rustfmt --check / rustfmt on **/*.rs using edition 2024 | With Cargo.toml, cargo clippy --all-targets --all-features -- -D warnings and cargo test --all-targets --all-features |
| Go | go, gofumpt, go:golang.org/x/tools/cmd/goimports, golangci-lint | goimports then gofumpt check/write on **/*.go | With go.mod, read-only tidy diff plus verify, golangci-lint run, and go test ./...; fix may run go mod tidy |
| Elixir | erlang, elixir | mix 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 |
| Nix | github:Mic92/nixfmt-rs, limited to Linux and macOS ARM64 | its nixfmt --check / nixfmt binary on **/*.nix | With 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.
| Step | Check command | Fix command | Gate / hooks |
|---|---|---|---|
ruff | ruff check --force-exclude {{ files }} | ruff check --force-exclude --fix {{ files }} | Python files; all three hooks |
ruff-format | ruff format --quiet --force-exclude --diff {{ files }} | ruff format --quiet --force-exclude {{ files }} | Python files; after ruff; all three hooks |
ty | ty check {{ files }} | none | Python files; after ruff-format; all three hooks |
biome | biome check --no-errors-on-unmatched {{ files }} | biome check --write --no-errors-on-unmatched {{ files }} | TypeScript files; all three hooks |
rustfmt | rustfmt --check --edition 2024 {{ files }} | rustfmt --edition 2024 {{ files }} | Rust files; all three hooks |
goimports | output=$(goimports -l {{ files }}) && test -z "$output" | goimports -w {{ files }} | Go files; all three hooks |
gofumpt | output=$(gofumpt -l {{ files }}) && test -z "$output" | gofumpt -w {{ files }} | Go files; after goimports; all three hooks |
mix-format | mix format --check-formatted {{ files }} | mix format {{ files }} | Elixir files; all three hooks |
nixfmt | nixfmt --check {{ files }} | nixfmt {{ files }} | Nix files; supported platforms; all three hooks |
pytest | prerequisite guard, then uv run pytest | none | root pyproject.toml plus tests/**/*.py; check only |
vitest | prerequisite guard, then aube exec vitest run | none | root package.json plus TS test/spec files; check only |
cargo-clippy | cargo clippy --all-targets --all-features -- -D warnings | none | root Cargo.toml; check only |
cargo-test | cargo test --all-targets --all-features | none | root Cargo.toml; check only |
go-mod | go mod tidy -diff && go mod verify | go mod tidy | root go.mod; check and fix, never pre-commit |
golangci-lint | golangci-lint run | none | root go.mod; check only |
go-test | go test ./... | none | root go.mod; check only |
mix-compile | mix compile --warnings-as-errors | none | root mix.exs; check only |
credo | prerequisite guard, then mix credo --strict | none | root mix.exs; check only |
mix-test | mix test --warnings-as-errors | none | root mix.exs plus test/**/*.exs; check only |
nix-flake-check | nix flake check | none | root 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.jinjaexplains selected check/fix behavior, manifest gates, project-owned test dependencies, and the Nix prerequisite.skills/setup-project/template/docs/src/reference/tooling.md.jinjalists 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:
| Profile | Ignore entries |
|---|---|
| Python | .venv/, __pycache__/, *.py[cod], .pytest_cache/, .ruff_cache/ |
| TypeScript | node_modules/, coverage/ |
| Rust | target/ |
| Go | coverage.out |
| Elixir | _build/, deps/, cover/ |
| Nix | .direnv/, result, result-* |
| Other | none |
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 concern | Exact page | Change | Owner |
|---|---|---|---|
| Architecture | docs/src/architecture/index.md | Root profile composition, shared/check-only maps, no-monorepo boundary | composition; final matrix reconciliation |
| Usage | docs/src/operations/index.md | Setup selection, legacy suggestions, add/remove update flow, manifest gates | matrix/docs task |
| Development | docs/src/development/index.md | Exact profile checks, fixtures, and matrix validation | matrix/docs task |
| Reference | docs/src/reference/index.md | Answer schema, profile/tool/command/ignore tables | composition selection contract; final matrix reconciliation |
| Generated development | skills/setup-project/template/docs/src/development/tooling.md.jinja | Conditional contributor behavior | serialized profile tasks; final reconciliation by matrix/docs |
| Generated reference | skills/setup-project/template/docs/src/reference/tooling.md.jinja | Conditional exact contracts | serialized profile tasks; final reconciliation by matrix/docs |
| Navigation | docs/src/SUMMARY.md and skills/setup-project/template/docs/src/SUMMARY.md.jinja | No change; existing tooling pages remain linked | matrix assertion only |
| Implemented feature | docs/src/features/language-quality-profiles/index.md | Create during close-out | lifecycle 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
- 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.
- Python and TypeScript profiles, fixtures, and their generated documentation sections.
- Rust and Go profiles, fixtures, and their generated documentation sections.
- Elixir and Nix profiles, fixtures, Nix prerequisite, and their generated documentation sections.
- 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:enableto 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
pushandpull_request, without write permissions; - job-level
contents: read; - checkout with persisted credentials disabled;
- a pinned
jdx/mise-actioninstalls the committed mise lock using its cache; mise run checkas 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 plusworkflow_dispatch;- no
pull_requesttrigger and no path filter; - concurrency group
pageswithcancel-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 ofdocs/book; - deploy job depending on build, carrying the same gate, only
pages: writeandid-token: write, andenvironment.name: github-pageswith 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:
- find
gh, otherwise print installation guidance and the manual commands below; - run
gh auth status; - resolve
OWNER/REPOwithgh repo view --json nameWithOwner --jq .nameWithOwner; - query
GET /repos/{owner}/{repo}/pages; - on HTTP 404, create Pages with
POST /repos/{owner}/{repo}/pages -f build_type=workflow; otherwise update it withPUT /repos/{owner}/{repo}/pages -f build_type=workflow; any other GET/API failure stops; - set
DOCS_DEPLOYMENT_ENABLED=truewithgh variable setonly after Pages configuration succeeds; - 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:
| Action | Major | Commit |
|---|---|---|
actions/checkout | v7.0.1 | 3d3c42e5aac5ba805825da76410c181273ba90b1 |
jdx/mise-action | v4.2.4 | 7e36c90d9ab29c415a2384db3006f3ec8a8cc654 |
actions/configure-pages | v6.0.0 | 45bfe0192ca1faeb007ade9deae92b16b8254a0d |
actions/upload-pages-artifact | v5.0.0 | fc324d3547104276b827a68afc52ff2a11cc49c9 |
actions/deploy-pages | v5.0.0 | cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 |
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
ghnever 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_ENABLEDand Pagesbuild_type=workflowjointly 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 concern | Exact page | Owner | Planned change |
|---|---|---|---|
| Root architecture | docs/src/architecture/index.md | deployment task | CI/deployment/GitHub-state trust boundaries |
| Root usage | docs/src/operations/index.md | enable task | Enablement, recovery, manual fallback |
| Root development | docs/src/development/index.md | validation task | Exact local/CI parity |
| Root reference | docs/src/reference/index.md | enable task | Workflows, task, variable, permissions, helper result |
| Generated development | skills/setup-project/template/docs/src/development/tooling.md.jinja | validation task | CI parity and workflow paths |
| Generated operations | skills/setup-project/template/docs/src/operations/github-pages.md.jinja | enable task | Enablement, recovery, fallback, URL |
| Generated reference | skills/setup-project/template/docs/src/reference/tooling.md.jinja | enable task | Sixth task, variable, workflow/permission contract, external gh |
| Generated navigation | skills/setup-project/template/docs/src/SUMMARY.md.jinja | enable task | Register GitHub Pages operations page |
| Roadmap | docs/src/planned-features.md | integration task | Mark implementation readiness |
| Implemented record | docs/src/features/github-validation-and-docs-deployment/index.md | lifecycle close-out | Delivery 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
- Validation workflow (
dstack-mol-41q.1): generate.github/workflows/validate.yml; own root/generated development docs, focused tests intests/test_github_validation.py, and shared exact-scaffold assertions caused by this file. - Deployment workflow (
dstack-mol-41q.2): after task 1, generate.github/workflows/docs.yml; own root architecture docs, focused tests intests/test_github_deployment.py, and its shared exact-scaffold assertion delta. - Enablement (
dstack-mol-41q.3): after task 2, add helper and sixth task; own root operations/reference, generated operations/reference/navigation, focused tests intests/test_github_enablement.py, and shared task/file assertions. - Integration (
dstack-mol-41q.4): after the other three, own remaining combined/update coverage intests/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.
ghis 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.
ghchanged 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
- Delivered Purposeful project scaffold/Universal project tooling/Language quality profiles records and current generated tooling contracts.
- Existing dstack validation workflows as repository patterns.
- GitHub Pages REST and custom workflow documentation: https://docs.github.com/en/rest/pages/pages and https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages.
- GitHub CLI manuals: https://cli.github.com/manual/gh_api, https://cli.github.com/manual/gh_repo_view, and https://cli.github.com/manual/gh_variable_set.
- Action tag commits verified from upstream Git refs on 2026-07-14.
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_messagewithout 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.Zsubject; - 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:
- use the hk built-in unchanged;
- use the built-in with the smallest necessary project-specific field override; or
- 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
otherprojects 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 concern | Exact page | Create or update | Planned change | Owning Beads task |
|---|---|---|---|---|
| Architecture | docs/src/architecture/index.md | Update | Native lock and customization boundary | dstack-mol-v8c.2 |
| Usage / Operations | Not applicable | — | Contributor behavior is development/reference material | — |
| Development | docs/src/development/index.md | Update incrementally | Harper behavior (.1), native policy (.2), validation matrix (.3) | tasks .1–.3 |
| Reference | docs/src/reference/index.md | Update incrementally | Harper contract (.1), exact custom steps/dependency exceptions (.2) | tasks .1–.2 |
| Generated Development | skills/setup-project/template/docs/src/development/tooling.md.jinja | Update incrementally | Harper behavior (.1) and native check/fix behavior (.2) | tasks .1–.2 |
| Generated Reference | skills/setup-project/template/docs/src/reference/tooling.md.jinja | Update incrementally | Harper contract (.1) and actual steps/justified ordering (.2) | tasks .1–.2 |
| Published Development | docs/src/development/tooling.md | Update incrementally | Keep dog-food contributor contract aligned with template changes | tasks .1–.2 |
| Published Reference | docs/src/reference/tooling.md | Update incrementally | Keep dog-food exact contract aligned with template changes | tasks .1–.2 |
| Planned navigation | docs/src/SUMMARY.md | Already updated | Design is registered under planned features | planning |
| Delivered navigation | docs/src/SUMMARY.md; docs/src/features/index.md | Update during close-out | Register the implemented feature in both delivered indexes | lifecycle close-out |
| Implemented Feature Record | docs/src/features/hk-policy-simplification/index.md | Create during close-out | Preserve delivery and audit history | lifecycle 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
dstack-mol-v8c.1: restore native Harper behavior, direct hook fixtures, and Harper-specific root/generated docs.dstack-mol-v8c.2: replace redundant custom steps, remove non-semantic dependencies, test each retained edge, and update native-policy root/generated docs.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:
| Class | Examples | Completion contract |
|---|---|---|
| Durable audit state | migration/workflow-migration.json, report, baseline, migration/legacy-tasks/*.md | Tracked and committed |
| Temporary reconciliation | migration/template-adoption-candidates/ | Removed before checkpoint |
| Conditional backup evidence | migration/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:
- a concise decision title;
- why migration needs the answer now;
- current authoritative evidence and uncertainty;
- the behavior or files the answer controls;
- one valid concrete example;
- available choices and a safe default when one exists;
- 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-
maindefault 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 concern | Exact page | Create or update | Planned change | Owning Beads task |
|---|---|---|---|---|
| Architecture | docs/src/architecture/index.md | Update | Additive adoption, repository identity, import transaction/resume, and hook-verification boundaries | tasks .8, .9, .5 |
| Usage / Operations | docs/src/operations/index.md | Update incrementally | Questions/artifacts/hooks (.1–.4), progress/retry (.7, .9), identity/adoption (.8), migration mode (.10) | tasks .1–.10; .5 reconciles |
| Development | docs/src/development/index.md | Update incrementally | Checkpoints (.4), large import/performance fixtures (.9), generated records/navigation (.10), integration (.5) | tasks .4, .9, .10, .5 |
| Reference | docs/src/reference/index.md | Update incrementally | Exact inventory/artifact/question/checkpoint/import-progress/identity/drafting commands, fields, states, and defaults | tasks .1–.10; .5 reconciles |
| Skill procedure | skills/migrate-workflow/SKILL.md | Update | Ordered gates, contextual questions, verified commits | tasks .1–.4 |
| Migration reference | skills/migrate-workflow/references/MIGRATION.md | Update | Detailed reconciliation, archive, and recovery procedures | tasks .1–.4 |
| Navigation | docs/src/SUMMARY.md | Update design markers | Register this design | planning |
| Implemented Feature Record | docs/src/features/migration-safety-and-clarity/index.md | Create during close-out | Preserve delivery and audit history | lifecycle 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 --writeand 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-
mainremote default branch; require explicit answers when ambiguous. - Verify exact stealth
.beadstracking, 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
dstack-mol-9zl.1: capture inventories/readiness, preserve byte-stable scans, guard additive hk reconciliation, and update its operations/reference sections.dstack-mol-9zl.2: classify artifacts, enforce backup disposition and durable tracking, and update its operations/reference sections.dstack-mol-9zl.3: standardize the reusable contextual-question checklist/examples and update its operations/reference sections.dstack-mol-9zl.4: provision the reconciled pinned hook, prohibit broad bypass, validate checkpoint hooks/targeted exceptions, and update development/operations/reference sections.dstack-mol-9zl.7: fix task-status precedence, preserve import audit/phase state, and expose remaining-work resume accounting.dstack-mol-9zl.8: make canonical project name/slug/default branch explicit or evidence-backed and reconcile stealth Beads tracking instructions.dstack-mol-9zl.9: batch large Beads imports, report progress, and prove interrupted retries scale with remaining work.dstack-mol-9zl.10: automate migration-safe validation, implemented-feature navigation, and review-required delivered record drafting.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-verifyfor 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-workflowagents 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
| Artifact | Lifecycle | Commit policy |
|---|---|---|
migration/baseline.json and migration/baseline.md | durable migration evidence | commit |
migration/workflow-migration.json and .md | durable migration state and report | commit |
migration/session-authority.json and resume approvals | durable authority audit | commit |
migration/legacy-tasks/ | durable legacy intent archive | commit |
migration/delivered-record-candidates/ | transient review workspace | never commit; remove after final verification |
migration/template-adoption-candidates/ and backup | conditional temporary reconciliation state | follow 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
draft-delivered-records --applywrites candidates undermigration/delivered-record-candidates/.- The agent reviews each candidate and promotes the actual implemented record. Candidate files remain available for review until final verification.
- Checkpoints stage only durable migration paths and promoted records. Commands must not use
git add -Awhen candidate files are present. finalize --applyperforms a preflight that every reviewed candidate path exists and still matches its recorded digest before it setsmigration_finalized. A missing or changed candidate fails finalization and leaves the migration unfinished. Finalization does not delete candidate files automatically.- After
finalize --applysucceeds andverify --beadsreports completion for a manifest withmigration_finalized: true, the user may explicitly authorize removal ofmigration/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. - 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_finalizedis 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_finalizedis 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 concern | Exact page | Change | Owner |
|---|---|---|---|
| Migration procedure | skills/migrate-workflow/SKILL.md | Mark delivered candidates transient, use explicit durable staging paths, and document post-verification deletion. | dstack-mol-u15.1 |
| Migration reference | skills/migrate-workflow/references/MIGRATION.md | Record artifact lifecycles, resume limits, and candidate deletion procedure. | dstack-mol-u15.1 |
| Operations | docs/src/operations/index.md | Clarify transient candidate material, explicit deletion authority, finalization boundary, and recovery. | dstack-mol-u15.1 |
| Migration reference | docs/src/reference/index.md | Distinguish delivered-record candidates from template candidates and document finalization, deletion, and redrafting. | dstack-mol-u15.1 |
| Verification tests | tests/test_migrate_legacy_workflow.py | Cover missing candidates before finalization, redrafting after loss, and finalized verification after deletion. | dstack-mol-u15.1 |
| Feature design navigation | docs/src/SUMMARY.md | Preserve the existing feature-design entry. | dstack-mol-u15.1 |
| Roadmap reconciliation | docs/src/planned-features.md | Update the feature from design to delivered only during close-out after delivery. | dstack-mol-42a |
| Implemented feature index | docs/src/features/index.md | Add the delivered record to the implemented-feature index during close-out. | dstack-mol-42a |
| Implemented SUMMARY navigation | docs/src/SUMMARY.md | Add the delivered record to the implemented-feature marker during close-out. | dstack-mol-42a |
| Delivered-record page | docs/src/features/migration-artifact-retirement/index.md | Create 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 checkvalidates 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
checkstill 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 andotherexclusivity.
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 concern | Exact page | Create or update | Planned change | Owning Beads task |
|---|---|---|---|---|
| Architecture | docs/src/architecture/index.md | Update | Root/package ownership and additive candidate boundary | .7, .9 reconciles |
| Usage | docs/src/operations/index.md | Update | Explicit inputs, preflight, Copier conflicts/recovery, candidate decisions | .6, .7, .9 |
| Development | docs/src/development/index.md | Update | mise evidence, package tasks, scale/recovery validation | .5, .8, .9 |
| Reference | docs/src/reference/index.md | Update | Exact answers, paths, states, commands, defaults, candidate fields | .5–.7, .9 |
| Generated layout reference | skills/setup-project/template/docs/src/reference/repository-layout.md.jinja | Create | Package map, ownership, tasks, full/changed scope | .7, .9 |
| Generated navigation | skills/setup-project/template/docs/src/SUMMARY.md.jinja | Update | Register layout reference only in monorepo mode | .7, .9 |
| Generated tooling docs | skills/setup-project/template/docs/src/development/tooling.md.jinja; skills/setup-project/template/docs/src/reference/tooling.md.jinja | Update | Package task and exact tooling contracts | .7, .9 |
| Skill procedures | skills/setup-project/SKILL.md; skills/update-project/SKILL.md | Update | Inputs, conversion, preflight, conflicts, recovery | .6, .7, .9 |
| Implemented Feature Record | docs/src/features/monorepo-tooling-layout/index.md | Create during close-out | Delivery evidence | lifecycle 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 checkvalidates 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
dstack-mol-5bq.5mise compatibility spike: timebox current official composition evidence and record the supported implementation path without changing the established ownership/task contract.dstack-mol-5bq.6layout contract: add the exact layout/package schema, path/name/profile validation, legacy-answer defaulting, explicit single-package conversion, and setup/update preflight.dstack-mol-5bq.7additive rendering: render one root tool/lock authority, package tasks, scoped pre-commit hk, Copier conflict/candidate behavior, and the Copier-owned repository-layout page.dstack-mol-5bq.8scale and update safety: add homogeneous/mixed/32-package matrices, full-check versus pre-commit scoping, conflict recovery, candidate preservation, and byte-idempotence tests.dstack-mol-5bq.9reader 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
- Universal project tooling
- Language quality profiles
- GitHub validation and docs deployment
- hk policy simplification
- Migration safety and clarity
- Migration artifact retirement
- Monorepo tooling layout
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
- Project overview
- Workflow architecture
- Install and use dstack
- Developing dstack
- Repository and command reference
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.
mainfast-forwarded to8a7e015d4e663e9f4ea3f670765f5cd3482ad790.
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.mddocs/src/architecture/index.mddocs/src/operations/index.mddocs/src/development/index.mddocs/src/reference/index.mddocs/src/planned-features.mddocs/src/features/index.mddocs/src/SUMMARY.mddocs/src/features/purposeful-project-scaffold/index.md
Audit Trail
- Specification reconciliation:
112d121, with roadmap readiness at353c8ce. - 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-a8iclosed 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.mddocs/src/operations/index.mddocs/src/development/index.mddocs/src/reference/index.mddocs/src/planned-features.mddocs/src/features/index.mddocs/src/SUMMARY.mddocs/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-b69closed 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, andgit 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.mddocs/src/operations/index.mddocs/src/development/index.mddocs/src/reference/index.mddocs/src/planned-features.mddocs/src/features/index.mddocs/src/SUMMARY.mddocs/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-9asclosed 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:enabletwice, then verify Pagesbuild_type=workflow,DOCS_DEPLOYMENT_ENABLED, andhtml_url): waived by the user for commitea6b558786b51cb1f07071913db50cea3f90b906. 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.mddocs/src/operations/index.mddocs/src/development/index.mddocs/src/reference/index.mddocs/src/planned-features.mddocs/src/features/index.mddocs/src/SUMMARY.mddocs/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-
ghenablement (dstack-mol-41q.3):ebbfe142b786d8a05028900cff234501e3027fac. - Combined profile/update integration (
dstack-mol-41q.4):ea6b558786b51cb1f07071913db50cea3f90b906. - Implementation coordinator
dstack-mol-41qclosed 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
- Workflow architecture
- Developing dstack
- Developer tooling
- Repository and command reference
- Generated tooling contract
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, andgit diff --checkpassed.- 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.mddocs/src/development/index.mddocs/src/development/tooling.mddocs/src/reference/index.mddocs/src/reference/tooling.mddocs/src/planned-features.mddocs/src/features/index.mddocs/src/SUMMARY.mddocs/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-v8cclosed 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
- Architecture
- Install and migration operations
- Development and validation
- Repository and migration command reference
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.mddocs/src/operations/index.mddocs/src/development/index.mddocs/src/reference/index.mddocs/src/features/migration-safety-and-clarity/design.mdskills/migrate-workflow/SKILL.mdskills/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
- Workflow architecture
- Migration operations
- Development and validation
- Repository and migration reference
skills/migrate-workflow/SKILL.mdskills/migrate-workflow/references/MIGRATION.md
Validation Evidence
mise run check: passed at implementation commit5b051f58ae92df543ee90d9cf8760bec2e495f8d.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.mddocs/src/operations/index.mddocs/src/reference/index.mdskills/migrate-workflow/SKILL.mdskills/migrate-workflow/references/MIGRATION.mddocs/src/features/migration-artifact-retirement/index.mddocs/src/features/index.mddocs/src/SUMMARY.mddocs/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
- Architecture
- Setup and update operations
- Development and scale evidence
- Repository-layout and mise reference
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.mddocs/src/operations/index.mddocs/src/development/index.mddocs/src/reference/index.mddocs/src/features/monorepo-tooling-layout/design.mdskills/setup-project/SKILL.mdskills/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.
