Skip to content

itsalt/pepper-orchestrator

v0.11.0MIT

Preview: one orchestrator session runs work across several repositories or parallel streams of one repository - plan, work packages, dispatch with worktrees and locks, PR review with a read-only reviewer agent, owner queue, closing a program when its goal is reached, state in files. Start with /pepper-orchestrator:init <program>, then /pepper-orchestrator:plan <task>.

Changelog

0.11.0 — 2026-10-01, public preview

  • Dedicated Codex CLI skill, native scout/reviewer/verifier roles, prepared ordinary Git worktrees and documented queue/App Server session transport. Keep Claude methodology and per-client models; switch clients only after stopping writers.
  • Local SQLite ID reservations with idempotent retries, explicit legacy import, short process locks and recoverable multi-file state changes.
  • Paired CLAUDE.md / AGENTS.md shared blocks preserve existing instructions and check expected versions. Numbering locks narrow only after producer migration.
  • Windows UTF-8, interpreter selection, CRLF point edits and PowerShell quoting. CI exercises concurrency/recovery on three platforms and installs the built plugin with native Windows Codex. Interactive account permissions/MCP/PR lifecycle remains a separate owner acceptance check. See Windows guide.

0.10.0 — preview, unreleased

Stage 3d: production by the orchestrator, only when the owner handed prod over by a decision D-n (DELIVERY.md sections 5-7).

  • orch.py release --plan writes release/release-sheet-<date>.md (EN/RU): the VERIFIED_TEST packages by repository with the SHA each passed the stand at (the evidence of its verify --env test, else the ledger), migrations from the package's Migrations row, the promote SHA per repository (the stand SHA that contains the others), open defects and self-contained steps with expectations (the owner can release by the sheet too). release_policy: per_package writes a sheet of one package right after its VERIFIED_TEST (never a second sheet for the same package).
  • orch.py release --check [<sheet>]: gates P1-P7 by facts, not status fields. P1: the promote SHA is the tip of origin/<integration_branch> (for ff: on it), contains every stand SHA, and prod has no commit the stand never saw (git rev-list --no-merges; merge commits of earlier promotes aside; ff needs prod to be an ancestor and a clean release_clone of the same origin); it also refuses a sheet planned for other branches or another promote method than orch.yaml has now, and a promote SHA that would ship another unreleased package not in the sheet. P2: every package VERIFIED_TEST. P3: no open defect of severity blocker, critical or high in bugs/. P4: migrations (the sheet or the package file now): with prod_migrations: owner an owner item R-n (once) and stop; with orchestrator the review report says migrations: safe, reversible and backup_prod is set. P5: release_window ("Mon-Fri 10:00-18:00 Europe/Berlin"; IANA zone, UTC or an offset; Пн-Пт too; past midnight allowed) and max_prod_releases_per_day counted from the ledger. P6: prod: orchestrator, no hold, configuration valid after re-reading orch.yaml. P7: after the release.
  • orch.py release --apply [<sheet>]: every gate first, nothing written before; then per repository backup_prod when the batch has migrations (output in the ledger; a failure stops before the promote), the promote (a PR integration_branch -> prod_branch titled [TAG] release <date> with the sheet as body, pending checks waited for, merged with --merge and never --delete-branch, so prod contains the stand SHA; or git push origin <sha>:refs/heads/<prod> from the clean clone, never forced), the prod deploy run, verify --env prod --sha <prod SHA> per package -> PROD, ledger rows and an FYI item in the owner queue. GitHub refusing the promote or red promote checks become an owner item, closed by a later successful promote of the sheet.
  • Failure on prod: defect, delivery.hold for every delivery, rollback_prod (with {previous_sha} = the prod tip before the release) only for a batch without migrations; otherwise, or when the rollback fails, an owner item with the ready command (a revert PR of the promote when no rollback_prod is set). The orchestrator never rolls back a database.
  • Ledger (backlog B1 of the 3c review): release/deliveries.md is written in owner_language (headings and fixed notes), package rows gain Prod run, Prod verification and Rollback columns (the stand rollback moved there from the note), and a Releases table records backup, promote, prod SHA, run, verification and rollback. A ledger written by 0.9.x is upgraded in place on the first write (its rows keep their values; a journal line records it).
  • Backlog B3 of the 3c review: an owner item opened because GitHub refused a merge is closed when a later deliver of the same package merges.
  • Code, not only history (review rev.2). P1 compares trees: the prod tip must carry the code of the stand SHA of the last promote (a hand-resolved promote merge, a revert or a hotfix on prod is red, with the recovery step; a reverted sheet is never offered for verify --env prod). --apply reads the prod tip again right before the merge and refuses when it moved since the gates, and after the promote compares the promoted commit's tree with the stand SHA's tree before any PROD. Any error after the promote (other code, an unknown merge commit, a failing command) ends in a hold, a defect and an owner item. P7 is red before the release when a package has nothing to verify on prod. The P1 fact names the promote merge method (merge_method other than merge is not used for a promote). The P4 migrations item is closed after the release of its batch and not opened again once the owner closed it. Pushes to integration_branch and prod_branch are denied like pushes to the base in the module and orchestrator settings when orch.yaml has a delivery block.
  • lint: release_policy, release_window, max_prod_releases_per_day, promote (and ff needs release_clone), prod_migrations: orchestrator needs prod: orchestrator.
  • orch.py settings orchestrator with prod: orchestrator allows verify_prod and backup_prod verbatim and rollback_prod (ask when rollback is in checkpoints); the promote PR, its merge and the promote push happen only inside release --apply, so no allow rule for gh pr create, gh pr merge or a push to prod (gh pr merge and pushes to the base stay denied).
  • close: the closeout has a Deliveries section from the ledger and the package Version column from the ledger when the orchestrator delivered the package.
  • Documentation: release mode, /pepper-orchestrator:release, concept section 15 (EN/RU), README scenario "Trusted release", the review brief's migrations verdict line.

0.9.1 — preview, unreleased

Hotfix for three field reports (Issues #20, #21, #24).

  • #20, output through a pipe. orch.py and safe_edit.py reconfigure stdout and stderr to UTF-8 (errors='replace') at start: an agent session reads them through a pipe, where Windows uses the ANSI code page (cp1252) and queue failed with UnicodeEncodeError on Russian text. PYTHONUTF8 is no longer needed.
  • #20, process output. All 16 subprocess.run(..., text=True) calls read with encoding='utf-8', errors='replace' (git, gh, claude --version, check, verify and delivery commands).
  • #20, the None in parse_push_trigger - cause established. On Windows subprocess communicate() reads pipes in reader threads (Popen._readerthread: buffer.append(fh.read())). A UnicodeDecodeError there (UTF-8 Cyrillic in a workflow decoded as cp1252, whose bytes 0x81, 0x8D, 0x8F, 0x90, 0x9D are undefined) kills only that thread; communicate() then returns stdout = stdout[0] if stdout else None. On POSIX the same decoding happens in the main thread and raises instead, which is why it did not reproduce there. Fixed by the UTF-8 reading above; besides, parse_push_trigger refuses a non-string text (DeployFormError: "could not be read") and deploy_safe_dirs offers no directory at all when a workflow could not be read, or contains bytes that are not UTF-8 (a replaced character never reaches a candidate name). The fix is guarded by the pipe tests (cp1252 output encoding, C locale); a separate selftest block only illustrates the CPython thread behaviour and would pass on 0.11.0 too.
  • #21, escalation. review-start --round 3+ prints and writes a conditional line ("if the same REVISE items are still open after this review, restart ..."); the owner item opens only when the package is set to REVISE again from round 3 (the round comes from the newest review report), once per open item.
  • #24, PR cell. set <WP> pr takes a pull request URL (a tail such as /files, ?w=1 or #issuecomment-… is cut) or a number (#87, 87), expanded to https://<host>/<owner>/<repo>/pull/<n> from origin_name() of the module repository, only when the host is a forge (never loopback or a private address such as the cloud git proxy); anything else is refused with an example. pr_url() expands a cell that is exactly such a number, so cells written before 0.9.1 work as they are. review-start --pr, merge add --pr and accept validate and normalize the value before anything is written (no partial state); accept extracts the URL from an older cell by search and never refuses because of it; merge add --pr also fills an empty PR cell; close --check reads numbered cells too.
  • The self-test reads child output as UTF-8 itself, so it runs under a non-UTF-8 locale too.

0.11.0 — preview, unreleased

Preview of stage 3c: trusted delivery of merges and the stand, only by an explicit owner decision.

  • delivery block in orch.yaml: merge, stand, prod, prod_migrations (owner | orchestrator, default owner; workspaces before 0.11.0 = all owner), enabled_by, hold. orch.py delivery show and delivery set <level> owner|orchestrator --decision D-n (orchestrator only with a recorded decision). lint: orchestrator without enabled_by or with an unrecorded one, prod: orchestrator without merge: orchestrator, merge_method and run_timeout values. Repository keys: merge_method (merge | squash | rebase), delete_branch, deploy_test, rollback_test ({previous_sha}), run_timeout, integration_branch.
  • orch.py accept <WP> <sha> --report <path>: ACCEPTED at the reviewed revision, journaled.
  • orch.py deliver --check <WP>: gates G1-G10 with facts (accepted revision and report, PR head = accepted SHA, gh pr checks, open/mergeable/base/title, merge queue head and previous merge VERIFIED_TEST or --after-failure D-n, locks, repository checks, owner items marked "blocks delivery" and referenced decisions, "graph: checked" when the package has a Specification, and the delivery level re-read from orch.yaml with no hold). --apply: gh pr merge <n> --repo <origin> --<merge_method> [--delete-branch] (never --admin; a GitHub refusal becomes an owner item), MERGED, merge queue, ledger release/deliveries.md, journal; with stand: orchestrator the deploy run of the merge SHA (gh run list + gh run watch, run_timeout) or deploy_test (stdin closed: no TTY confirmations), then verify --env test and VERIFIED_TEST. A failure: delivery.hold, defect, rollback_test when configured, REVISE text; orch.py hold / unhold; the first lint warning and resume name the hold. Without delivery.merge: orchestrator, deliver refuses with "delivery is done by the owner" and the owner's command.
  • settings orchestrator follows the levels: gh run watch/list, gh pr view/checks, deploy_test, verify_test and rollback_test verbatim (rollback checkpoint = ask). gh pr merge stays denied in every session: the merge happens only inside orch.py deliver --apply.
  • deliver refuses on an invalid delivery configuration (and G10 re-checks it); merge_method other than merge, squash or rebase never reaches gh; --after-failure takes a recorded D-n, journaled and in the ledger; a deploy run still in progress at verification exits 2 (MERGED, no hold); a merge commit GitHub has not reported yet stops before the stand; accept notes the revision in the package's PR cell; the review and owner modes hand merges to deliver when merge: orchestrator.
  • Work package row "Graph"; the review brief checks the graph and writes "graph: checked".
  • deliver mode and command; hard rules 1 and 13 name the only exception; README (EN/RU) "Trusted delivery"; concept 1.8, sections 1, 2 and 12.

0.8.0 — preview, unreleased

Preview of stage 3e: a channel for defects of the plugin itself.

  • orch.py report --check [--command] [--log] [--title] [--expected-actual] [--workaround]: facts of the installed copy and the environment (plugin and version, Claude Code, OS and architecture, Python, shell), the command and the first 30 lines of its output (or the top of the journal), the workspace shape without names. Names from orch.yaml (program, tag, title, coordinator, modules, sessions, repositories, their paths and origin URLs, web hosts, cloud environments, workspace path and branch) become placeholders; home paths, e-mail addresses, secret-looking strings and the terms of a gitignored .private-terms.local are removed; the result is scanned again and nothing is written if anything private remains. Writes bugs/PLUGIN-BUG-<n>.md (owner language) and bugs/PLUGIN-BUG-<n>.issue.md (English), prints the Issue text and a fingerprint: plugin, version and the error line (the exception line of a traceback, else the first line with an error word, else the title) without placeholders, timestamps, SHAs, package ids and numbers. Also covered: owners and non-public hosts of every origin (the home repository too), URL-encoded forms, and NAME_PASSWORD=/NAME_KEY: secrets. --log refuses environment, settings and key files, orch.yaml and mostly KEY=value files.
  • orch.py report --apply [--id] [--confirmed]: without --confirmed and without bug_reports: auto (which needs bug_reports_decision: D-n recorded in decisions.md; lint checks it) it refuses with the question for the owner. The title and the text are scanned again. Searches Issues of ITSalt/PepperSkills by the fingerprint as a quoted phrase (open and closed, open ones preferred, the state journaled); a match gets a comment with this environment's facts, otherwise gh issue create --title "[<plugin> <version>] <title>" --label bug,from-agent,needs-triage (retried with bug only when the labels are missing, with a command for the maintainer). The URL goes to the record, the journal and an FYI owner item. Without gh: steps for the GitHub MCP tools, or the text for manual posting. --security points to SECURITY.md and writes nothing.
  • orch.py report --status (used by resume): recorded defects with their Issues and, with gh, one line when a newer version is on the marketplace's main.
  • report mode and command; hard rule 11 "a defect of the plugin is reported, not patched"; the package section "If a permission is denied" points to it. README (EN/RU) scenario "The plugin broke - report it"; concept 1.7, section 16.
  • Repository: issue form agent-bug-report.yml (labels bug, from-agent, needs-triage), links to SECURITY.md and CONTRIBUTING in config.yml, the indentation of bug.yml fixed (it did not parse), .github/CODEOWNERS (* @ITSalt), PR template with Fixes #N and a private-traces check, CONTRIBUTING sections "Report a defect from an agent", "Fix from an agent" and the merge rule; scripts/test-github-templates.py in check.sh.

0.7.1 — preview, unreleased

Hotfix for Windows: generated settings were rejected by their own validator, so no settings files were written and dispatch refused.

  • One function builds the absolute path of a rule (session_settings.abs_rule_path): //<path> on macOS and Linux (unchanged output, compared byte for byte with 0.7.0 on a fixture); on Windows the documented POSIX form //<drive letter>/<path with forward slashes>; network (UNC) and relative paths are refused with a clear error. Used for the repository, module paths, workspace and both templates.
  • Bash rules with paths use forward slashes; on Windows the orchestrator's settings also allow the python ... and py -3 ... forms of its scripts. --settings paths in start commands use forward slashes on Windows.
  • shell: bash|powershell in orch.yaml (default bash; init --shell, asked explicitly on Windows): with PowerShell, init and dispatch print cd "<dir>"; claude ....
  • Texts: on Windows a worktree does not read .claude/settings.local.json of the main checkout (the 0.6.0 statement held for macOS and Linux only); the plugin passes the rules with --settings on every system. README (EN/RU) section "Windows".
  • Backlog: a Windows runner in CI; PowerShell-specific forms of Bash rules.

0.7.0 — preview, unreleased

Preview of stage 3b: verification of the stand and production by facts, whoever merged and deployed.

  • orch.py verify <WP> --env test|prod [--sha <sha>] [--expect-version <v>]: the expected SHA is the merge commit of the package PR (through gh) or --sha; checks in order: the run of each deploy_workflows entry (a list or {test, prod}) for that SHA on the environment's branch (integration_branch/prod_branch, default the base) finished with success; version_url (with {base_url}/{env}, or per environment) serves the SHA (version_pattern with one group) or --expect-version; verify_test/verify_prod commands run through the shell in the main checkout with ORCH_ENV, ORCH_SHA, ORCH_WP, ORCH_BASE_URL, timeout verify_timeout (default 300 s). Report reports/verify-<WP>-<env>-<date>.md with a table (check, command or target, exit, first output lines with secret-looking fragments redacted, verdict) and a "Live scenario" section. PASS: status VERIFIED_TEST or PROD (a later status is kept). FAIL: status kept, journal, bugs/BUG-<n>-verify-<wp>-<env>.md; an owner item only when the deploy run is missing or failed. WAIT (exit code 2): the deploy run is still queued or running - a journal line, no report, no defect, no owner item. Test needs MERGED or later; an ACCEPTED package is set to MERGED after gh pr view confirms the merge. On prod with a separate prod_branch the expected SHA is the tip of origin/<prod_branch> that contains the merge commit, else a refusal asking for --sha. lint checks version_pattern (compiles) and verify_timeout (positive integer); an invalid pattern at run time is a FAIL. Reports and defects follow the owner language. --dry-run prints the plan and neither runs, calls gh nor writes; without gh it refuses with a hint when a run or a merge commit is needed. verify --list shows packages waiting for test or prod verification.
  • Status vocabulary: VERIFIED_TEST (satisfies dependencies like MERGED).
  • verify mode (references/modes/verify.md, command /pepper-orchestrator:verify), brief references/verify-brief.md, agent orchestrator-verifier (Read, Grep, Glob, Bash; read-only; no model, runs on the orchestrator's model); resume lists what waits for verification.
  • README (EN/RU): "Checking the stand and production by facts"; concept 1.6, section 9.

0.6.0 — preview, unreleased

Preview of stage 3a: session permissions, worktree preparation, message delivery, on-demand locks.

  • orch.py settings <module|all|orchestrator> writes orchestration/settings/<name>.json from orch.yaml and templates/settings/*.json: Read of the repository, module paths and workspace; narrow Bash rules (cat, grep, rg, sed -n, ls, find, head, tail, wc, git status/diff/log/show/branch/fetch/add/commit/switch/restore --staged, gh pr view/list/checks/diff); gh pr create; every command of tests, checks and worktree_setup verbatim, one exact rule per simple command. Deny: gh pr merge, force pushes, pushes to the base in every usual form (origin <base>, HEAD:<base>, *:<base>, refs/heads/<base>, with any tail), force pushes after any argument (--force, -f, --force-with-lease, +<ref>), gh workflow run, gh release, Edit of the workspace, production MCP servers from environments.prod, a module's deploy_prod command, ssh/psql/mysql when guards are set, Skill(<name>) for methodology.forbidden. No allow rule for git push (a * tail would also match refspecs to the base and force flags): pushes of the package branch go to the classifier, or ask with the push checkpoint (Bash(git push *)). Ask: checkpoints (push, pr, deploy_test; default deploy_test). autoMode.environment = $defaults + trusted repository and source control; crossSessionInbound: accept. Idempotent; rules are syntax-checked before writing; <name>.local.json is never touched (and gitignored in new workspaces).
  • dispatch adds --permission-mode <permission_mode> --settings <absolute path> to local start commands, refuses without the file (hint orch.py settings <module>), warns when the file is older than orch.yaml; --no-settings keeps the pre-0.6.0 command. Cloud modules are unchanged.
  • init requires --permission-mode (auto recommended, asked explicitly), writes permission_mode, generates all settings files, prints the orchestrator start command (--name <coordinator_session> --permission-mode <mode> --settings orchestration/settings/orchestrator.json) and the /config alternative, and opens a P-n item with a ready .worktreeinclude for local repositories with streams that have none.
  • lint: permission_mode and checkpoints values are checked; warnings for a workspace without permission_mode, missing or stale settings files, cp/rsync/ln of .env*, secret, key or certificate directories or .claude/ in worktree_setup, backticked names in Shared paths or Resources rows that are not locks, on-demand locks older than lock_stale_hours (default 4).
  • On-demand locks: resources entries {name, mode: on-demand} are not taken at dispatch; the session sends LOCK/UNLOCK (protocol), lock acquire/release as before; status REVIEW (READY), DONE or CANCELLED releases them; overlap --planned reports package resources declared by two packages; lock list marks on-demand locks.
  • Work package template: section 6 "If a permission is denied" (never work around a refusal, QUESTION with the exact text, retry when the classifier is unavailable, LOCK/UNLOCK); the Start command note describes the dispatch flags. Protocol: LOCK, UNLOCK, message delivery. Bootstrap prompt and the dispatch/resume modes check the session name against coordinator_session.
  • Field fixes: init --in-repo accepts a positive paths filter when the branch filter already excludes orch/<program>; --deploy-override D-n without --dir takes the first directory the readable workflows ignore and asks for --dir only when there is none, naming both reasons and both options; backticked text that is not a lock no longer refuses dispatch.
  • README (EN/RU): "Session permissions and permission mode" and the scenario "A stream got a refusal"; concept 1.5, sections 4 and 12.

0.5.0 — preview, unreleased

Preview of stage 2e: implementer model per package, session kind chosen by the owner, cloud environment.

  • init requires --sessions local|cloud (the owner's explicit choice; the mode recommends local, asks and waits for the answer; the choice is journaled); --sessions cloud requires --cloud-environment <name>; in a cloud session (CLAUDE_CODE_REMOTE=true) init --sessions local and dispatch of a local module are refused (a cloud orchestrator works only with cloud sessions). The choice is the program's sessions; repositories and modules inherit it.
  • orch.yaml: models (implement, implement_effort, escalate, escalate_effort), module model/effort, cloud_environment (program, repository or module); lint rejects unknown aliases and efforts and warns about cloud modules without an environment. Without models start commands carry no model flags, as in 0.4.0.
  • Work package template: Model, Effort, Model reason; new-wp fills them; orch.py model changes them together with the start command and journals; dispatch takes the flags from the header.
  • dispatch of a cloud module prints a block (environment, repository and branch, model and effort, claude.ai/code prefill link without the prompt above 2000 characters) and refuses a cloud module without an environment; orch.py cloud-env records the name.
  • review-start from round 3 prints and queues an escalation restart (cd <repo> && claude --resume <session> --model <escalate> locally; model list or /model in the cloud).
  • Agents: orchestrator-scout has model: opus; orchestrator-reviewer has no model on purpose.
  • dispatch --dry-run prints a model note (model <m>, effort <e> or model owner default) next to the locks, and the journal line of DISPATCHING gets the same suffix, also in workspaces created before 0.5.0.
  • Model and effort in package headers are validated: invalid values are lint errors and refuse dispatch; an Effort without a Model is a lint warning. From review round 3 the escalation hint is printed every round, but only one open owner item per package. init --sessions local --cloud-environment is refused.
  • Concept 1.4 (EN and RU): session kind and implementer model, and the /model <name> trap; README "Models and environment".

0.4.0 — preview, unreleased

Preview of stage 2d: program completion. One program, one goal: reached, closed; the next goal is a new program.

  • PLAN.md template: "Goal and completion condition"; plan fills it and does not run on a closed program.
  • Mode close and orch.py close --check | --apply: blockers by fact (non-terminal packages, open PRs of package branches via gh, or branches still on origin until --prs-verified, locks, queued merges, open owner items), module sessions to close; --apply writes reports/closeout-<date>.md from the template (EN/RU), sets state: closed, puts a banner on status.md, journals and commits; a separate home repository archives the workspace to features/_archive/<program> with git mv; an in-repo workspace gets an owner item with the tag and branch-deletion commands (never run by the plugin) and an optional question about keeping the workspace in docs/ of the base branch.
  • orch.py owner carry <id> "<reason>" moves an open owner item to backlog.md.
  • After closing: dispatch, new-wp, lock and merge changes are refused with a hint; lint reads only; among several workspaces a closed one is never picked automatically; resume on a closed program reports the result, and on a finished one proposes close.
  • Mode reopen and orch.py reopen "<reason>".
  • Concept 1.3 (EN and RU), section 21 "Program completion"; README scenario 10.
  • Closing is strict: --prs-verified needs concrete evidence (a PR URL with its state, or list_pull_requests/gh pr list output) and is written to the journal and the closeout; recorded PR URLs are checked with gh pr view; a failing ls-remote, a missing module repository or an uncheckable PR URL blocks until verified; an unwritten completion condition needs --goal-confirmed. close --apply checks the commit conditions before changing anything and a second --apply finishes an unfinished close; the archive move is pushed; a workspace at the root of its repository is not moved. In-repo archive commands run from any clone and are tied to the closeout commit (git push origin <sha>:refs/tags/<tag> && git push origin --delete orch/<p>), and a closed in-repo program whose branch is gone is never pushed again. The closeout has a version column to fill in and a "checks without full evidence" section. After closing set, decide, owner add and review-start are refused too, and lint reports a closed program with a non-terminal package. ORCH_NO_GH=1 hides gh.

0.3.0 — preview, unreleased

Preview of stage 2b: review of module deliveries.

  • Mode review and command /pepper-orchestrator:review: automatic findings, the orchestrator-reviewer agent on the first submission, the revision diff on resubmissions, verdict REVISE/ACCEPTED, report from the review-report template (EN/RU), REVISE message and ACCEPTED hand-over (merge queue, owner merge item). Never merges, approves or comments.
  • orch.py review-start <WP>: automatic findings reusing the stream rules (files outside the allowed paths, shared paths undeclared or without the lock, repository checks) plus a stale merge-base with the branch files the base changed since; report skeleton; status REVIEW; the disposable clone command; --since/--round for resubmissions (git range-diff after a rebase).
  • scripts/review_clone.sh: clone at a SHA into a marked temporary directory, setup, tests, removal (--keep for mutations, --cleanup only for marked directories); never pushes.
  • Agents (Claude Code adapter): orchestrator-reviewer (read-only, disposable clone, mutations, claims as claims, base comparison) and orchestrator-scout (read-only facts, SELECT only).
  • references/review-brief.md: brief template and risk checklists (state machines, migrations, registries and shared types, UI, permissions, integrations).
  • README: "Typical workflows" (EN/RU) with exact calls for local and cloud sessions.
  • review-start reviews origin/<branch> or the given --ref (never a local branch), warns when the local branch differs, stops on a failing fetch (--no-fetch to skip), prints git range-diff <base>..<old> <base>..<new> after a rebase, and puts main @ <sha> in the report header. Review clones use the repository's own review_setup with ORCH_MAIN_CHECKOUT, never worktree_setup. review_clone.sh checks flag values and mktemp.
  • Agents state honestly that MCP tools are not available to them (the orchestrator collects database and GitHub-tool facts) and forbid database clients and ssh through Bash; the cloud review brief allows only reading GitHub tools. The report template has an "Owner questions" section, and small fixes that need the owner's consent become conditional REVISE items.

0.2.1 — preview, unreleased

Preview of stage 2c: cloud sessions over one repository.

  • In-repo workspace: init --in-repo <repo-id> switches to orch/<program> (created without tracking the base), finds a directory every push workflow ignores (on.push paths-ignore, branches, branches-ignore in .github/workflows/*) and refuses when there is none; new orch.yaml keys workspace_mode, workspace_branch, workspace_dir; repository paths may be relative to the workspace's repository (path: .). commit goes only to workspace_branch and always pushes to the same-named remote branch.
  • sessions: cloud on a repository or module: work packages carry a cloud-session prompt (read the package from orch/<program> or inline, branch from the base, PR with the package id, no message back, never merge tools such as mcp__github__merge_pull_request); dispatch prints it (--inline appends the package text).
  • orch.py ready: dispatched packages whose branch is on origin (git ls-remote), with the PR via gh when available; resume describes the no-gh path through the session's GitHub tools.
  • Workspace discovery also finds nested in-repo workspaces (up to four levels below the current directory); lint checks the in-repo keys and warns when the workspace directory is not ignored by every push workflow.
  • scripts/install-skill.sh (repository root): idempotent copy of a canonical skill into ~/.claude/skills for cloud environment setup scripts; README section "Cloud sessions".
  • Skill: hard rule "no merge tools", cloud section, /pepper-orchestrator <mode> calls without plugin commands. Concept 1.2 (EN and RU), section 20 "Cloud sessions".
  • Deploy check is strict: workflows are read from the pushed ref (git ls-tree/git show), a missing ref or any workflow form outside the documented list is a refusal, hidden directories are never candidates and docs/ comes first; an unsafe --dir is refused; the only override is an owner decision (--deploy-override D-n, stored as deploy_check_override). commit of an in-repo workspace refuses while the check fails.
  • dispatch --dry-run writes nothing for any module; a cloud package must be on origin/orch/<program> (same content) before its prompt is printed; with push_deploys a cloud package holds the staging lock and its prompt says to push once.
  • init --in-repo fetches first and reuses an existing origin/orch/<program> (refusing a second workspace); commit refuses a detached HEAD before committing, pushes to the branch's own remote and keeps an existing upstream; repository names are read from GitHub and cloud proxy URLs; ready reports only open PRs with the package id in their body.
  • README setup fragment never fails the environment's setup script; install-skill.sh removes its temporary directory on failure.

0.2.0 — preview, unreleased

Preview of stage 2a: streams in one repository and dispatch. A 0.1.0 workspace works unchanged (orch.py upgrade only adds the two new tables when locks or the merge queue are needed). 0.1.0 modules that share one repository path now get a lint warning (not an error) and are dispatched one at a time; each keeps its own base. To run them in parallel, add a repos entry and turn them into kind: area|domain modules with paths.

  • orch.yaml: repos block (base, branch prefix, worktree root and setup, merge policy, shared paths, resources, checks, deploy workflows) and modules of kind area, domain or repo with paths, session, test_db, ports, tests, methodology; the 0.1.0 module form is kind: repo, paths: ["**"].
  • New orch.py commands: dispatch, overlap, lock acquire|release|list, merge add|done|drop|list, worktrees, upgrade. lint checks module path overlaps, whole-repository modules sharing a repository, lock and merge queue tables.
  • New mode dispatch and command /pepper-orchestrator:dispatch; init handles several modules per repository, reads the repository's branch prefix, asks the owner's language explicitly and refuses a workspace in a module's base checkout (also on commit); resume reads worktrees, finds PRs by branch and package id, foreign writers and stand deploys; owner prints the merge queue in order with waits and recommends batches when merges deploy production.
  • Work package template: stream, worktree, allowed and shared paths, migrations, resources, test database and ports, line, merge slot, methodology limits; generated worktree preparation, delivery (with or without a remote) and start command (claude -w for streams).
  • safe_edit.py --stdin: one or more OLD/NEW blocks, applied all or nothing, no temporary files; lint rejects leftover marker lines; backup fallback when .orch-backup/ cannot be written.
  • P4 identifies a module repository by git common directory and origin URL (linked worktrees and clones included; git older than 2.31 supported); orch/<program> is the only allowed branch.
  • Globs support {a,b} (expanded for matching and overlaps; init keeps commas inside braces); [/] are literal. Dependencies accept module ids with hyphens (WP-ADMIN-UI-01).
  • Locks: shared-path locks collide by glob; unknown resources and paths outside shared_paths are refused; a released lock with a queue stays as a free row, the queue is respected, and a package leaves every queue once it gets its lock; merge done names the waiting packages.
  • push_deploys: true on a repository: delivery sections tell sessions to commit locally and push only with the stand slot. git status in session worktrees uses --no-optional-locks.
  • plan never writes an open P-n's recommendation as decided; the manifest description says where to start.
  • Concept 1.1 (EN and RU): rules P1-P5 in sections 4, 7 and 12, new section 19 on repositories where a push deploys a stand.

0.1.0 — preview, unreleased

Preview of the stage 1 core; formats and commands may change before 1.0.0.

  • Stage 1 core: canonical skill with a mode router and modes init, plan, resume, owner, decide.
  • Workspace CLI orch.py (init, new-wp, set, journal, owner, queue, decide, lint, commit) and safe_edit.py (exactly one match, backup, size check), standard library only, with a self-test.
  • Workspace, work package and bug templates in English and Russian; optional Specification field in work packages and spec_graph: none in orch.yaml as the docking point for a specification graph.
  • Concept: English translation (references/concept.md) and Russian original (references/concept.ru.md).
  • Claude Code short commands in commands/.