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
8 changes: 4 additions & 4 deletions ADAPTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Benny remains dormant. Its copied runtime entry discovers this shared contract i
- A file this fork never changed: apply the change, then check it against the decisions below. The 0.15.25 sync rewrote upstream's new fast-mode sentence in two otherwise untouched forensics playbooks.
- A file this fork deleted, such as `.cursor-plugin/plugin.json`: keep it deleted unless the change removes the recorded reason.

The fork guards catch only the denylisted primitives, so read every change against the decisions in this guide. When `comparisonMayBeTruncated` is true, the file list is incomplete; sync through an intermediate upstream commit. Finish a sync by moving `UPSTREAM.json` and the first line of this guide to the new commit, adding a paragraph below that names what was taken, kept, and skipped, running the [verification](#verification) checks, and refreshing the installations as described under Antigravity integration.
The [fork guards](./docs/ci.md#fork-guards) reject the denylisted Cursor primitives and require each local decision listed in `REQUIRED` in `scripts/check-fork.mjs`, by file and anchor sentence. A decision this guide records without such a rule is guarded only by reading, so read every change against the guide. When a sync changes a guarded decision on purpose, update its section here and its rule in the same commit. When `comparisonMayBeTruncated` is true, the file list is incomplete; sync through an intermediate upstream commit. Finish a sync by moving `UPSTREAM.json` and the first line of this guide to the new commit, adding a paragraph below that names what was taken, kept, and skipped, running the [verification](#verification) checks, and refreshing the installations with the commands under [T3 Code overlay](#t3-code-overlay).

## Upstream behavior retained

Expand Down Expand Up @@ -57,7 +57,7 @@ T3 Code runs Codex or Claude Code underneath, so it is an overlay on the selecte

After maintained-source changes, refresh the existing installations with `agy plugin install <source>`, `codex plugin add pstack-codex@personal` for this machine's existing Codex ID, and `claude plugin update pstack@pstack-local`. Do not flatten pstack skills into shared standalone names or restore retired paseo aliases.

The `0.15.25-shared.3` T3 update keeps the same shared configuration and adds a read-only `config.mjs resolve --host t3` preview for one role or panel. `bin/t3-targets.mjs` maps exact targets and effort against the current thread's capability catalog, preserves xagent entries and repeated/required panel members, and rejects unavailable explicit targets without model substitution. Missing effort controls remain visible warnings with no claim of delivery. T3 children now use application-owned `isolation: "worktree"`; briefs and acceptance evidence must distinguish the parent commit from uncommitted or separately prepared input. The catalog no longer assumes particular vendors are absent. `scripts/t3-targets.test.mjs` and the T3 contract guard protect these boundaries, and [T3 live verification](./docs/t3-verification.md) separates selection, task metadata, provider observations and artifact acceptance. chhoumann/t3-pstack's declared adaptation checks and creedants/pstack-t3's catalog-backed role resolution informed these boundaries; their code, model defaults, automatic fallback, separate configuration and standing coordinators are not imported.
The `0.15.25-shared.3` T3 update keeps the same shared configuration and adds a read-only `config.mjs resolve --host t3` preview for one role or panel. `bin/t3-targets.mjs` maps exact targets and effort against the current thread's capability catalog, preserves xagent entries and repeated/required panel members, and rejects unavailable explicit targets without model substitution. Missing effort controls remain visible warnings with no claim of delivery. T3 children now use application-owned `isolation: "worktree"`; briefs and acceptance evidence must distinguish the parent commit from uncommitted or separately prepared input. The catalog no longer assumes particular vendors are absent. `scripts/t3-targets.test.mjs` and the fork guards' required T3 anchors protect these boundaries, and [T3 live verification](./docs/t3-verification.md) separates selection, task metadata, provider observations and artifact acceptance. chhoumann/t3-pstack's declared adaptation checks and creedants/pstack-t3's catalog-backed role resolution informed these boundaries; their code, model defaults, automatic fallback, separate configuration and standing coordinators are not imported.

The `0.15.25-shared.4` follow-up adds opt-in T3 candidate roles and same-family `@latest` selectors. A candidate role chooses one provider, preferring the current parent or the first configured candidate; an explicit `--provider` can select another configured candidate. Failures never walk the list. Family selection uses canonical numeric releases in the task's live catalog, freezes concrete IDs for that task and preserves exact pins. It does not add a second registry or change xagent defaults. Each new delegate is classified by its own phase and difficulty; ordinary implementation returns to its ordinary role after a hard design. The optional `hardest architect runners` panel supports Fable/Astra designs without rewriting other panels. Native roles and their inheritance remain separate. Both installed helpers must be upgraded before storing the new candidate-object shape, and existing sessions must reload the new runtime. [Routing examples](./docs/t3-model-routing.md) cover the contract and compatibility boundary.

Expand All @@ -79,9 +79,9 @@ For all CI checks, including strict TypeScript checks, Bun tests and reproducibl

The CLI tests use real Git checkouts and subprocesses with vendor stand-ins, including staged/committed read-only violations, misleading verdicts, timeout and cancellation. Vendor acceptance pins the fixture's test contents and checks the worker's successful test receipt against its final source before independently rerunning it. The shared verification runner gives each command a fresh Python bytecode-cache prefix and disables cache writes; `-B` alone can still load stale bytecode after an equal-size edit in the same second. A worker receipt is not sufficient without that independent run. Importing the test, rewriting it, or reusing a receipt from older code cannot satisfy the full acceptance gate.

Run `scripts/xagent-e2e.sh` after changing `bin/xagent*` or upgrading an agent CLI; it calls every vendor. Run `python3 scripts/pstack-host-e2e.py <new-run-dir>` for actual Claude and Codex hosts executing swarm then interrogate through their current shared policy on synthetic fixtures. It records source hashes, policy, worker receipts and independent tests, and checks that the parent verified the final source and that each configured reviewer saw it in a separate worktree. It checks `xagent:` entries through their receipts, counting a `meta.json` as an xagent attempt when either marker `bin/xagent` creates first (`prompt.md`, `agent.log`) sits beside it, so a broken one still fails, keyed by mode, agent and model, and listing any other `meta.json` under the evidence directory as ignored, and native entries through the host's own log, parsed by `scripts/e2e-native-evidence.py`: Claude's stream-json Agent calls and their resolved model, or Codex's persisted session rollouts (the Codex host therefore runs without `--ephemeral`). A native dispatch's checkout comes from its subagent's own tool calls: the Claude events whose `parent_tool_use_id` is its Agent call, or the Codex child rollout (whose task payload is encrypted). Those calls must use exactly one checkout under the run other than the parent, and it must be a linked worktree at the fixture base. The dispatch writes when it edited that checkout with its host's file-edit tool and the edit succeeded (Claude `Write`/`Edit` with a successful tool result, a completed Codex `FileChange`), and reviews when it edited nothing there and the checkout holds the final `stats.py`. A native review must also bracket its work, as xagent's `snapshot_before` and `snapshot_after` do: its subagent's own first and last shell commands in that worktree run the absolute path of `scripts/e2e-snapshot.py` with a Python interpreter (optionally after a `cd`, with nothing else in the same command), every other shell command there falls between them, and every snapshot the tool prints for that worktree (leaving ignored test receipts and caches out) matches the worktree's state when the run ends. The snapshot lines come from the subagent's own tool results or Codex `aggregated_output`, which the host cannot write, and an echoed line does not count because it never ran the tool; forging one would take rewriting the tool or shadowing `python3` on PATH, which is outside the threat model of an acceptance test for cooperating agents. A shell edit during a review, before it, or after it therefore stops it counting. Shell edits are not writer evidence, so a writer that edits only through the shell cannot fill the writer slot. When the effective policy sets `reasoning_effort`, a worker fills a role only if its xagent receipt, Claude Agent call or Codex `spawn_agent` records an effort level; the level itself may differ, since poteto-mode adjusts it per task. Each checkout belongs to one owner, a worker (kind, agent and model) in one mode, so an xagent retry or a native writer's follow-up fix may reuse its worktree; and each configured writer or reviewer slot needs an attempt in a checkout no other slot used, so two reviews in one worktree count once. A missing log or a dispatch that used no path is reported as a gap and fails the check. It never changes preferences. Each worker attempt is limited to xagent's default 900 seconds with one retry, not doubled. Both live harnesses use `timeout` with a kill-after limit for the outer host process; host workflows default to 6 attempts × (900-second limit + xagent's termination grace + 30 seconds of start-up and snapshots) + 600 seconds of host work + both final checks, so the writer, review and post-fix re-review rounds can each retry, configurable with `--host-timeout`. Verification commands use `scripts/e2e-process.py` with a 30-second default deadline, process-group termination and bounded output collection; the host harness exposes `--check-timeout`. A verification timeout remains a failed check with logs and exit code 124.
Run `scripts/xagent-e2e.sh` after changing `bin/xagent*` or upgrading an agent CLI; it calls every vendor. Run `python3 scripts/pstack-host-e2e.py <new-run-dir>` after changing cross-agent routing: actual Claude and Codex hosts run swarm, then interrogate, through their current shared policy on synthetic fixtures. The host harness accepts a run only on evidence the host cannot write, such as xagent receipts, the host's own logs, snapshots the snapshot tool printed, and its own independent tests, because the host's success report is the thing under test. Its acceptance rules live in the script's module docstring, beside the code and tests that enforce them, so change them there. Neither harness changes preferences. Both bound the outer host process with `timeout` and a kill-after limit, and a verification timeout is a failed check with exit code 124.

The runtime checks start with `scripts/check-fork.mjs`, which validates the manifests, all SKILL.md and agent frontmatter, each skill's link to the shared runtime contract, local links, and a denylist of the Cursor-only wording this guide replaces; see [Fork guards](./docs/ci.md#fork-guards). Use a fresh Codex app-server skills/list and Claude `plugin details` to verify inventory; a static validator alone is not a discovery or behavioral test.
The runtime checks start with `scripts/check-fork.mjs`, which validates the manifests, all SKILL.md and agent frontmatter, each skill's link to the shared runtime contract, local links, a denylist of the Cursor-only wording this guide replaces, and the files and anchor sentences of the local decisions it requires; see [Fork guards](./docs/ci.md#fork-guards). Use a fresh Codex app-server skills/list and Claude `plugin details` to verify inventory; a static validator alone is not a discovery or behavioral test.

Rebuild the `orch` and `watch-pr` bundles with `python3 scripts/build-runtime.py` when their sources, dependencies or builder change. Use the Bun version in `.bun-version` and locked development dependencies. `python3 scripts/build-runtime.py --check` compares a temporary build with the working tree without writing artifacts. Node runtime helpers never download dependencies.

Expand Down
9 changes: 9 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Agent guide

This repository is the Codex and Claude Code fork of cursor/plugins `pstack`, pinned in `UPSTREAM.json`. [ADAPTATION.md](ADAPTATION.md) records each local decision and its reason.

- Gate: `bash scripts/check.sh` (`runtime` or `build` for one half). On macOS, put coreutils' `gnubin` first in `PATH` as [docs/ci.md](docs/ci.md) shows.
- Upstream sync: run `node scripts/check-upstream.mjs`, then merge each changed file by the rules in [Upstream sync](ADAPTATION.md#upstream-sync). Never copy an upstream directory over this tree.
- A [fork guard](docs/ci.md#fork-guards) failure means a sync dropped a recorded decision or brought back Cursor-only wording. Fix the text, not the guard.
- Host caches and installed copies are generated installation artifacts, never edit targets. Edit this checkout.
- After maintained-source changes, refresh the installations with the commands in the "After maintained-source changes" paragraph under [T3 Code overlay](ADAPTATION.md#t3-code-overlay).
44 changes: 41 additions & 3 deletions docs/ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ bash scripts/check.sh build
| Skills | a skill directory lacks `SKILL.md`, a frontmatter `name` differs from its directory or agent file name, a `description` is empty, or a `SKILL.md` has no link to `references/runtime.md` |
| Links | a Markdown link outside code points at a missing file or leaves the repository |
| Manifests | a manifest is not valid JSON or loses its name (`pstack`, or `pstack-codex` for Codex), or the root `plugin.json` references `agent-plugins.org`, whose `$schema` makes Codex truncate each skill to 8,000 bytes |
| T3 contract | the T3 runtime loses the catalog-backed resolver, application-owned worktree isolation, completed status or available-result requirement |
| Required | a local decision in the `REQUIRED` table of `scripts/check-fork.mjs` loses its file or anchor sentence, such as the verification-skill replays, xagent, explicit PR, push and merge authorization, fast mode only on request, watch-pr `--once`, or the T3 dispatch contract; or a rule cites an adaptation-guide section that no longer exists |

When the denylist fires after a sync, rewrite the sentence the way the adaptation guide records for that sync instead of swapping tokens. A file that names a pattern on purpose, such as an adapter listing the fields it forbids, goes in that rule's `allow` list in `scripts/check-fork.mjs`; `skills/poteto-help/SKILL.md` is the one allowed `disable-model-invocation`. An allowed file that stops matching fails as stale, so an allowance cannot outlive the sentence it excuses. `scripts/check-fork.test.mjs` plants each violation in a copy of the tree and checks that it is reported.
When the denylist fires after a sync, rewrite the sentence the way the adaptation guide records for that sync instead of swapping tokens. A file that names a pattern on purpose, such as an adapter listing the fields it forbids, goes in that rule's `allow` list in `scripts/check-fork.mjs`; `skills/poteto-help/SKILL.md` is the one allowed `disable-model-invocation`. An allowed file that stops matching fails as stale, so an allowance cannot outlive the sentence it excuses.

When a required rule fires after a sync, restore the local decision in the synced file; each problem names the rule, its anchor, and the guide section that records the decision. If the decision itself changes, update that section and the rule in the same commit. `scripts/check-fork.test.mjs` plants each violation and each lost decision in a copy of the tree and checks that it is reported, and fails when a required rule has no planted loss.

## Update the distributed bundles

Expand Down Expand Up @@ -72,7 +74,43 @@ Each job has a ten-minute limit. A newer run on the same PR or ref cancels the o

The macOS runtime job installs coreutils. Ubuntu already supplies GNU `timeout`.

After the first successful GitHub run, select all three check names in branch protection if they must block merges. Adding the workflow does not configure branch protection.
### Branch protection

`main` is protected, and the protection also applies to administrators (`enforce_admins`). GitHub rejects direct pushes to `main`, so every change lands through a pull request. A merge needs these three checks, reported by GitHub Actions (app ID 15368):

- `Runtime (ubuntu-24.04, Node 22.18.0, Python 3.9)`
- `Runtime (macos-15, Node 24, Python 3.14)`
- `Build and types`

A branch does not need to be up to date with `main` before it merges (`strict` is off), no review approval is required, and force pushes to `main` and its deletion are blocked.

Each check name is the job's `name` in the [workflow](../.github/workflows/ci.yml), with the matrix `os`, `node`, and `python` values filled in. A pull request that changes a matrix value or a job name reports its checks under new names. It never reports the old required names, so it waits for them indefinitely, and `enforce_admins` leaves no bypass. Update the protection when that pull request is ready to merge. Open pull requests that ran before the change keep the old names until CI runs on them again. `PUT` replaces the whole protection, so send every setting, not only the new check list:

```sh
gh api -X PUT repos/mtmtian/pstack-remix/branches/main/protection --input - <<'EOF'
{
"required_status_checks": {
"strict": false,
"checks": [
{ "context": "Runtime (ubuntu-24.04, Node 22.18.0, Python 3.9)", "app_id": 15368 },
{ "context": "Runtime (macos-15, Node 24, Python 3.14)", "app_id": 15368 },
{ "context": "Build and types", "app_id": 15368 }
]
},
"enforce_admins": true,
"required_pull_request_reviews": null,
"restrictions": null,
"allow_force_pushes": false,
"allow_deletions": false
}
EOF
```

Read the result back with `gh api repos/mtmtian/pstack-remix/branches/main/protection`. To remove the protection entirely:

```sh
gh api -X DELETE repos/mtmtian/pstack-remix/branches/main/protection
```

## Checks that still require a host

Expand Down
Loading
Loading