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
32 changes: 30 additions & 2 deletions .localsetup-release.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
{
"schema_version": 1,
"schema_version": 2,
"policy": "sequential-logical-slices",
"anchor": {
"commit": "51fbdf7c94f1f6087ecc69a99cf4d037a0c76117",
"version": "5.6.2",
"tag": "v5.6.2"
},
"overrides": [],
"policy": "sequential-logical-slices"
"major_line": 4,
"reconciliation": {
"original_anchor": {
"commit": "6c2d34ec897ccfad1c5038457b02cdbb7f0f7701",
"version": "4.22.9",
"tag": "v4.22.9"
},
"published_anchor": {
"commit": "51fbdf7c94f1f6087ecc69a99cf4d037a0c76117",
"version": "5.6.2",
"tag": "v5.6.2"
},
"cutoff": {
"commit": "8ed6e80d488010fad9e6b79f3f2bf69628f61c6e",
"source_version": "5.7.1",
"corrected_version": "4.44.1"
},
"reclassified_slices": [
{
"slice": "issue-100-verified-consumer-migration",
"classification": "minor",
"commits": [
"442f308690b62d1548daa5e197ec1d036e52cc3b",
"fdca87241f91b597152297042c8c6fb366272545"
]
}
]
}
}
16 changes: 15 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,25 @@ Starting at the last verified published version, apply logical accepted slices
in integration ancestry order: each independently accepted user-visible feature
increments MINOR once and resets PATCH to zero; each small fix, documentation
consolidation, or maintenance slice increments PATCH once. Breaking changes need
an explicit compatibility decision and appropriate MAJOR treatment. Count a
an explicit compatibility decision and appropriate MAJOR treatment unless an
active major-line lock blocks that release; while locked, restore compatibility
or stop release work until the lock is explicitly amended. Count a
slice's final accepted outcome once, not its fixups, merges, generated receipts,
release syncs, or work already published. Record the deterministic mapping from
logical slice to source commit, classification, and resulting version.

The corrected 4.x release line is explicitly major-locked: accepted releases may
increment MINOR or PATCH only, with no automatic or implicit MAJOR increment.
Reject any prospective MAJOR classification while this lock is active; do not
silently downgrade it. The one-time numbering reconciliation preserves published
v5.6.2 and its tag/assets as immutable while mapping its content to corrected
arithmetic 4.43.2 after the exact historical issue-100 MAJOR-to-MINOR
reconciliation. Branding maps to 4.44.0, and canonical repository-name policy
maps to 4.44.1. As of this reconciliation, 4.44.1 is not published or current.
The SDK paging and Agent Q v2/envelope compatibility breaks remain; corrected
numbering does not restore source or protocol compatibility, and 4.44.1 release
guidance must disclose both breaks clearly.

Use canonical version/release tooling and preserve source/receipt semantics.
If tooling cannot represent this sequence, implement and validate the missing
policy before publication; never hand-edit generated versions or weaken gates.
Expand Down
19 changes: 9 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<a href="ls/docs/PLATFORM_REGISTRY.md"><img src="https://img.shields.io/badge/platforms-cursor%20%7C%20claude--code%20%7C%20codex%20%7C%20openclaw%20%7C%20kilo%20%7C%20opencode-1f6feb" alt="Supported platforms"></a>
</p>

**Version:** 5.7.1<br>
**Version:** 4.44.1<br>

**LocalSetup gives coding agents a repo-local operating layer.**

Expand All @@ -25,16 +25,15 @@ LocalSetup provides capability skills, executable workflow packages, explicit ad
Start with the [quickstart](ls/docs/QUICKSTART.md) or browse the [documentation](ls/docs/README.md). The [latest published release](https://github.com/CruxExperts/localsetup/releases/latest) provides release notes and downloads.

<!-- release-summary:start -->
## What's new in 5.7.1
## What's new in 4.44.1

LocalSetup 5.7.1 gives its GitHub documentation a consistent light and dark visual identity and clarifies the canonical repository name as CruxExperts/LocalSetup. The README hero and current architecture and installation diagrams use approved LocalSetup branding, with reproducible rendering and accessible descriptions.
LocalSetup 4.44.1 corrects the active release sequence to the authorized 4.x line and combines the approved GitHub visual identity, canonical repository spelling, and a safe installer fallback for mixed-major release tags. The published v5.6.2 tag and assets remain unchanged.

- **Theme-aware graphics:** The README hero, architecture diagram, and installation flow each have light and dark images selected by GitHub's color scheme. Existing light image paths remain valid.
- **Reproducible brand assets:** The graphics renderer uses approved tokens and pinned JetBrains Mono v2.304 Regular and SemiBold files. The original font license and hashes are recorded with the source.
- **Asset inventory and brand contract:** Documentation checks recognize images in picture sources, and the brand guide records the visual rules and future AstroSite handoff. Nerd Font glyphs remain an optional site profile.
- **Canonical repository spelling:** The maintainer policy identifies `CruxExperts/LocalSetup` as the GitHub repository name and preserves existing repository URL paths and compatibility identifiers.
- **Corrected 4.x release line:** The verified history maps v5.6.2 content to corrected arithmetic 4.43.2, the branding feature to 4.44.0, and canonical repository-name policy to 4.44.1. The policy blocks MAJOR increments while the 4.x lock is active.
- **Theme-aware LocalSetup graphics:** The README hero, architecture diagram, and install-flow diagram use matching light and dark artwork with the approved mark, palette, and typography. The pinned renderer, JetBrains Mono files, source tokens, and font license make the exports reproducible.
- **Canonical name and release discovery:** Public repository policy uses `LocalSetup` spelling while retaining established commands and URLs. If release API lookup fails and stable tags span multiple major versions, the installer asks for `LOCALSETUP_BOOTSTRAP_REF` instead of guessing from numeric order.

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

The [4.4.0 guide](ls/docs/releases/4.4.0.md) remains available as release history.
Expand Down Expand Up @@ -85,7 +84,7 @@ Start with the [workflow packages guide](ls/docs/WORKFLOW_PACKAGES.md) for usage
<!-- facts-block:start -->
| Fact | Value |
|---|---|
| Current version | `5.7.1` |
| Current version | `4.44.1` |
| 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 | `105` |
| Workflow packages | `18` |
Expand All @@ -112,7 +111,7 @@ The legacy public form still opens the same wizard when a terminal is available:
curl -sSL https://raw.githubusercontent.com/CruxExperts/localsetup/main/install | bash -s -- --yes --tools codex
```

The public command is release-backed even though the small wrapper is downloaded from `main`: managed bootstrap installs resolve the latest non-draft, non-prerelease GitHub release tag before cloning or refreshing `~/.local/share/localsetup/source`, with a stable-tag fallback when release lookup is unavailable. Set `LOCALSETUP_BOOTSTRAP_REF` only when you intentionally want an explicit branch, tag, or commit. Explicit `--directory` checkouts are source-authoritative and are never auto-fetched or replaced.
The public command is release-backed even though the small wrapper is downloaded from `main`: managed bootstrap installs resolve the latest non-draft, non-prerelease GitHub release tag before cloning or refreshing `~/.local/share/localsetup/source`. If release lookup is unavailable, the installer uses a tag fallback only when all discoverable stable tags share one major version; it stops and asks for `LOCALSETUP_BOOTSTRAP_REF` when tags span multiple major lines. Set that variable only when you intentionally want an explicit branch, tag, or commit. Explicit `--directory` checkouts are source-authoritative and are never auto-fetched or replaced.

When raw managed bootstrap finds a clean legacy managed source checkout identified by `_localsetup/tools/localsetup.py`, it recognizes and refreshes that checkout to the release-backed modern layout with `ls/tools/localsetup.py`. Before fetching and replacing the checkout, LocalSetup stores a Git rollback bundle and JSON manifest outside the source checkout under `<source-parent>/state/source-migrations` when that location is external, or `~/.local/share/localsetup/state/source-migrations` otherwise. Dirty or untracked source checkouts remain rejected before refresh.

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.7.1
4.44.1
19 changes: 16 additions & 3 deletions install
Original file line number Diff line number Diff line change
Expand Up @@ -524,12 +524,25 @@ PY

latest_release_from_git_tags() {
command -v git >/dev/null 2>&1 || return 1
git ls-remote --tags --refs "$BOOTSTRAP_REPO" 'v*' 2>/dev/null \
local tags tag version major first_major=""
tags="$(git ls-remote --tags --refs "$BOOTSTRAP_REPO" 'v*' 2>/dev/null \
| awk '{print $2}' \
| sed 's#refs/tags/##' \
| grep -E '^v[0-9]+([.][0-9]+)*$' \
| sort -V \
| tail -n 1
|| true)"
[[ -n "$tags" ]] || return 1
# When API discovery is unavailable, a mixed-major tag set has no safe
# chronological interpretation. Do not silently select an older release
# line just because its major number sorts higher.
for tag in $tags; do
version="${tag#v}"
major="${version%%.*}"
if [[ -n "$first_major" && "$major" != "$first_major" ]]; then
return 1
fi
first_major="$major"
done
printf '%s\n' "$tags" | sort -V | tail -n 1
}

resolve_bootstrap_ref() {
Expand Down
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:** 5.7.1<br>
**Version:** 4.44.1<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/5.7.1.md) for LocalSetup 5.7.1, 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.44.1.md) for LocalSetup 4.44.1, 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
80 changes: 65 additions & 15 deletions ls/config/release-policy.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,79 @@
"additionalProperties": false,
"required": ["schema_version", "policy", "anchor", "overrides"],
"properties": {
"schema_version": {"const": 1},
"schema_version": {"enum": [1, 2]},
"policy": {"const": "sequential-logical-slices"},
"anchor": {
"anchor": {"$ref": "#/$defs/taggedAnchor"},
"overrides": {
"type": "array", "maxItems": 256,
"items": {"$ref": "#/$defs/override"}
},
"major_line": {"const": 4},
"reconciliation": {
"type": "object", "additionalProperties": false,
"required": ["original_anchor", "published_anchor", "cutoff", "reclassified_slices"],
"properties": {
"original_anchor": {"$ref": "#/$defs/taggedAnchor"},
"published_anchor": {"$ref": "#/$defs/taggedAnchor"},
"cutoff": {
"type": "object", "additionalProperties": false,
"required": ["commit", "source_version", "corrected_version"],
"properties": {
"commit": {"$ref": "#/$defs/sha"},
"source_version": {"$ref": "#/$defs/version"},
"corrected_version": {"$ref": "#/$defs/version"}
}
},
"reclassified_slices": {
"type": "array", "minItems": 1, "maxItems": 1,
"items": {
"type": "object", "additionalProperties": false,
"required": ["slice", "classification", "commits"],
"properties": {
"slice": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{0,127}$"},
"classification": {"const": "minor"},
"commits": {
"type": "array", "minItems": 2, "maxItems": 32,
"uniqueItems": true,
"items": {"$ref": "#/$defs/sha"}
}
}
}
}
}
}
},
"allOf": [
{
"if": {"properties": {"schema_version": {"const": 2}}, "required": ["schema_version"]},
"then": {"required": ["major_line", "reconciliation"]}
},
{
"if": {"properties": {"schema_version": {"const": 1}}, "required": ["schema_version"]},
"then": {"not": {"anyOf": [{"required": ["major_line"]}, {"required": ["reconciliation"]}]}}
}
],
"$defs": {
"sha": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
"version": {"type": "string", "maxLength": 64, "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"},
"taggedAnchor": {
"type": "object", "additionalProperties": false,
"required": ["commit", "version", "tag"],
"properties": {
"commit": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
"version": {"type": "string", "maxLength": 64, "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"},
"commit": {"$ref": "#/$defs/sha"},
"version": {"$ref": "#/$defs/version"},
"tag": {"type": "string", "pattern": "^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"}
}
},
"overrides": {
"type": "array", "maxItems": 256,
"items": {
"type": "object", "additionalProperties": false,
"required": ["commit", "slice", "classification"],
"properties": {
"commit": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
"slice": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{0,127}$"},
"classification": {"enum": ["none", "patch", "minor", "major"]}
}
"override": {
"type": "object", "additionalProperties": false,
"required": ["commit", "slice", "classification"],
"properties": {
"commit": {"$ref": "#/$defs/sha"},
"slice": {"type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{0,127}$"},
"classification": {"enum": ["none", "patch", "minor", "major"]}
}
}
},
"$comment": "The runtime also rejects duplicate JSON keys/commit overrides, checks tag equals v plus version, validates regular committed blobs, and binds anchor/overrides to Git ancestry."
"$comment": "Runtime validation additionally binds tags, commits, versions and history prefixes, and rejects duplicate JSON keys or override SHAs. Schema 2 is the repository-local 4.x major-line lock and one-time historical numbering reconciliation."
}
12 changes: 10 additions & 2 deletions ls/core/release_docs/planning.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,14 @@ def plan(root: Path, base: str | None = None, head: str = "HEAD", repair: bool =
baseline_tag = (previous[1] if previous else _tag_for_commit(repo_root, source_base)) or f"v{current_version}"
target_version = current_version
else:
source_base = explicit_base or str(version_plan["base"])
baseline_tag = _tag_for_commit(repo_root, source_base) or str(version_plan.get("anchor", {}).get("tag") or f"v{version_plan['base_version']}")
published_anchor = version_plan.get("published_anchor")
if (isinstance(published_anchor, dict)
and isinstance(version_plan.get("line_reconciliation"), dict)):
source_base = str(published_anchor["commit"])
baseline_tag = str(published_anchor["tag"])
Comment on lines +115 to +119

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the v5.6.2 baseline in repair mode

When v4.44.1 has been published and release-docs ... --repair --verify-baseline is used, control enters the repair branch before this new reconciliation-aware anchor handling. _prior_release() compares versions numerically, so it excludes v5.6.2 because it is greater than 4.44.1 and can select v4.22.9 instead; the repair candidate then includes the entire already-published migration history and may rewrite the 4.44.1 notes from the wrong baseline. Apply the reconciliation/published-anchor selection to repair planning as well.

AGENTS.md reference: AGENTS.md:L55-L62

Useful? React with 👍 / 👎.

else:
source_base = explicit_base or str(version_plan["base"])
baseline_tag = _tag_for_commit(repo_root, source_base) or str(version_plan.get("anchor", {}).get("tag") or f"v{version_plan['base_version']}")
target_version = version_plan["target_version"]
documents = tracked_documents(repo_root)
all_changed = _changed_paths(repo_root, source_base, source_head)
Expand Down Expand Up @@ -148,6 +154,8 @@ def plan(root: Path, base: str | None = None, head: str = "HEAD", repair: bool =
"ok": bool(documents) and not any(item["code"] == "invalid_version_plan" for item in findings),
"target_version": target_version,
"source_commit": source_head,
"source_base": source_base,
"baseline_version": baseline_version,
"baseline_tag": baseline_tag,
"changed_paths": changed_paths,
"generated_paths": generated_paths,
Expand Down
2 changes: 1 addition & 1 deletion ls/core/versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ def publish_preflight(repo_root: Path, *, base: str | None = None, head: str | N
result["reason"] = "dirty_worktree"
result["dirty_worktree"] = dirty
return result
if plan["bump"] != "none" and not plan["ok"]:
if not plan["ok"]:
sync_version_files(repo_root, target)
commit = commit_version_sync(repo_root, target)
if commit:
Expand Down
Loading
Loading