From 953d1656a4b0c344e70c66edbae64053bdf18667 Mon Sep 17 00:00:00 2001 From: Ramesh Padmanabhaiah Date: Wed, 27 May 2026 15:05:37 -0700 Subject: [PATCH] Document delegation-first manifest design --- README.md | 44 +++++++++++++++++++++++++++++--------------- TODO.md | 30 ++++++++++++++---------------- docs/design.md | 38 +++++++++++++++++++++++++++----------- 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index d5525e9..4ab4d4c 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,8 @@ Over time, each project repo can declare how Base should interact with it, likely through a small project manifest or well-defined conventions. The first version of that manifest is `base_manifest.yaml` at a project repo -root. It declares the project name and the project artifacts Base should manage: +root. It declares the project name and the project contracts Base should +orchestrate: ```yaml project: @@ -80,32 +81,45 @@ project: brewfile: Brewfile -artifacts: - - type: tool - name: terraform - version: latest +# Future contract; Base will delegate to mise rather than reimplementing it. +mise: .mise.toml +artifacts: - type: python-package name: requests version: latest + +# Future contract for `basectl test example`. +test: + command: pytest tests/ ``` -The manifest intentionally describes what the project needs, not how to install -it. Base owns the artifact registry and chooses the manager for each supported -`type` and `name` pair. Unknown artifacts fail setup clearly instead of running -arbitrary user-provided install commands. +The manifest intentionally describes what the project needs, not arbitrary +commands to execute. Base's direction is delegation-first: use mature tools for +the domains they already own, and keep Base responsible for workspace +orchestration, project discovery, the project virtual environment, and +diagnostics. The optional top-level `brewfile` field points to a Homebrew `Brewfile` relative to the project root. When present, `basectl setup` runs `brew bundle --file=/` before reconciling artifacts. Use -this for ordinary Homebrew formulae and casks; keep Base-aware dependencies in -`artifacts`. +this for ordinary Homebrew formulae and casks instead of adding every Homebrew +package to Base's hand-curated artifact registry. + +Future manifest fields should follow the same rule. A `mise` field should cause +Base to run `mise install` and later delegate task execution to `mise run` when a +project chooses that substrate. A `test` field should give `basectl test` a +single project-owned command to run. Base should not run arbitrary setup hooks +until there is an explicit, reviewable contract for when they run, where they +run, whether they are interactive, and how dry-run/check/doctor report them. The supported artifact registry lives in -`cli/python/base_setup/registry.py`. Today, `python-package` artifacts install -into the project virtual environment at `~/.base.d//.venv`. -Homebrew-managed `tool` artifacts currently support `version: latest`; pinned -Homebrew versions fail clearly until Base grows explicit versioned tool support. +`cli/python/base_setup/registry.py`. It should stay small and Base-aware. Today, +`python-package` artifacts install into the project virtual environment at +`~/.base.d//.venv`. Homebrew-managed `tool` artifacts currently support +`version: latest`, but ordinary Homebrew tools should move toward Brewfile +delegation. Pinned Homebrew versions fail clearly until Base grows explicit +versioned tool support. You can inspect the projects Base can see with: diff --git a/TODO.md b/TODO.md index c3688f8..8c04b8e 100644 --- a/TODO.md +++ b/TODO.md @@ -9,22 +9,6 @@ they are merged. ## P1 — Product Core And Composability -- [ ] Redesign project manifests around delegation-first orchestration. - - Goal: reduce the hand-curated artifact registry and make Base easier for - real projects to adopt. - - Expected design topics: - - Keep `brewfile: Brewfile` as the primary path for ordinary Homebrew - formulae and casks. - - Add first-class `mise` delegation when a project declares `.mise.toml` or - `mise.toml`. - - Consider a structured `python:` section for Base-managed venvs and Python - package requirements. - - Define a `test:` contract for future `basectl test `. - - Decide whether setup hooks belong in the manifest and what guardrails they - need. - - Constraint: preserve Base's safety stance; do not silently run arbitrary - project commands without a clear contract. - - [ ] Add first-class `mise` integration. - Goal: let Base orchestrate project tool versions and tasks without becoming a version manager. @@ -37,6 +21,20 @@ they are merged. - Expected behavior: delegate to the project's declared test command, `mise` task, or conventional runner while preserving Base logging and exit status. +- [ ] Consider a structured `python:` manifest section. + - Goal: make Base-managed Python environments clearer than encoding every + package as an artifact entry. + - Expected design topics: default project venv location, optional venv path + override, package requirement syntax, relationship to `requirements.txt`, + and migration from existing `python-package` artifacts. + +- [ ] Decide whether setup hooks belong in the manifest. + - Goal: preserve Base's safety stance while allowing real projects to perform + necessary post-setup work when delegation targets are not enough. + - Expected behavior: either define a constrained hook contract with explicit + timing, dry-run, interactivity, and diagnostics semantics, or document why + project-owned installers remain the right layer for hooks. + - [ ] Implement `basectl onboard`. - Goal: provide the guided checklist-style Base setup experience described in `docs/basectl-onboard.md`. diff --git a/docs/design.md b/docs/design.md index dc749f4..5a04823 100644 --- a/docs/design.md +++ b/docs/design.md @@ -313,7 +313,7 @@ project root. Base reads this manifest to know what to install and configure. File: `base_manifest.yaml` -Current structure: +Current and planned structure: ```yaml project: @@ -321,20 +321,35 @@ project: brewfile: Brewfile -artifacts: - - type: tool - name: terraform - version: latest +# Future contract; Base delegates to mise instead of reimplementing it. +mise: .mise.toml +artifacts: - type: python-package name: requests version: latest + +# Future contract for `basectl test myproject`. +test: + command: pytest tests/ ``` -The Python layer interprets this declarative manifest and translates each -artifact into concrete installation actions. Base owns the artifact registry and -chooses the manager for each supported `(type, name)` pair. The current registry -is `cli/python/base_setup/registry.py`. +The Python layer interprets this declarative manifest and translates it into +orchestration actions. The design rule is delegation-first: + +- Use Homebrew's own `Brewfile`/`brew bundle` flow for ordinary macOS packages. +- Use `mise` for tool versions, language runtimes, environment variables, and + tasks when a project opts into it. +- Use a project-owned `test` contract for future `basectl test ` + delegation. +- Let Base own the project virtual environment and Base-aware package + reconciliation. +- Do not run arbitrary project setup hooks until Base has a clear safety + contract for execution timing, dry-run behavior, interactivity, and + diagnostics. + +Base owns the artifact registry only for things it must manage directly. The +current registry is `cli/python/base_setup/registry.py`. The optional top-level `brewfile` field delegates ordinary Homebrew dependencies to Homebrew's native `brew bundle` flow. The path is relative to the project root @@ -348,8 +363,9 @@ through that project-scoped venv. Homebrew-managed `tool` artifacts currently support `version: latest`. If a project requests a pinned Homebrew version, setup fails clearly instead of -silently installing a different version. Richer version conflict handling across -projects is a later iteration, not part of the initial build. +silently installing a different version. New ordinary Homebrew tools should +prefer Brewfile delegation over registry growth. Richer version conflict +handling across projects is a later iteration, not part of the initial build. Artifact install commands keep stdout attached to the terminal so long-running tools such as `brew` and `pip` remain live and readable while setup runs. Base's