Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
8 changes: 6 additions & 2 deletions .github/workflows/pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,11 @@ jobs:
id: test-policy
run: |
set -euo pipefail
uv run --frozen python ls/tools/localsetup.py --source-root . test-workers --json > /tmp/localsetup-test-policy.json
# Admit as many shard jobs as this runner has available logical CPUs,
# up to the configured shard count. Each job uses its own CPU budget.
uv run --frozen python ls/tools/localsetup.py --source-root . test-workers --workers "$(nproc)" --json > /tmp/localsetup-test-policy.json
policy="$(python -c 'import json,sys; print(json.dumps(json.load(open(sys.argv[1])),separators=(",",":")))' /tmp/localsetup-test-policy.json)"
printf '%s\n' "$policy"
echo "json=$policy" >> "$GITHUB_OUTPUT"

- name: Verify framework context
Expand Down Expand Up @@ -277,6 +280,7 @@ jobs:
- name: Run pytest
env:
CANDIDATE_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
LOCALSETUP_TEST_WORKERS: ${{ fromJSON(needs.framework-prerequisites.outputs.test_policy).workers_per_shard }}
run: |
set -euo pipefail
test "$(git rev-parse HEAD)" = "$CANDIDATE_SHA"
Expand All @@ -286,7 +290,7 @@ jobs:
export DBUS_SESSION_BUS_ADDRESS="unix:path=$XDG_RUNTIME_DIR/bus"
sudo systemctl start "user@$(id -u).service"
systemctl --user show-environment >/dev/null
uv run --frozen --group s3-sdk pytest -n 1 ls/tests -q \
uv run --frozen --group s3-sdk pytest -n "$(nproc)" ls/tests -q \
--ci-shard=${{ matrix.shard }} --ci-shards=${{ fromJSON(needs.framework-prerequisites.outputs.test_policy).shard_count }} \
--maxfail=1 --durations=20

Expand Down
19 changes: 16 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ Do not impose an arbitrary length cap on this file. In particular, do not trim i

Keep this file aligned with the repo's actual workflow. If a rule also belongs in installed Codex context for future converted repos, mirror the portable part into `ls/templates/codex/AGENTS.md`. If the rule is only for this checkout, keep it here.

## Repository demo and presentation assets

Use the dedicated `localsetup` CDN bucket for this repository's approved public
demo videos, previews, and similar presentation assets. Keep source masters and
working files in the Git-ignored `.agents/state/demo-library/`. Publish only
reviewed assets, use descriptive versioned object paths, and verify anonymous
access and returned bytes before linking them from documentation. Keep the
shared `default` bucket private and preserve its existing access controls.
Use `https://cdn.cruxexperts.com` for this CDN's authenticated S3 endpoint and
verified public links. The GS Garage endpoint is a separate local service and
must not be used for this repository's public demo assets.

## Founding Principle: Eliminate Friction and Ambiguity

LocalSetup should make work simpler and clearer. Prefer updating the existing owner of a behavior, document, workflow, tool, or check. Add a new one only when a concrete requirement cannot be met by improving existing material; keep any addition small and state the gap it fills. Add gates and process steps only for a specific safety, correctness, or acceptance need. This is the framework's [founding workflow design principle](ls/docs/WORKFLOW_STANDARD.md#founding-design-principle). Follow the scoped verification policy under [Testing Guidelines](#testing-guidelines) and [Unit-Test Concurrency Policy](#unit-test-concurrency-policy).
Expand Down Expand Up @@ -332,8 +344,9 @@ execution environment remain applicable; changed inputs invalidate that proof.

Run cheap audit, catalog, version, and documentation checks before expensive
validation. Hosted Python validation partitions all collected cases across the
configured shards, with one worker per active shard. The resolved aggregate
budget limits concurrent shards; remaining shards queue. Each shard stops
configured shards. Each isolated runner uses its available logical CPUs for its
shard's guarded worker pool; the resolved `max_parallel` limit controls how many
shard jobs run at once. Remaining shards queue. Each shard stops
on its first failure, reports slow cases, and has a 60-minute job deadline. A
failed or empty shard cannot satisfy the aggregate check. Rerun failed jobs after
an understood transient failure; do not restart successful jobs without a reason.
Expand Down Expand Up @@ -385,7 +398,7 @@ On resume, recalculate the budget from currently available CPUs. Inspect inherit
worker overrides and do not carry forward a stale lower setting when the user
requests the full formula-based budget.

The default aggregate test-worker budget is `max(1, floor(available logical CPU cores / 3))`. A configured positive integer override may increase or decrease that budget, with a hard cap of available logical CPUs and a tighter physical-memory capacity. Resolve and enforce the budget in code from selected configuration; agents and users edit settings, not scheduling calculations. Hosted partitions queue within that budget; local queues follow the active worker count. Concurrent test processes share the budget; they must not each claim it. Preserve stricter native execution limits.
The default aggregate test-worker budget is `max(1, floor(available logical CPU cores / 3))`. A configured positive integer override may increase or decrease that budget, with a hard cap of available logical CPUs and a tighter physical-memory capacity. Resolve and enforce the budget in code from selected configuration; agents and users edit settings, not scheduling calculations. Hosted jobs have isolated runner budgets: each shard's worker pool is capped by that runner's available CPUs and memory, while the matrix concurrency limit bounds active jobs. Local queues follow the active worker count. Concurrent test processes on the same host share its budget; they must not each claim it. Preserve stricter native execution limits.

Test effort must be proportional to risk. For tiny docs, policy, metadata, or one-line behavior changes, prefer static checks such as `git diff --check`, targeted syntax checks, or no test run when there is no executable surface. Do not add broad or repetitive tests merely to increase evidence. Add tests only for behavior that can realistically regress, and keep test code smaller than the implementation unless the behavior is safety-critical or has multiple important edge cases. Run the smallest relevant validation first; broaden only after focused checks pass or when the affected surface justifies it.

Expand Down
30 changes: 19 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ AI is a tool. Expertise determines what it multiplies. LocalSetup brings enginee

[Read the complete story](ls/docs/WHY_LOCALSETUP.md) · [Explore the capabilities](ls/docs/FEATURES.md) · [Understand the security boundaries](SECURITY.md)

## See LocalSetup in action

Watch a Codex session work through a simulated coding task while LocalSetup's
terminal companion shows commands, results, and layout controls. The full demo
is silent and runs for about six minutes.

[![Animated preview of the LocalSetup terminal companion](https://cdn.cruxexperts.com/localsetup/demos/codex-observer-b8b5a3e9a5cf/preview.gif)](https://cdn.cruxexperts.com/localsetup/demos/codex-observer-b8b5a3e9a5cf/demo.mp4)

[Watch the full demo](https://cdn.cruxexperts.com/localsetup/demos/codex-observer-b8b5a3e9a5cf/demo.mp4).

## An operating layer around your tools

**Carry your context forward.** Keep project instructions, architectural decisions, and engineering standards in reviewable files. Reuse them across projects and supported clients instead of reconstructing them for each conversation.
Expand All @@ -38,7 +48,7 @@ AI is a tool. Expertise determines what it multiplies. LocalSetup brings enginee
<!-- facts-block:start -->
| Fact | Value |
|---|---|
| Current version | `4.89.4` |
| Current version | `4.89.8` |
| Supported platforms | `codex, claude-code, cursor, kilo, opencode, openclaw, github-copilot-cli, github-copilot-vscode, cline-cli, cline-vscode, amp-cli, goose-cli, pi-cli, hermes-agent, qwen-code-cli, kimi-cli, factory-droid, antigravity-app, gemini-cli, omp-cli` |
| Shipped skills | `115` |
| Workflow packages | `21` |
Expand Down Expand Up @@ -91,21 +101,19 @@ The guided installer explains the options, lets you select packages and supporte
<details>
<summary>Release included in this checkout</summary>

**Version:** 4.89.4<br>
**Version:** 4.89.8<br>

<!-- release-summary:start -->
## What's new in 4.89.4
## What's new in 4.89.8

LocalSetup 4.89.4 makes agent work easier to observe, preserves independently owned skills, and adapts test execution to resource pressure while keeping terminal operations under explicit owner control.
LocalSetup 4.89.8 adds an animated README preview and full recorded demo on the dedicated public CDN, and uses the available runner CPUs for parallel CI shards.

- **Follow native agent activity:** an owned terminal view shows bounded item metadata and operation state, with guarded recovery after transient read failures and an explicit history-gap signal.
- **Keep terminal work under its owner:** managed shell operations retain process and session identity, private input remains operation-bound, and failures provide actionable feedback without granting new authority.
- **Use independently owned skills:** select repository, personal, or framework origins explicitly; recorded snapshots and collision checks protect custom source during install, update, and rollback.
- **See test pressure and progress:** the shared worker policy adapts to memory headroom and exposes versioned telemetry while the protected test scope retains its resource limits.
- **Rejoin the right shell state:** attach, logs, input, and family instructions retain an explicitly selected private state root, including safely quoted paths in older status layouts.
- **Find the practical starting point:** the homepage and framework guides lead with visible operations, privacy, and concrete engineering workflows, with detailed mechanisms in linked references.
- **See LocalSetup in action:** the README shows a 15-second animated preview that links to a silent, six-minute Codex session demonstrating visible commands, results, and layout controls.
- **Keep demo media separate:** reviewed, versioned public assets use the dedicated LocalSetup CDN bucket while the shared system bucket stays private.
- **Use available CI capacity:** each hosted shard uses its runner's available logical CPUs, while the matrix schedules concurrent shard jobs up to its configured limit.
- **Respect Git discovery boundaries:** a malformed Git file beyond a filesystem boundary does not prevent client state from using its global location, while malformed markers inside the boundary still fail closed.

See the [4.89.4 release guide](ls/docs/releases/4.89.4.md) for compatibility, updating, and verification.
See the [4.89.8 release guide](ls/docs/releases/4.89.8.md) for compatibility, updating, and verification.
<!-- release-summary:end -->

</details>
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.89.4
4.89.8
4 changes: 2 additions & 2 deletions ls/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# LocalSetup Framework Engine

**Version:** 4.89.4<br>
**Version:** 4.89.8<br>

`ls/` is the engine that makes the public LocalSetup promise real. It stores the framework code, shipped skills, workflow packages, platform templates, docs, tests, and install manifests that turn a repository into a portable agent workspace.

Expand All @@ -26,7 +26,7 @@ For the public product overview, start with the [root README](../README.md). Thi
LocalSetup-managed entries in consuming repositories are install output. Adapter directories may also contain project-owned skills, files, and symlinks; preserve that content in place. See [adapter ownership](docs/ADAPTER_OWNERSHIP.md).

<!-- release-link:start -->
Read the [current release guide](docs/releases/4.89.4.md) for LocalSetup 4.89.4, including compatibility, updating, and verification. Find downloads in the [latest published release](https://github.com/CruxExperts/localsetup/releases/latest).
Read the [current release guide](docs/releases/4.89.8.md) for LocalSetup 4.89.8, including compatibility, updating, and verification. Find downloads in the [latest published release](https://github.com/CruxExperts/localsetup/releases/latest).
<!-- release-link:end -->

## Install flow
Expand Down
2 changes: 1 addition & 1 deletion ls/core/client_state/locator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .models import ClientStateError, GitContext, StateLocation


_NOT_REPOSITORY = ("not a git repository", "outside repository")
_NOT_REPOSITORY = ("not a git repository", "outside repository", "invalid gitfile format")
_STATE_CHILD = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")


Expand Down
2 changes: 0 additions & 2 deletions ls/core/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ def _configure_test_workers(config):
override = requested if type(requested) is int else None
workers = resolved_test_workers(override, project_root=project_root(config))
config.option.numprocesses = workers
if config.getoption("ci_shards") > 1:
config.option.numprocesses = 1
config.option.dist = "load"
except ValueError as exc:
raise pytest.UsageError(str(exc)) from exc
Expand Down
8 changes: 5 additions & 3 deletions ls/core/test_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import sys
import uuid

from .test_workers import default_test_workers, testing_configuration, resolved_test_workers
from .test_workers import TEST_WORKERS_ENV, testing_configuration, resolved_test_workers
from .test_pressure import host_memory, host_reserve
from .test_telemetry import Telemetry

Expand Down Expand Up @@ -50,7 +50,8 @@ def resource_budget(project_root: Path | None = None) -> dict[str, int]:
min(values["MemTotal"], values["MemAvailable"]) * fraction // 100)
memory = min(memory, values["MemTotal"] * policy.get("physical_memory_percent", 95) // 100,
max(0, values["MemAvailable"] - host_reserve(values, policy)))
cpu_percent = default_test_workers() * 100
cpu_percent = resolved_test_workers(project_root=project_root) * 100
explicit_workers = (TEST_WORKERS_ENV in os.environ or policy.get("workers", "auto") != "auto")
# Respect tighter enclosing cgroups, including hosted/container runners.
directory = cgroup_directory()
while directory != Path("/sys/fs"):
Expand All @@ -64,7 +65,8 @@ def resource_budget(project_root: Path | None = None) -> dict[str, int]:
if cpu_file.is_file():
quota, period = cpu_file.read_text().split()
if quota != "max":
cpu_percent = min(cpu_percent, max(1, int(quota) * 100 // int(period) // 3))
parent_percent = max(1, int(quota) * 100 // int(period))
cpu_percent = min(cpu_percent, parent_percent if explicit_workers else max(1, parent_percent // 3))
if directory == Path("/sys/fs/cgroup"):
break
if directory.parent == directory:
Expand Down
2 changes: 1 addition & 1 deletion ls/core/test_workers.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def test_workers_payload(
"configured_workers": configured["workers"] if configured is not None else None,
"shard_count": shard_count,
"shard_indices": list(range(shard_count)) if shard_count is not None else [],
"workers_per_shard": 1 if shard_count is not None else None,
"workers_per_shard": workers if shard_count is not None else None,
"max_parallel": min(workers, shard_count) if shard_count is not None else workers,
"adaptive": configured.get("adaptive") if configured else None,
"local_queue_slots": workers,
Expand Down
2 changes: 1 addition & 1 deletion ls/docs/COMMAND_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,7 @@ localsetup test-workers --status --json
localsetup test-workers --watch
```

The common `testing` section owns `workers` (`"auto"` or a positive integer) and `shard_count` (1–32), with legacy `[tool.localsetup.testing]` as a fallback. Auto resolves to `max(1, floor(available logical CPU cores / 3))`; an explicit value is capped at available logical cores and execution is further constrained by memory. `--workers` takes precedence over `LOCALSETUP_TEST_WORKERS`, which takes precedence over the project setting. JSON includes stable hosted CI partitions and their aggregate concurrency. The command reads `--target-directory` or `--repo` when supplied, otherwise the current project directory; the installed framework source is not substituted for that project.
The common `testing` section owns `workers` (`"auto"` or a positive integer) and `shard_count` (1–32), with legacy `[tool.localsetup.testing]` as a fallback. Auto resolves to `max(1, floor(available logical CPU cores / 3))`; an explicit value is capped at available logical cores and execution is further constrained by memory. `--workers` takes precedence over `LOCALSETUP_TEST_WORKERS`, which takes precedence over the project setting. JSON includes stable hosted CI partitions, the per-runner worker request, and matrix job concurrency. Each isolated CI runner enforces its own CPU and memory limits; local concurrent runs share one guarded host budget. The command reads `--target-directory` or `--repo` when supplied, otherwise the current project directory; the installed framework source is not substituted for that project.

In this repository, plain `pytest ls/tests -q` loads the shared plugin. Local
execution has one queue per active worker; pending work is redistributed when
Expand Down
2 changes: 1 addition & 1 deletion ls/docs/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ implemented controls and prerequisites.
## Generated Facts

<!-- facts-block:start -->
- Current version: `4.89.4`
- Current version: `4.89.8`
- Supported platforms: `codex, claude-code, cursor, kilo, opencode, openclaw, github-copilot-cli, github-copilot-vscode, cline-cli, cline-vscode, amp-cli, goose-cli, pi-cli, hermes-agent, qwen-code-cli, kimi-cli, factory-droid, antigravity-app, gemini-cli, omp-cli`
- Shipped skills: `115`
- Workflow packages: `21`
Expand Down
4 changes: 2 additions & 2 deletions ls/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ This is the public documentation map for LocalSetup. Start here when you want th
## Generated Facts

<!-- facts-block:start -->
- Current version: `4.89.4`
- Current version: `4.89.8`
- Supported platforms: `codex, claude-code, cursor, kilo, opencode, openclaw, github-copilot-cli, github-copilot-vscode, cline-cli, cline-vscode, amp-cli, goose-cli, pi-cli, hermes-agent, qwen-code-cli, kimi-cli, factory-droid, antigravity-app, gemini-cli, omp-cli`
- Shipped skills: `115`
- Workflow packages: `21`
Expand Down Expand Up @@ -55,7 +55,7 @@ This is the public documentation map for LocalSetup. Start here when you want th
| [Harness automation](HARNESS_AUTOMATION.md) | Opt-in heartbeat activation, typed LSCli profiles, reserved actions/controller accounting, runtime artifacts, cron gating and command-policy boundaries. |

<!-- release-link:start -->
Read the [current release guide](releases/4.89.4.md) for LocalSetup 4.89.4, including compatibility, updating, and verification. Find downloads in the [latest published release](https://github.com/CruxExperts/localsetup/releases/latest).
Read the [current release guide](releases/4.89.8.md) for LocalSetup 4.89.8, including compatibility, updating, and verification. Find downloads in the [latest published release](https://github.com/CruxExperts/localsetup/releases/latest).
<!-- release-link:end -->

The [4.4.0 guide](releases/4.4.0.md) covers the earlier context and package consolidation.
Expand Down
Loading
Loading