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
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/install-failure.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ body:
Simulator Broker is **Alpha**, **macOS-only**, and needs **Xcode** to
create or run iOS Simulators. Install the CLI with
`brew install fiveonecode/simulator-broker/simbroker` or
`npm install -g` of the `simbroker-0.1.0-alpha.3.tgz` from GitHub
`npm install -g` of the `simbroker-0.1.0-alpha.4.tgz` from GitHub
Releases. Install the operator app with
`brew install --cask fiveonecode/simulator-broker/simulator-broker`.

Expand All @@ -23,7 +23,7 @@ body:
label: What install path did you use?
options:
- Homebrew (`brew install fiveonecode/simulator-broker/simbroker`)
- npm (`npm install -g` of `simbroker-0.1.0-alpha.3.tgz` from GitHub Releases)
- npm (`npm install -g` of `simbroker-0.1.0-alpha.4.tgz` from GitHub Releases)
- Homebrew cask (`brew install --cask fiveonecode/simulator-broker/simulator-broker`)
- CLI-only (`bash scripts/install_local.sh --cli-only`)
- Contributor app + CLI (`npm run install:local`)
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Publish the Alpha CLI tarball and the packable npm CLI when a version
# tag is pushed. After merge, create the matching tag (example:
# v0.1.0-alpha.1). This workflow does not build or attach the macOS app.
# Publish the Alpha CLI tarball, its SHA-256 checksum, and the packable npm
# CLI when a version tag is pushed. The operator attaches the signed,
# notarized macOS app zip, completing the four-custom-asset Release contract.
name: Release CLI

on:
Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
fi
gh release create "${GITHUB_REF_NAME}" \
--title "Simulator Broker ${GITHUB_REF_NAME}" \
--notes "Alpha CLI and npm package. Install the CLI with \`brew install fiveonecode/simulator-broker/simbroker\` or \`npm install -g\` the attached \`simbroker-${version}.tgz\`. Install the operator app with \`brew install --cask fiveonecode/simulator-broker/simulator-broker\`. Node.js 20 or newer is required. macOS and Xcode are still required to create and run iOS Simulators. This workflow attaches the CLI tarball and npm package; the signed, notarized operator app zip is attached to the same GitHub Release by the operator. See CHANGELOG.md." \
--notes "Alpha release artifacts. Install the CLI with \`brew install fiveonecode/simulator-broker/simbroker\` or \`npm install -g\` the attached \`simbroker-${version}.tgz\`. Install the operator app with \`brew install --cask fiveonecode/simulator-broker/simulator-broker\`. Node.js 20 or newer is required. macOS and Xcode are still required to create and run iOS Simulators. This workflow attaches three custom assets: the CLI tarball, its SHA-256 checksum, and the npm package. The operator attaches the signed, notarized app zip to complete exactly four custom assets; GitHub source archives are generated separately. See CHANGELOG.md." \
"${prerelease_args[@]}" \
"$asset" \
"$checksum" \
Expand Down
37 changes: 37 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.1.0-alpha.4] - 2026-08-31

This release hardens the public install, upgrade, and dashboard paths used for
the first broader Simulator Broker announcement. It also makes the complete
GitHub Release inventory explicit: CLI archive, CLI checksum, npm tarball, and
notarized app zip.

### Added

- `scripts/package_cask_zip.sh` (`npm run package:cask-zip`) writes the
Expand All @@ -18,6 +25,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`codesign --verify --deep --strict` and an unstapled app with
`xcrun stapler validate`. It does not build, sign, notarize, tag, or
publish.
- Correlated installed-app smoke evidence now proves that the launched
`/Applications` app decoded the freshly prepared broker snapshot and
completed a manual refresh under one exact process, executable, state root,
and snapshot generation.

### Changed

- Public onboarding now keeps Homebrew CLI, Homebrew cask, guided setup,
reinstall, and direct tagged-asset commands aligned and CI-gated. Bash PATH
persistence follows the login files Bash actually reads, while reinstall
keeps host configuration and broker state unless reset is explicit.
- GitHub workflows use maintained Node 24 action runtimes with explicit cache
behavior, and the agent/reliability contract now examines interacting
conditions, degraded operation, recovery, and residual risk without adding
unnecessary operational coupling.
- The app's timestamp wording and Automatic shutdown guidance now distinguish
snapshot age from refresh time and explain intentional warm Simulator reuse.
- Completion fixtures and durable task evidence remain public-safe even when a
checkout lives beneath a private machine path.

### Fixed

- `simbroker setup --help` follows the normal help path instead of entering
setup dispatch, and installed daemon health is checked against the current
runtime across upgrades before commands are exposed.
- The Simulators pane remains usable at the minimum supported window size.
- Dashboard refresh failures now fail closed: stale service authority cannot
enable mutations, queued or cancelled setup/refresh work cannot publish
after lifecycle loss, and verified recovery restores authority only after a
current exact-status success.

## [0.1.0-alpha.3] - 2026-08-29

Expand Down
4 changes: 2 additions & 2 deletions Casks/simulator-broker.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cask "simulator-broker" do
version "0.1.0-alpha.3"
sha256 "42d5d441a40d551201afa23df303738475b559d9b7d1c98f0403aa1ff1822c8b"
version "0.1.0-alpha.4"
sha256 "d44c4ba8318338c5e009ed2e71aa6fea03e6167698a4a60df7ce5b865f5e3963"

url "https://github.com/fiveonecode/simulator-broker/releases/download/v#{version}/Simulator-Broker-#{version}.zip"
name "Simulator Broker"
Expand Down
4 changes: 2 additions & 2 deletions Formula/simbroker.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
class Simbroker < Formula
desc "Local iOS Simulator control plane CLI"
homepage "https://github.com/fiveonecode/simulator-broker"
url "https://github.com/fiveonecode/simulator-broker/releases/download/v0.1.0-alpha.3/simulator-broker-0.1.0-alpha.3-cli.tar.gz"
sha256 "2607b6756b2785d433c00f14ccbf9d56a24d8a607668994cc2bdd611c85c2e86"
url "https://github.com/fiveonecode/simulator-broker/releases/download/v0.1.0-alpha.4/simulator-broker-0.1.0-alpha.4-cli.tar.gz"
sha256 "1e04e4e9f7c0b372722b80e057b63dda87e12d7d5cbf7043d084826f0ea57503"
license "MIT"

depends_on macos: :sonoma
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ simbroker idle enable --grace-seconds <60-86400> --actor-type human --actor-id <
Other CLI install options:

```bash
npm install -g https://github.com/fiveonecode/simulator-broker/releases/download/v0.1.0-alpha.3/simbroker-0.1.0-alpha.3.tgz
npm install -g https://github.com/fiveonecode/simulator-broker/releases/download/v0.1.0-alpha.4/simbroker-0.1.0-alpha.4.tgz
simbroker --help
```

Expand All @@ -102,8 +102,8 @@ are also attached to those releases. The archive contains a versioned top-level
directory:

```bash
tar -xzf simulator-broker-0.1.0-alpha.3-cli.tar.gz
./simulator-broker-0.1.0-alpha.3-cli/bin/simbroker --help
tar -xzf simulator-broker-0.1.0-alpha.4-cli.tar.gz
./simulator-broker-0.1.0-alpha.4-cli/bin/simbroker --help
```

`simbroker` help and `simbroker doctor` print human-readable text by default.
Expand Down
15 changes: 10 additions & 5 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
## Supported Versions

Security fixes are considered for the current `main` branch and for the latest
tagged Alpha (`0.1.0-alpha.3`). Older Alpha tags are not supported. The
published CLI artifacts are the GitHub Release tarball, the Homebrew
formula that installs that tarball, and the packable `simbroker` npm
package, and the signed, notarized operator app zip
`Simulator-Broker-0.1.0-alpha.3.zip`.
tagged Alpha (`0.1.0-alpha.4`). Older Alpha tags are not supported. The
published Alpha has exactly four custom GitHub Release assets:

1. `simulator-broker-0.1.0-alpha.4-cli.tar.gz`
2. `simulator-broker-0.1.0-alpha.4-cli.tar.gz.sha256`
3. `simbroker-0.1.0-alpha.4.tgz`
4. `Simulator-Broker-0.1.0-alpha.4.zip`

The Homebrew formula and cask install the matching CLI and signed, notarized
app archives. GitHub's generated source archives appear separately.

## Reporting A Vulnerability

Expand Down
16 changes: 13 additions & 3 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ does not require XcodeGen. The app still needs the CLI installed separately.
## Install the CLI with npm

```bash
npm install -g https://github.com/fiveonecode/simulator-broker/releases/download/v0.1.0-alpha.3/simbroker-0.1.0-alpha.3.tgz
npm install -g https://github.com/fiveonecode/simulator-broker/releases/download/v0.1.0-alpha.4/simbroker-0.1.0-alpha.4.tgz
command -v simbroker
simbroker --help
```
Expand All @@ -76,13 +76,23 @@ To install from a tagged Alpha without cloning, download
then run:

```bash
tar -xzf simulator-broker-0.1.0-alpha.3-cli.tar.gz
./simulator-broker-0.1.0-alpha.3-cli/bin/simbroker --help
tar -xzf simulator-broker-0.1.0-alpha.4-cli.tar.gz
./simulator-broker-0.1.0-alpha.4-cli/bin/simbroker --help
```

The archive is the Node CLI only and contains that versioned top-level
directory.

A complete tagged Alpha has exactly four custom GitHub Release assets:

1. `simulator-broker-<version>-cli.tar.gz`
2. `simulator-broker-<version>-cli.tar.gz.sha256`
3. `simbroker-<version>.tgz`
4. `Simulator-Broker-<version>.zip`

GitHub's generated source archives appear separately and are not part of that
four-asset install contract.

- If Homebrew is present and `$(brew --prefix)/bin` is writable, the wrapper
is installed there so a new login shell already has it on `PATH`.
- Otherwise the wrapper is installed to `~/.local/bin` and the installer
Expand Down
4 changes: 3 additions & 1 deletion docs/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ This Alpha already includes:
`simulators repair --alias <alias>`
- CLI-only install through `bash scripts/install_local.sh --cli-only`, plus
the contributor app+CLI path `npm run install:local`
- tagged Alpha CLI tarball through `npm run package:cli` and GitHub Releases
- tagged Alpha GitHub Releases with exactly four custom assets: the CLI
tarball, its `.sha256` checksum, the packable npm tarball, and the signed,
notarized app zip. GitHub's generated source archives appear separately
- public Node test CI: GitHub-hosted Ubuntu for broker-core and
harness-adoption plus the public docs contract, GitHub-hosted macOS for
client tests. Tagged releases run the public docs contract before packaging.
Expand Down
104 changes: 104 additions & 0 deletions docs/test/front-door.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,58 @@ function readRepoFile(relativePath) {
const packageJson = JSON.parse(readRepoFile("package.json"));
const version = packageJson.version;
const cliArchiveDirectory = `simulator-broker-${version}-cli`;
const customReleaseAssetTemplates = [
"simulator-broker-<version>-cli.tar.gz",
"simulator-broker-<version>-cli.tar.gz.sha256",
"simbroker-<version>.tgz",
"Simulator-Broker-<version>.zip",
];

function assertExactCustomReleaseAssetInventory(markdown) {
const marker = "A complete tagged Alpha has exactly four custom GitHub Release assets:";
const markerIndex = markdown.indexOf(marker);
assert.notEqual(markerIndex, -1, "release asset inventory marker must be present");

const lines = markdown.slice(markerIndex + marker.length).trimStart().split(/\r?\n/);
const assets = [];
for (const line of lines) {
const match = line.match(/^\d+\. `([^`]+)`$/);
if (match) {
assets.push(match[1]);
continue;
}
if (assets.length > 0) {
break;
}
}
assert.deepEqual(assets, customReleaseAssetTemplates);
}

function assertExactWorkflowAssetArguments(workflow) {
const lines = workflow.split(/\r?\n/);
const createIndex = lines.findIndex((line) => line.includes('gh release create "${GITHUB_REF_NAME}"'));
assert.notEqual(createIndex, -1, "gh release create command must be present");

const commandLines = [];
for (let index = createIndex; index < lines.length; index += 1) {
const line = lines[index].trim();
commandLines.push(line);
if (!line.endsWith("\\")) {
break;
}
}
const normalizedLines = commandLines.map((line) => line.replace(/\s+\\$/, ""));
assert.equal(normalizedLines.length, 7, "release command must keep its exact flag and asset shape");
assert.equal(normalizedLines[0], 'gh release create "${GITHUB_REF_NAME}"');
assert.equal(normalizedLines[1], '--title "Simulator Broker ${GITHUB_REF_NAME}"');
assert.match(normalizedLines[2], /^--notes ".*"$/);
assert.equal(normalizedLines[3], '"${prerelease_args[@]}"');
assert.deepEqual(
normalizedLines.slice(4),
['"$asset"', '"$checksum"', '"$npm_asset"'],
"the tag workflow must attach exactly the three operator-replaceable CLI/npm assets",
);
}

function firstScreen(markdown) {
const lines = markdown.split(/\r?\n/);
Expand Down Expand Up @@ -434,9 +486,14 @@ test("release workflow packages the CLI tarball on version tags", () => {
assertWorkflowJobRunsExactCommand(release, "release", "npm run test:docs");
assert.ok(release.includes("npm run package:cli"));
assert.ok(release.includes("npm run package:npm"));
assert.ok(release.includes('asset="artifacts/cli/simulator-broker-${version}-cli.tar.gz"'));
assert.ok(release.includes('checksum="${asset}.sha256"'));
assert.ok(release.includes("artifacts/npm/simbroker-${version}.tgz"));
assert.ok(release.includes("gh release create"));
assert.ok(release.includes("--prerelease"));
assertExactWorkflowAssetArguments(release);
assert.match(release, /CLI tarball, its SHA-256 checksum, and the npm package/);
assert.match(release, /complete exactly four custom assets/);
assert.equal(release.includes("test:app"), false);
assert.equal(
release.replace(/\s+/g, " ").includes("This release is not a Homebrew formula, notarized app, or npm package."),
Expand All @@ -449,6 +506,53 @@ test("release workflow packages the CLI tarball on version tags", () => {
"tag release notes must not claim the notarized app zip is absent",
);
assert.ok(release.includes("brew install --cask fiveonecode/simulator-broker/simulator-broker"));

const withUnexpectedAsset = release.replace(
' "$npm_asset"',
' "$npm_asset" \\\n "unexpected.zip"',
);
assert.notEqual(withUnexpectedAsset, release, "negative fixture must add a fourth attachment");
assert.throws(
() => assertExactWorkflowAssetArguments(withUnexpectedAsset),
"a fourth workflow attachment must fail the exact asset assertion",
);
const withInterspersedAsset = release.replace(
' "${prerelease_args[@]}"',
' "unexpected.zip" \\\n "${prerelease_args[@]}"',
);
assert.notEqual(withInterspersedAsset, release, "negative fixture must intersperse an attachment");
assert.throws(
() => assertExactWorkflowAssetArguments(withInterspersedAsset),
"a positional attachment interspersed with flags must fail the exact asset assertion",
);
});

test("public release contract inventories exactly four custom assets", () => {
const spec = readRepoFile("spec/build-and-test.md");
const gettingStarted = readRepoFile("docs/getting-started.md");
const status = readRepoFile("docs/status.md");
const security = readRepoFile("SECURITY.md");

assertExactCustomReleaseAssetInventory(spec);
assertExactCustomReleaseAssetInventory(gettingStarted);
assert.match(status, /exactly four custom assets/);
for (const template of customReleaseAssetTemplates) {
assert.ok(
security.includes(template.replace("<version>", version)),
`SECURITY must name ${template}`,
);
}
assert.match(spec, /GitHub's generated source archives[\s\S]*not part of this custom-asset count/);

const withoutChecksum = spec.replace(
"2. `simulator-broker-<version>-cli.tar.gz.sha256`\n",
"",
);
assert.notEqual(withoutChecksum, spec, "negative fixture must remove the checksum asset");
assert.throws(
() => assertExactCustomReleaseAssetInventory(withoutChecksum),
"omitting the CLI checksum must fail the release-contract assertion",
);
});

test("on-demand OCR review uses the maintained hosted action runtime contract", () => {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"test:package-smoke": "bash ./scripts/package_smoke.sh",
"verify:public-surface": "node client/public-surface.mjs"
},
"version": "0.1.0-alpha.3",
"version": "0.1.0-alpha.4",
"description": "Local simulator broker and macOS operator app for coordinated iOS Simulator workflows",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/simbroker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Alpha CLI for Simulator Broker. Node.js 20 or newer is required. Creating and
running iOS Simulators still requires macOS and Xcode.

```bash
npm install -g https://github.com/fiveonecode/simulator-broker/releases/download/v0.1.0-alpha.3/simbroker-0.1.0-alpha.3.tgz
npm install -g https://github.com/fiveonecode/simulator-broker/releases/download/v0.1.0-alpha.4/simbroker-0.1.0-alpha.4.tgz
simbroker --help
```

Expand Down
2 changes: 1 addition & 1 deletion packages/simbroker/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "simbroker",
"version": "0.1.0-alpha.3",
"version": "0.1.0-alpha.4",
"private": false,
"description": "CLI for the local iOS Simulator control plane",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion spec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ This repo exists to develop a reusable local simulator broker:
- local install, local-debug portable packaging, Release distribution packaging, and onboarding flows now exist through `install_local.sh`, `install_local.sh --cli-only`, `package_local.sh`, `package_distribution.sh`, `test:install-smoke`, `test:package-smoke`, `host init --bootstrap-config`, and `project init`
- the published onboarding docs now distinguish CLI-only install, repo-local contributor app+CLI install, local-debug portable bundling, and signed distribution packaging; a new login shell should resolve `simbroker` after install without sourcing `env.sh`
- `CONTRIBUTING.md` publishes a public-patch track (Node.js 20 and the Node test suites, no harness session) and a labeled maintainer/agent harness track; `agent:complete` enforcement is unchanged
- tagged Alpha `0.1.0-alpha.3` publishes a CLI tarball from `scripts/package_cli.sh`, the packable npm CLI, and a notarized operator app zip that include guided `simbroker setup`, and runs broker-core plus harness-adoption on GitHub-hosted Ubuntu and client tests on GitHub-hosted macOS; the macOS app suite and home-path public-surface scan are not on those jobs. Reproduce the cask zip with `scripts/package_cask_zip.sh` after Developer ID signing and notarization.
- tagged Alpha `0.1.0-alpha.4` publishes exactly four custom GitHub Release assets: a CLI tarball from `scripts/package_cli.sh`, its SHA-256 checksum, the packable npm CLI, and a notarized operator app zip. The tag workflow runs the public docs, public-surface, broker-core, client, and harness-adoption checks on GitHub-hosted Ubuntu before attaching the first three assets; the operator attaches the app zip after Developer ID signing and notarization. GitHub's generated source archives are not custom assets. Public pull-request CI remains split between Ubuntu and macOS, while the macOS app suite and home-path public-surface scan stay local.
- public pull-request CI and the tagged-release workflow run `npm run test:docs`
so archive paths, install guidance, and workflow gates cannot drift without a
failing check
Expand Down
Loading