diff --git a/.forgejo/workflows/guard.yml b/.forgejo/workflows/guard.yml index 7f952d4..dbdfd35 100644 --- a/.forgejo/workflows/guard.yml +++ b/.forgejo/workflows/guard.yml @@ -20,17 +20,16 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - name: Install pinned negentropy - run: | - set -eu - curl -fsSL https://releases.negentropy.perish.uk/manage.sh -o "$RUNNER_TEMP/manage-negentropy.sh" - sh "$RUNNER_TEMP/manage-negentropy.sh" install --channel stable --bin-dir "$HOME/.local/bin" - echo "$HOME/.local/bin" >> "$GITHUB_PATH" + - name: Install Ectropy + uses: PerishLab/actions/setup-ectropy@main + + - name: Install Plumb + uses: PerishLab/actions/setup-plumb@main - name: Guard run: | set -eu - deno run --allow-read "--allow-write=." --allow-env --allow-net "--allow-run=git,cargo,negentropy,deno,tea,sh,runseal" --config .runseal/deno.json --lock .runseal/deno.lock --frozen=true .runseal/wrappers/guard.ts --fresh + deno run --allow-read "--allow-write=." --allow-env --allow-net "--allow-run=git,cargo,ectropy,plumb,deno,tea,sh,runseal" --config .runseal/deno.json --lock .runseal/deno.lock --frozen=true .runseal/wrappers/guard.ts --fresh guard-macos: runs-on: macos diff --git a/.forgejo/workflows/release-beta.yml b/.forgejo/workflows/release-beta.yml index 43587c5..e975c9c 100644 --- a/.forgejo/workflows/release-beta.yml +++ b/.forgejo/workflows/release-beta.yml @@ -70,15 +70,17 @@ jobs: - name: CLI smoke run: cargo run --locked -p sidecar -- doctor --config examples/minimal.toml - - name: Install pinned negentropy - run: | - set -eu - curl -fsSL https://releases.negentropy.perish.uk/manage.sh -o "$RUNNER_TEMP/manage-negentropy.sh" - sh "$RUNNER_TEMP/manage-negentropy.sh" install --channel stable --bin-dir "$HOME/.local/bin" - echo "$HOME/.local/bin" >> "$GITHUB_PATH" + - name: Install Ectropy + uses: PerishLab/actions/setup-ectropy@main + + - name: Install Plumb + uses: PerishLab/actions/setup-plumb@main + + - name: Plumb + run: plumb doctor . - - name: Negentropy - run: negentropy --strict . + - name: Ectropy + run: ectropy --strict . build: needs: [metadata, verify] diff --git a/.forgejo/workflows/release-stable.yml b/.forgejo/workflows/release-stable.yml index 6fdf73e..8acc27f 100644 --- a/.forgejo/workflows/release-stable.yml +++ b/.forgejo/workflows/release-stable.yml @@ -69,15 +69,17 @@ jobs: - name: CLI smoke run: cargo run --locked -p sidecar -- doctor --config examples/minimal.toml - - name: Install pinned negentropy - run: | - set -eu - curl -fsSL https://releases.negentropy.perish.uk/manage.sh -o "$RUNNER_TEMP/manage-negentropy.sh" - sh "$RUNNER_TEMP/manage-negentropy.sh" install --channel stable --bin-dir "$HOME/.local/bin" - echo "$HOME/.local/bin" >> "$GITHUB_PATH" + - name: Install Ectropy + uses: PerishLab/actions/setup-ectropy@main + + - name: Install Plumb + uses: PerishLab/actions/setup-plumb@main + + - name: Plumb + run: plumb doctor . - - name: Negentropy - run: negentropy --strict . + - name: Ectropy + run: ectropy --strict . build: needs: [metadata, verify] diff --git a/.runseal/deno.lock b/.runseal/deno.lock index e12282c..e0f8a6c 100644 --- a/.runseal/deno.lock +++ b/.runseal/deno.lock @@ -1,13 +1,13 @@ { "version": "5", "specifiers": { - "jsr:@perish/sealkit@*": "0.1.2", + "jsr:@perish/sealkit@*": "0.1.8", "jsr:@perish/shield@0.1.0": "0.1.0", "jsr:@std/cli@1.0.30": "1.0.30" }, "jsr": { - "@perish/sealkit@0.1.2": { - "integrity": "49dbe51e044756e5c745de322ef785982b6000421ce9ebd51198f18868bafc40", + "@perish/sealkit@0.1.8": { + "integrity": "068e6078b21999452bb447c57e6d3f0dfd970228e1f14f3b419febd36cff4450", "dependencies": [ "jsr:@perish/shield", "jsr:@std/cli" diff --git a/.runseal/wrappers/guard.ts b/.runseal/wrappers/guard.ts index 480cefc..af68610 100644 --- a/.runseal/wrappers/guard.ts +++ b/.runseal/wrappers/guard.ts @@ -29,8 +29,10 @@ await guard( ".runseal/wrappers/guard.ts", ".runseal/wrappers/init.ts", ".runseal/wrappers/land.ts", + ".runseal/wrappers/release.ts", ]]], }, + { label: "plumb doctor", runs: [["plumb", ["doctor", "."]]] }, ], Deno.args, ); diff --git a/.runseal/wrappers/init.ts b/.runseal/wrappers/init.ts index c9a1bab..50c8837 100644 --- a/.runseal/wrappers/init.ts +++ b/.runseal/wrappers/init.ts @@ -1,15 +1,4 @@ -import { cli, flags } from "@perish/sealkit/cli"; import { init } from "@perish/sealkit/init"; -import { io } from "@perish/sealkit/io"; - -const args = cli.parse(Deno.args, { boolean: ["help", "h"] }); -flags(args).positionals("init", { allowHelp: true }); -if (flags(args).help()) { - io.print("Usage: runseal :init"); - io.print(""); - io.print("Validate the repository and install versioned git hooks."); - Deno.exit(0); -} await init({ tools: [ @@ -19,19 +8,24 @@ await init({ "tea", "runseal", "sh", + "ectropy", + "plumb", ], paths: [ "Cargo.toml", "Cargo.lock", - "negentropy.toml", - "vocabulary.toml", + "ectropy.toml", "manage.sh", + "manage.ps1", "runseal.toml", ".runseal/deno.json", ".runseal/deno.lock", ".runseal/wrappers/guard.ts", ".runseal/wrappers/init.ts", ".runseal/wrappers/land.ts", + ".runseal/wrappers/release.ts", ".forgejo/workflows/guard.yml", + ".forgejo/workflows/release-beta.yml", + ".forgejo/workflows/release-stable.yml", ], }); diff --git a/AGENTS.md b/AGENTS.md index b84c067..2897390 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -44,7 +44,7 @@ The TCP broker is local service discovery and runtime registry for host processe ## Build-time Stamps -`crates/cli` reads three optional build-time env vars via `option_env!` and bakes them into the binary; `.github/scripts/release/assets/package.{sh,ps1}` set all three from the release workflow: +`crates/cli` reads three optional build-time env vars via `option_env!` and bakes them into the binary; `.forgejo/scripts/release/assets/package.{sh,ps1}` set all three from the release workflow: - `SIDECAR_BUILD_VERSION` → `cli::version()` (defaults to `v` for dev builds). - `SIDECAR_BUILD_CHANNEL` → `cli::channel()` (`stable` / `beta` / `dev`; defaults to `dev`, which disables the startup check and `update` subcommand). @@ -102,20 +102,33 @@ Root `manage.{sh,ps1}` accept exactly: `install`, `update`, `uninstall`. There i ## Repo-local Support -`runseal.toml` and `.runseal/wrappers/*` are the repo-local operator entrypoints for support tasks that do not belong in the installable `sidecar` product binary. The wrappers are Deno TypeScript run through `runseal`; local development requires `runseal`, `deno`, and a `negentropy` binary matching the pin in `.runseal/negentropy.version`. Current support commands: - -- `runseal :init` — idempotent post-clone validator. It quick-fails on missing required tools (git, deno, cargo, gh, runseal, the pinned negentropy) or repository entrypoints, and exits cleanly only when the checkout is ready for development. -- `runseal :guard` — the full local gate: fmt, clippy, tests, `deno fmt` / `deno check` over `.runseal`, and the pinned `negentropy --strict .`. -- `runseal :land` — lands the current clean topic branch: push, create or reuse the PR, await the checks on the exact pushed head SHA, squash-merge pinned to that SHA, sync `main`, delete the branch. `--dry-run` prints the plan without touching git or GitHub. -- `runseal :cloudflare` — repo-local Cloudflare support for checking credentials and ensuring exact-path `sidecar.perish.uk/manage.sh|ps1` redirects to the release bucket. Use `manage-ensure-redirect --dry-run` before applying changes. +`runseal.toml` and `.runseal/wrappers/*` are thin repo-local operator +entrypoints for support tasks that do not belong in the installable `sidecar` +product binary. Shared operator logic belongs in Sealkit; `.runseal` contains +no dedicated TypeScript tests. Local development requires `runseal`, `deno`, +Ectropy, and Plumb. Current support commands: + +- `runseal :init` — idempotent post-clone validator for tools, repository + entrypoints, and versioned Git hooks. +- `runseal :guard` — the full local gate: fmt, clippy, tests, Deno checks, + `plumb doctor .`, and `ectropy --strict .`. +- `runseal :land` — lands the current clean topic branch through Forgejo, + waits for checks on the exact pushed head SHA, squash-merges that SHA, syncs + `main`, and deletes the branch. `--dry-run` prints the plan without mutation. +- `runseal :release` — dispatches the stable or beta Forgejo release workflow. ## Constitution -`negentropy` is the structure checker for this repository; `negentropy --strict .` must print `clean` before anything lands. Its configuration is repo-owned: +Ectropy owns pure AST syntax execution. Plumb owns repository shape, the +canonical `ectropy.toml` policy, and which paths receive syntax grants. Both +must pass before anything lands: -- `negentropy.toml` — scan roots (`crates/**/*.rs`, `docs/**/*.md`), module roots, block/path depth limits, the comment ban, the single-word identifier rule, and the test-syntax grant for `crates/*/tests`. -- `vocabulary.toml` — registered compound atoms; while it is empty, every identifier must stay a single word. -- `.runseal/negentropy.version` — the pinned checker version (currently `v0.1.0-beta.9`). `runseal :init`, `runseal :guard`, and CI all verify the installed binary against this pin and refuse a mismatch. +- `ectropy.toml` — scan roots (`crates/**/*.rs`, `docs/**/*.md`), module roots, + limits, the comment ban, the single-word rule, and explicit test/environment + grants. +- `plumb doctor .` — repository layout, operator, workflow, and policy + enforcement. +- `ectropy --strict .` — syntax execution against that policy. ## Common Commands @@ -124,7 +137,7 @@ Root `manage.{sh,ps1}` accept exactly: `install`, `update`, `uninstall`. There i - Clippy: `cargo clippy --locked --workspace --all-targets -- -D warnings` - CLI smoke: `cargo run --locked -p cli -- doctor --config examples/minimal.toml` - Plan: `cargo run --locked -p cli -- plan --config examples/minimal.toml --format json` -- Constitution check: `negentropy --strict .` +- Repository check: `plumb doctor . && ectropy --strict .` - Full gate: `runseal :guard` ## Repository Shape @@ -133,9 +146,11 @@ Root `manage.{sh,ps1}` accept exactly: `install`, `update`, `uninstall`. There i - `crates/cli/`: CLI parsing, lifecycle execution (`start`/`stop`/`restart`/`status`/`list`/`reset`), `inspect [payload]`, output formatting, exit behavior. - `manage.sh` and `manage.ps1`: public install/update/uninstall manager entrypoints uploaded as release assets. - `docs/`: durable design notes for planned architecture changes, including the TCP broker runtime direction. -- `.runseal/`: runseal wrapper entrypoints (`guard.ts`, `init.ts`, `land.ts`, `cloudflare.seal`), the shared wrapper `lib/`, and the `negentropy.version` pin. -- `negentropy.toml` and `vocabulary.toml`: the constitution the `negentropy` checker enforces over `crates/` and `docs/`. -- `.github/scripts/`: workflow-only release helpers. +- `.runseal/`: thin runseal wrapper entrypoints for guard, init, land, and + release. +- `ectropy.toml`: the Plumb-managed syntax policy Ectropy executes over + `crates/` and `docs/`. +- `.forgejo/scripts/`: workflow-only release helpers. ## Standard Workflow @@ -147,7 +162,9 @@ After cloning or when the toolchain looks stale, run: runseal :init ``` -It validates the required tools (including a `negentropy` matching `.runseal/negentropy.version`) and the repository entrypoints, then exits. It installs nothing: there are no local git hooks. The gates are `runseal :guard` before landing and the `guard` workflow in CI. +It validates the required tools and repository entrypoints, then installs the +versioned Git hooks. The gates are `runseal :guard` before landing and the +`guard` workflow in CI. ### Branch Names @@ -178,10 +195,13 @@ cargo clippy --locked --workspace --all-targets -- -D warnings cargo test --locked --workspace deno fmt --check .runseal deno check --config .runseal/deno.json --lock .runseal/deno.lock --frozen=true .runseal/wrappers/*.ts -negentropy --strict . +plumb doctor . +ectropy --strict . ``` -CI reruns the same wrapper: `.github/workflows/guard.yml` installs the pinned negentropy release, then executes `.runseal/wrappers/guard.ts` on every PR and every push to `main`. +CI reruns the same wrapper: `.forgejo/workflows/guard.yml` installs Ectropy and +Plumb through the shared actions, then executes `.runseal/wrappers/guard.ts` on +every PR and every push to `main`. ### PR Descriptions @@ -202,7 +222,9 @@ Add `## Compatibility` when a manifest field, CLI flag, protocol field, output s ### Merging -`main` is PR-only and protected by the repository ruleset `main guard`. The required merge gate is the `guard` check from `.github/workflows/guard.yml` (currently `guard (ubuntu-latest)`). Required approvals are intentionally `0`. +`main` is PR-only and protected by the repository ruleset `main guard`. The +required merge gate is the `guard` check from `.forgejo/workflows/guard.yml`. +Required approvals are intentionally `0`. From a clean topic branch, default to landing with: @@ -210,7 +232,9 @@ From a clean topic branch, default to landing with: runseal :land ``` -It pushes the branch, creates or reuses the PR, records the exact pushed head SHA, polls the GitHub check-runs on that SHA until every one succeeds, squash-merges with `--match-head-commit ` so only the audited commit can land, syncs `main`, and deletes the branch. If `:land` is unavailable, wait for green checks and fall back to `gh pr merge --squash --delete-branch`. +It pushes the branch, creates or reuses the PR, records the exact pushed head +SHA, polls the Forgejo checks on that SHA until every one succeeds, +squash-merges only the audited commit, syncs `main`, and deletes the branch. ## Stamp args protocol diff --git a/negentropy.toml b/ectropy.toml similarity index 88% rename from negentropy.toml rename to ectropy.toml index 8681bca..f20c823 100644 --- a/negentropy.toml +++ b/ectropy.toml @@ -1,41 +1,43 @@ -[scan] -include = [ - "crates/**/*.rs", - "docs/**/*.md", -] -exclude = [ - "**/target/**", -] - -[module] -roots = [ - "crates/*/src", - "crates/*/tests", - "docs", -] - -[limit] -block = 4 -path = 4 - [comment] allow = false -[word] -single = true - [[grant]] -syntax = "test" paths = ["crates/*/tests/**/*.rs"] +syntax = "test" [[grant]] -syntax = "environment" paths = [ - "crates/cli/src/main.rs", "crates/cli/src/args.rs", "crates/cli/src/cli.rs", "crates/cli/src/commands/runtime.rs", + "crates/cli/src/main.rs", "crates/cli/src/update.rs", "crates/core/src/paths.rs", "crates/*/tests/**/*.rs", ] +syntax = "environment" + +[limit] +block = 4 +fanout = 10 +file = 300 +markup = 8 +param = 4 +path = 4 + +[module] +roots = [ + "crates/*/src", + "crates/*/tests", + "docs", +] + +[scan] +exclude = ["**/target/**"] +include = [ + "crates/**/*.rs", + "docs/**/*.md", +] + +[word] +single = true diff --git a/runseal.toml b/runseal.toml index 101759d..ac725eb 100644 --- a/runseal.toml +++ b/runseal.toml @@ -9,7 +9,7 @@ permissions = [ "--allow-write=.", "--allow-env", "--allow-net", - "--allow-run=git,cargo,negentropy,deno,tea,sh,runseal", + "--allow-run=git,cargo,ectropy,plumb,deno,tea,sh,runseal", ] [[injections]] diff --git a/vocabulary.toml b/vocabulary.toml deleted file mode 100644 index 870a531..0000000 --- a/vocabulary.toml +++ /dev/null @@ -1,3 +0,0 @@ -# vocabulary.toml — registered compound atoms. - -[compound]