framework: make tool discoverability, workspace placement and model tiering mechanical (#1174)
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful

This commit was merged in pull request #1174.
This commit is contained in:
Mos
2026-08-13 14:21:22 +00:00
parent 41749bbd33
commit afdaa6d0e6
11 changed files with 2865 additions and 8 deletions
@@ -11,22 +11,105 @@ All tool suites are located at `~/.config/mosaic/tools/`.
Mosaic wrappers at `~/.config/mosaic/tools/git/*.sh` handle platform detection and edge cases. Always use these before raw CLI commands.
This index is complete and is kept complete mechanically: `tools/quality/scripts/check-tools-index.sh`
fails CI when a wrapper ships without an entry here, or when an entry here names a wrapper that no
longer exists. A wrapper missing from this list is, from inside an agent session, indistinguishable
from a wrapper that was never written — which is how the APPROVE/APPROVED incident below happened.
Every command takes `--help`. All of them accept `--login <account>` to pin the acting identity;
supply it explicitly on any host where the provider CLI's default account is an admin.
| Issues | |
| ------------------ | --------------------------------- |
| `issue-create.sh` | Create an issue (Gitea or GitHub) |
| `issue-view.sh` | Show one issue |
| `issue-list.sh` | List issues |
| `issue-edit.sh` | Edit title/body/labels/milestone |
| `issue-comment.sh` | Add a comment |
| `issue-assign.sh` | Assign or unassign |
| `issue-close.sh` | Close an issue |
| `issue-reopen.sh` | Reopen a closed issue |
| Pull requests | |
| ---------------- | --------------------------------------------------------- |
| `pr-create.sh` | Open a pull request |
| `pr-view.sh` | Show one PR |
| `pr-list.sh` | List PRs |
| `pr-diff.sh` | Fetch a PR's diff |
| `pr-metadata.sh` | PR metadata as JSON (head SHA, base, state, mergeability) |
| `pr-review.sh` | **Place a review verdict — see the dialect note below** |
| `pr-ci-wait.sh` | Block until the PR's CI reaches a terminal state |
| `pr-merge.sh` | Merge a PR |
| `pr-close.sh` | Close a PR without merging |
| Milestones | |
| --------------------- | ------------------ |
| `milestone-create.sh` | Create a milestone |
| `milestone-list.sh` | List milestones |
| `milestone-close.sh` | Close a milestone |
| Gates and guards | |
| ----------------------- | --------------------------------------------------------------------------------------------------------- |
| `ci-queue-wait.sh` | CI queue guard — required before push/merge (see below) |
| `push-guard.sh` | Refuse verifications that pass for the wrong reason (e.g. green against an unpushed tree) |
| `mutate-push-guard.sh` | Regenerate the guard's mutation-coverage table from measurement, so the table cannot drift from the guard |
| `verify-clean-clone.sh` | Prove the **committed** artifact runs, from a clean clone — not the working tree |
| Context | |
| -------------------- | ---------------------------------------------------------------------------------------- |
| `detect-platform.sh` | Resolve the provider (Gitea vs GitHub) for the current repo; every other wrapper uses it |
| `lane-brief.sh` | Live dispatch brief for a repo "lane" (milestone/label) straight from the provider |
| Workspace | |
| -------------------- | ------------------------------------------------------------------------ |
| `mosaic-worktree.sh` | Create/list/remove git worktrees — **the only supported way**; see below |
| `wrapper-guard.sh` | PreToolUse hook that enforces the two rules above; not called by hand |
**Workspace placement is derived, not chosen.** `mosaic-worktree.sh new <branch>` takes a branch
name and nothing else. Every path comes out of `git worktree list --porcelain` — main worktree,
repo name, parent dir, then `<parent>/<repo>-worktrees/<branch-slug>`. There is no placement flag
because a decision an agent has to make is a decision that drifts: the rule "big work goes on a work
filesystem" already existed in prose and 255 GB accumulated in `$HOME` across 842 directories
anyway, under five simultaneous conventions on a single host.
```bash
# Issues
~/.config/mosaic/tools/git/issue-create.sh
~/.config/mosaic/tools/git/issue-close.sh
~/.config/mosaic/tools/git/mosaic-worktree.sh new <branch> [--from <base>]
~/.config/mosaic/tools/git/mosaic-worktree.sh path <branch> # derived path, no side effect
~/.config/mosaic/tools/git/mosaic-worktree.sh list # this repo's worktrees + state
~/.config/mosaic/tools/git/mosaic-worktree.sh rm <branch> # removal is part of the task
~/.config/mosaic/tools/git/mosaic-worktree.sh gc [--apply] # reclaim clean + fully-pushed ones
```
# PRs
~/.config/mosaic/tools/git/pr-create.sh
~/.config/mosaic/tools/git/pr-merge.sh
Worktrees rather than clones, because `git worktree list` makes every checkout enumerable — a bare
clone dropped somewhere on disk can never be safely reclaimed, so it is never reclaimed. `rm` and
`gc` decide by **evidence, never by size or age**: a worktree is reclaimable only when
`git status --porcelain` is empty _and_ `git rev-list --count HEAD --not --remotes` is 0. Anything
else is preserved and reported. `--force` exists and is yours to type deliberately.
# Milestones
~/.config/mosaic/tools/git/milestone-create.sh
`wrapper-guard.sh` is registered as a Claude Code `PreToolUse` hook on `Bash` (see
`runtime/claude/settings.json`). It blocks exactly three things and lets everything else through:
a `git clone`/`git worktree add` targeting `$HOME`; a raw provider-API **write** to an endpoint that
already has a wrapper above (reads are untouched — they are how you gather evidence); and the
literal `"event": "APPROVE"`. For a genuine gap no wrapper can express, prefix
`MOSAIC_WRAPPER_OVERRIDE=1`. Reaching for the override twice for the same call means the wrapper has
a missing flag — extend the wrapper.
```bash
~/.config/mosaic/tools/git/issue-create.sh --help
~/.config/mosaic/tools/git/pr-review.sh --pr 42 --event APPROVED --body "..."
# CI queue guard (required before push/merge; defaults to the checked-out branch)
~/.config/mosaic/tools/git/ci-queue-wait.sh --purpose push|merge
```
**Review dialect — the reason `pr-review.sh` is not optional.** Gitea's approve event is
`APPROVED`; GitHub's is `APPROVE`. Send GitHub's spelling to a Gitea host and it answers **HTTP
200**, files the review as PENDING, and then rejects the submit with `422 review stay pending` — the
verdict looks placed and is not. (`REQUEST_CHANGES` is spelled identically on both, so only the
approve path carries the trap.) `pr-review.sh` sends the correct token for the detected provider.
Whatever you use, re-read `GET /pulls/{n}/reviews` and assert the state before reporting a verdict
placed.
The guard exits nonzero for any provider-asserted non-green, missing, or malformed CI state. If credentials or the provider are unavailable, it emits `CANNOT_ASSERT` and writes a JSONL audit record. Push degrades to exit 0 so recovery work is not bricked; merge holds with retryable exit 75 until the provider recovers, then self-clears without manual reset. Neither outcome is evidence that CI was clear. `pr-merge.sh` automatically inspects the exact PR head repository and full commit SHA rather than its `main` base; this also handles fork PRs without branch-name ambiguity. Pass `--expect-head <approved-full-sha>` to bind a commit-specific review or merge-gate verdict; Gitea uses atomic `head_commit_id` and GitHub uses `--match-head-commit`.
### Code Review (Codex)