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
13 changes: 8 additions & 5 deletions .envrc
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ watch_file mise.lock
PROJECT_ROOT="$(find_up pyproject.toml)"
PROJECT_ROOT="${PROJECT_ROOT%/*}"
# A nested standalone checkout never inherits an enclosing repository's tools.
# Attached members retain their declared workspace runtime boundary.
runtime_parent="$(cd "${PROJECT_ROOT}/./.." && pwd -P)"
# A member checked out as a submodule shares its Git superproject runtime, the
# same root its Makefile resolves (flext-x8gn6).
RUNTIME_ROOT="$(git -C "${PROJECT_ROOT}" rev-parse --show-superproject-working-tree)"
RUNTIME_ROOT="${RUNTIME_ROOT:-${PROJECT_ROOT}}"
runtime_parent="$(cd "${RUNTIME_ROOT}/.." && pwd -P)"
export GIT_CEILING_DIRECTORIES="${runtime_parent}"
export MISE_CEILING_PATHS="${runtime_parent}"
VENV_DIR="${PROJECT_ROOT}/.venv"
VENV_DIR="${RUNTIME_ROOT}/.venv"
PROJECT_STATE_ROOT="${PROJECT_ROOT%/*}/.flext-runtime/${PROJECT_ROOT##*/}"
# Scratch never lives inside a versioned tree: the home scratch root mirrors
# the absolute checkout path so a sandbox is never a tracked scope of any
Expand Down Expand Up @@ -126,8 +129,8 @@ if env -i \
'MISE_GITHUB_OAUTH_CLIENT_ID=' \
'MISE_GITHUB_OAUTH_EXPORT_ENV=' \
'MISE_GITHUB_OAUTH_OPEN_BROWSER=false' \
'MISE_LOCKFILE=false' \
'MISE_LOCKED=false' \
'MISE_LOCKFILE=true' \
'MISE_LOCKED=true' \
'MISE_LOCKFILE_PLATFORMS=linux-x64,linux-arm64,macos-x64,macos-arm64,windows-x64' \
"HOME=${scratch}/home" \
"USERPROFILE=${scratch}/home" \
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ jobs:
run: |
CI=Y make gen
git status --short
test -z "$(git status --porcelain --untracked-files=all)"
test -z "$(git status --porcelain --untracked-files=all --ignore-submodules=none)"

# Setup installs frozen from the committed uv.lock (`uv sync --locked`)
# and never rewrites it; the deps audit proves that locked graph.
Expand All @@ -168,7 +168,7 @@ jobs:
- name: Candidate cleanliness (blocking)
run: |
git status --short
test -z "$(git status --porcelain --untracked-files=all)"
test -z "$(git status --porcelain --untracked-files=all --ignore-submodules=none)"
# End SECTION: ci job

# === SECTION: release-plan job (managed) ===
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
*/.hooks.json.agents-governance.json
.claude/*.agents-governance.json
.gemini/*.agents-governance.json
.claude/settings.json
.claude/settings.local.json
.gemini/settings.json

# Operator-private local config overrides
/config/codegen-overrides.local.yaml
Expand Down
6 changes: 3 additions & 3 deletions .mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
# === SECTION: settings (managed) ===
# Source: config:codegen.toolchain.mise_lockfile / mise_locked / mise_lockfile_platforms
[settings]
lockfile = false
locked = false
lockfile = true
locked = true
lockfile_platforms = ["linux-x64", "linux-arm64", "macos-x64", "macos-arm64", "windows-x64"]
[tool_config]
locked = false
locked = true
# End SECTION: settings

# === SECTION: tools (managed) ===
Expand Down
54 changes: 42 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ TESTMON_DATAFILE := $(PROJECT_STATE_ROOT)/testmon/.testmondata
export TESTMON_DATAFILE
# === SECTION: REPOSITORY_ROOT isolation (managed) ===
# Source: physical checkout topology; caller variables cannot select a workspace.
ifneq ($(filter standalone,$(MAKE_PROFILE))$(GEN_INIT_ONLY),)
# Operator law 2026-09-24 (flext-x8gn6): inside a workspace every make run, root
# or member, uses the workspace runtime. A member resolves the Git superproject
# that checks it out as a submodule; a checkout without one (a standalone clone,
# a linked worktree) owns its runtime.
ifneq ($(GEN_INIT_ONLY),)
override REPOSITORY_ROOT := $(MAKEFILE_ROOT)
else
override REPOSITORY_ROOT := $(shell cd "$(MAKEFILE_ROOT)" && root=$$(git rev-parse --show-superproject-working-tree) && if [ -n "$$root" ]; then cd "$$root" && pwd -P; else pwd -P; fi)
Expand Down Expand Up @@ -241,6 +245,7 @@ _bootstrap_setup_tools:
caller_xdg_data_home="$$caller_home/.local/share"; \
fi; \
caller_path="$$PATH"; \
mise_lockfile_platforms="linux-x64,linux-arm64,macos-x64,macos-arm64,windows-x64"; \
caller_comspec="$${COMSPEC:-}"; \
caller_pathext="$${PATHEXT:-}"; \
caller_systemroot="$${SYSTEMROOT:-}"; \
Expand Down Expand Up @@ -370,9 +375,9 @@ mise_exec() { \
'MISE_GITHUB_OAUTH_CLIENT_ID=' \
'MISE_GITHUB_OAUTH_EXPORT_ENV=' \
'MISE_GITHUB_OAUTH_OPEN_BROWSER=false' \
'MISE_LOCKFILE=false' \
'MISE_LOCKED=false' \
'MISE_LOCKFILE_PLATFORMS=linux-x64,linux-arm64,macos-x64,macos-arm64,windows-x64' \
'MISE_LOCKFILE=true' \
'MISE_LOCKED=true' \
$${mise_lockfile_platforms:+"MISE_LOCKFILE_PLATFORMS=$$mise_lockfile_platforms"} \
"HOME=$$scratch/home" \
"USERPROFILE=$$scratch/home" \
"APPDATA=$$scratch/appdata" \
Expand Down Expand Up @@ -458,17 +463,16 @@ $${mise_config_argument:+"$$mise_config_argument"} \
fi; \
caller_mise_version="$$runtime_release"; \
printf 'mise setup receipt=%s storage=%s\n' "$$runtime_release" "$$mise_storage_root"; \
# Only ``upg`` resolves: it re-resolves every ``latest`` selector and the \
# Python minor line into mise.lock, with download URLs and checksums. \
# Only ``upg`` resolves. Artifact tools own a five-platform URL/checksum \
# matrix; npm owns one platform-independent Aube dependency graph. \
if [ "$(TOOL_BOOTSTRAP_RESOLVE)" = "1" ]; then \
mise_checked "$$scratch/lock.log" mise_exec project "$$latest_mise" -C "$$project_root" lock --bump; \
mise_checked "$$scratch/lock-artifacts.log" mise_exec project "$$latest_mise" -C "$$project_root" lock --bump python uv kubectl helm kind direnv taplo ast-grep gitleaks "aqua:boyter/scc" kubeconform node go make "github:qltysh/qlty" "github:kucherenko/jscpd" "github:microsoft/waza"; \
mise_lockfile_platforms=; \
mise_checked "$$scratch/lock-npm-prettier.log" mise_exec project "$$latest_mise" -C "$$project_root" lock --bump "npm:prettier"; \
mise_lockfile_platforms="linux-x64,linux-arm64,macos-x64,macos-arm64,windows-x64"; \
fi; \
# ``locked`` mode installs exactly what the committed mise.lock pins. \
mise_checked "$$scratch/install.log" mise_exec project "$$latest_mise" -C "$$project_root" install --yes; \
# ``mise install`` may reuse an installed fuzzy match. Upgrade Python inside \
# the configured minor line so ``python = \"3.13\"`` always resolves the \
# newest available 3.13 patch without rewriting the project selector. \
mise_checked "$$scratch/python-upgrade.log" mise_exec project "$$latest_mise" -C "$$project_root" upgrade --no-prune python; \
mise_checked "$$scratch/uv-version.log" mise_exec project "$$latest_mise" -C "$$project_root" exec -- uv --version; \
uv_output=$$(cat "$$scratch/uv-version.log"); \
case "$$uv_output" in \
Expand Down Expand Up @@ -1093,6 +1097,11 @@ _builtin_setup_submodules:
done

.PHONY: _builtin_require_github_auth
# The credential check precedes the Mise pin check even under -j. `make setup`
# first runs on the host's make before Mise installs the declared one, so the
# ordering uses .NOTPARALLEL (every GNU Make; 4.4+ serializes only this target's
# prerequisites) instead of .WAIT, which older releases read as a missing target.
.NOTPARALLEL: _bootstrap_setup_tools
_bootstrap_setup_tools: _builtin_require_github_auth $(if $(filter upg,$(MAKECMDGOALS)),,_builtin_require_mise_pin)
_builtin_require_github_auth:
@if [ "$(GITHUB_CREDENTIAL_READ_STATUS)" != "0" ]; then \
Expand Down Expand Up @@ -1152,12 +1161,21 @@ endif
# `upg` is the only recipe that resolves: the bootstrap above bumps mise.lock
# before installing, and this lifecycle upgrades every uv.lock, provisions the
# environment frozen from the new locks, and conforms dependency floors.
# The floors land in the codegen SSOT, so `gen` projects them into every
# pyproject and the locks are re-resolved against those raised floors before
# the frozen reprovision: the committed lock must match the committed
# pyproject, or `setup --locked` (the CI path) rejects it.
# Branch-tracked git dependencies are moving sources by declaration
# (workspace.yaml owns the branch): --refresh re-reads their metadata so a
# stale cached requires-dist can never block or skew the resolution
# (flext-62fbu).
# (flext-62fbu). Like `setup`, it runs the declared pre-/post-upg lifecycle
# hooks, post-upg inside the activated environment.
.PHONY: _upg_lifecycle
_upg_lifecycle: _builtin_setup_submodules
@set -eu; \
case " $(CUSTOM_DECLARED_TARGETS) " in \
*" pre-upg "*) $(SELF_MAKE) pre-upg ;; \
esac
$(call _run_for_all_projects,--upgrade --refresh)
@$(SELF_MAKE) _builtin_setup_environment
@set -eu; \
Expand All @@ -1167,7 +1185,19 @@ _upg_lifecycle: _builtin_setup_submodules
for project in $$selected; do set -- "$$@" --projects "$$project"; done; \
$(PROJECT_FLEXT_INFRA) deps modernize --repository-root "$(PROJECT_ROOT)" \
--apply --rewrite-constraints "$$@"
@$(SELF_MAKE) gen
$(call _run_for_all_projects,)
@$(SELF_MAKE) _builtin_setup_environment
$(call _run_for_all_projects,--check)
+@XDG_DATA_HOME="$${SETUP_DIRENV_XDG_DATA_HOME:?missing persistent direnv data home}" \
"$${SETUP_DIRENV:?missing Mise-resolved direnv executable}" exec "$(PROJECT_ROOT)" $(SELF_MAKE) _upg_activated

.PHONY: _upg_activated
_upg_activated:
@set -eu; \
case " $(CUSTOM_DECLARED_TARGETS) " in \
*" post-upg "*) $(SELF_MAKE) post-upg ;; \
esac


# _builtin-self-* targets serve the workspace root itself (project selector
Expand Down
32 changes: 16 additions & 16 deletions mise.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 5 additions & 9 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading