Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,40 +72,54 @@ 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:
name: example

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=<project-root>/<brewfile>` 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/<project>/.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/<project>/.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:

Expand Down
30 changes: 14 additions & 16 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <project>`.
- 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.
Expand All @@ -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`.
Expand Down
38 changes: 27 additions & 11 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,28 +313,43 @@ 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:
name: myproject

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 <project>`
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
Expand All @@ -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
Expand Down
Loading