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
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{
"name": "paacm",
"description": "PAACM: the Verified Single-Writer Loop for agentic coding. One writer agent, read-only explorer and reviewer subagents, tests protected after approval, and completion gated on executed checks.",
"version": "3.5.0",
"version": "3.5.1",
"source": "./plugins/paacm"
}
]
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{
"name": "paacm",
"description": "PAACM: the Verified Single-Writer Loop for agentic coding. One writer agent, read-only explorer and reviewer subagents, tests protected after approval, and completion gated on executed checks.",
"version": "3.5.0",
"version": "3.5.1",
"source": "plugins/paacm"
}
]
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

## 3.5.1 — Fixes from a team's upgrade

Reviewing a team project's upgrade to 3.5.0 found these problems in the runtime. Each fix is covered by a test in `test/review-fixes.test.mjs` that failed before it.

- **An error no longer lets the agent stop unverified.** An invalid `.agent/paacm.json` crashed the stop hook, which is not configured to fail closed, so the turn ended without the gate; 3.4.1 blocked. It is now reported like the configuration errors the gate itself finds. An error while judging one project (the session's own, another worktree, a checkout below a non-git session folder) no longer discards the other projects' results: it blocks that stop once and names the error. On the continuation the stop is let through, as a hook error the IDE shows.
- **A gate log that cannot be written no longer loses the result.** A full disk, or a directory named `gate.log`, made `paacm gate` crash after it had recorded the result. It now warns and keeps the result and the `paacm gate: exit` line. An untracked file that cannot be inspected, such as a symbolic link loop, no longer breaks the gate either.
- **A missing script is not a missing tool.** Exit 127 for a command named by a path inside the project (`./scripts/build.sh`), which a change may have removed or renamed, is an ordinary failure again; only the failing command's own message counts. The verify instructions say so. A program that is not installed, also one named by a path outside the project, is still a missing tool.
- **The protect hook fails closed when git cannot run.** With git not on the hook's `PATH`, or refusing the folder (`safe.directory`), an edit in a sibling worktree was taken to be outside every project and allowed. It is now refused, with git's own message and the folder it failed in.
- **No second gate run and no repeated nudge for an unchanged working tree.** A stop that answers the finish nudge reuses a passing gate for the same working tree however old it is (a failing one is run again); before, a tree with uncommitted changes ran the whole gate again once 15 seconds had passed. A nudge is given once for a working tree and phase, not once every 15 seconds, so an agent waiting for the human is not nudged at every turn. The working-tree fingerprint now includes the size and modification time of untracked files.
- **The review input keeps secrets out.** Untracked files named like secrets (`.env`, `.env.*`, `*.pem`, `*.key`, `*.p12`, `*.pfx`, SSH private keys) are listed by name, anywhere in the repository; their content no longer goes to the reviewers.
- **A test added after a blocked task's approval does not hold other worktrees.** Only files that existed when the tests were approved count. A change to them that arrived from the base branch still holds every worktree that has it, as in 3.5.0, because git cannot tell a reviewed change from one the writer made a remote-tracking ref for. The troubleshooting guide says how to settle it.
- **A task state that cannot be read is reported.** When `task start` or `approve-tests` checks for blocked tasks, an unreadable `state.json` or tasks folder is skipped with a warning instead of silently.
- **The shell guard checks long option lists in linear time.** A git command with many `-c` options made the hook-skipping pattern backtrack exponentially; about 40 of them exceeded the hook's timeout, and the command was refused.

Not changed: when the session folder is not a git repository, the stop gate still runs the checks, and the post-edit hook the `postEdit` commands, of each checkout below it that the session edited. Making that opt-in is a change to the method, for a later release. The upgrade does not remove the session baselines that 3.4.x left in the temporary folder (`paacm-sessions` in the system's temporary directory); delete them when no 3.4.x session runs on the machine.

**Upgrading.** `paacm upgrade` to 3.5.1; nothing to configure.

## 3.5.0 — Finishing, worktrees and shared machines

Running 3.4.1 on a team project (several people on one server, linked worktrees, headless agent runs) showed where the runtime enforced less than the method asks. Each fix is covered by tests that failed before it ([ADR 0021](docs/method/adr/0021-finishing-worktrees-and-shared-machines.md)).
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ The [user guide](docs/guide/README.md) covers setup, writing requests, supportin

## Status and limits

PAACM 3.5.0 is a complete implementation of the specification for Claude Code and Cursor, including project extensions for adapting it to a repository's own conventions ([guide](docs/guide/extending.md)). Markdown instructions are guidance; the enforcement comes from the hooks, the IDE's permissions and its sandbox. Use the power layer or a plugin when enforcement matters. The method's evidence comes from published studies and vendor guidance, not from your code: [evaluate it](docs/guide/evaluation.md) on tasks from your own history before relying on a claim that it helps.
PAACM 3.5.1 is a complete implementation of the specification for Claude Code and Cursor, including project extensions for adapting it to a repository's own conventions ([guide](docs/guide/extending.md)). Markdown instructions are guidance; the enforcement comes from the hooks, the IDE's permissions and its sandbox. Use the power layer or a plugin when enforcement matters. The method's evidence comes from published studies and vendor guidance, not from your code: [evaluate it](docs/guide/evaluation.md) on tasks from your own history before relying on a claim that it helps.

Upgrading from PAACM 2.0.0: see [upgrading-from-2.md](docs/guide/upgrading-from-2.md).

Expand Down
2 changes: 1 addition & 1 deletion docs/guide/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ Run the same manifest in your CI, so that every pull request passes the same com
With the plugin, the repository has no copy of the runtime; pin the kit's version instead:

```yaml
- run: npx github:Hyper-AI-Lab/hyper-agents#v3.5.0 check --tier full
- run: npx github:Hyper-AI-Lab/hyper-agents#v3.5.1 check --tier full
```

Add `--quiet` to show only the check lines and the end of a failing check's output. Held-out acceptance tests for high-stakes work ([phase 7](../method/ALGORITHM.md#phase-7-verify)) also run in CI, outside the agent's workspace.
Expand Down
8 changes: 7 additions & 1 deletion docs/guide/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,18 @@ It closes only a finished task, and the message says what is missing:

### "The gate is green, but task … is still …"

The stop hook nudges once when the agent tries to stop with an open task whose gate passes, and once when a STANDARD or DEEP task changed files without recording its phases. If the agent is waiting for your answer, it says so and stops again; the second stop is always let through. Claude Code shows a nudge as stop hook feedback, not as a hook error; only a failing gate is reported as a blocking error.
The stop hook nudges once when the agent tries to stop with an open task whose gate passes, and once when a STANDARD or DEEP task changed files without recording its phases. If the agent is waiting for your answer, it says so and stops again; the second stop is always let through, and the nudge is not repeated while the working tree and the phase stay the same, however long you take to answer. Claude Code shows a nudge as stop hook feedback, not as a hook error; only a failing gate is reported as a blocking error.

### A check fails with exit code 127

The check could not find a command (on Windows, cmd says the command "is not recognized as an internal or external command"): the tool is not installed where the agent runs, or not on the `PATH` of the IDE. The gate prints a hint, and the agent stops with `BLOCKED: trigger 2` instead of changing code. Install the tool and say "continue", or take the check out of the tier the task needs. `doctor` lists the check programs it cannot find.

A command named by a path, such as `./scripts/build.sh`, is a file of the project, not a tool: when the shell cannot find it, a change probably removed or renamed it, and the gate reports an ordinary failure for the agent to fix.

### "task … (in the worktree at …) is blocked, and these files frozen by its approved tests changed since"

Another worktree of the same repository has a blocked task with approved tests, and one of the files those tests froze (a test, `.agent/checks.conf` or `.agent/paacm.json`) changed in a commit this worktree contains, for example through a merge of the base branch. PAACM does not let a new task start or approve tests over it, because that would let a frozen-file change through without you. The task's owner resumes it in that worktree (`paacm task resume <id>`), settles the change with you (`reopen-tests`, then `approve-tests`), and finishes or blocks it again. A test file added after the approval does not count. Do not leave blocked tasks behind on a shared machine.

### "PAACM could not record the session baseline"

The session start could not write to `paacm-sessions/` in the worktree's git directory, for example because the clone belongs to another account. The session works normally; only the stop hook's list of files changed without a task falls back to every uncommitted file. Give each person their own clone ([shared machines](setup.md#shared-machines)).
Expand Down
2 changes: 1 addition & 1 deletion docs/method/ALGORITHM.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ Each phase lists its entry condition, the steps, the artifact it produces and it
- Optionally, run best-of-N: two to four worktree-isolated attempts, filtered by the regression and acceptance tests, then selected by the reviewer. The selector MUST be independent of the tests the writer saw.
5. When the `claude-security` plugin is installed, high-stakes work also runs its scan of the changes at high effort; confirmed findings are fixed within the plan or end in `BLOCKED:`.
6. A project MAY configure a mutation check in the `full` tier. When it fails, the writer MUST NOT edit the frozen tests; it reports the surviving mutants and stops with `BLOCKED:` (trigger 4) for the human to decide on more tests.
7. The gate saves its full output in the task folder (`gate.log`), so the writer can keep its console output short (`paacm gate --quiet`) and the reviewer can read the evidence. A check that cannot find a command (exit 127) is reported as a missing tool: an environment problem for the human (trigger 2), not a reason to change code.
7. The gate saves its full output in the task folder (`gate.log`), so the writer can keep its console output short (`paacm gate --quiet`) and the reviewer can read the evidence. A check that cannot find a program (exit 127) is reported as a missing tool: an environment problem for the human (trigger 2), not a reason to change code. A command named by a path in the project is an ordinary failure, since the change may have removed or renamed it.
8. The gate's configuration warnings say whether a change to a protected file arrived through a merge of commits a remote-tracking branch has (such as the base branch). That is context, not an exemption: the report accounts for every warning, saying who approved the change or, for a merged one, where it was reviewed.
- **Exit:** the gate is green at the route's tier and the diff audit is clean.
- **Rule:** after **three consecutive gate failures on the same check** (the retry cap), the writer MUST stop and escalate (trigger 5) instead of trying again.
Expand Down
6 changes: 6 additions & 0 deletions docs/project/requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,9 @@ Evidence (`npm test`, 160 tests):
- A fresh-context review of the release found twelve problems, eleven of them reproduced, and four plausible ones; each fix has a test that failed before it: the stop hook keeping the gate result it ran itself; moving into a worktree or sub-folder never releasing the session's failing gate; checkouts below a non-git session folder protected; a locally merged branch staying the task's own in the audit; no new task over a blocked task's changed frozen files; a review diff that survives untracked nested repositories, keeps skip-worktree files out, does not rehash every file, splits type changes and submodules correctly and cannot overflow on backtick runs; FAST next steps through phase 7; missing tools ending in `BLOCKED:` trigger 2; more ways to skip git hooks; doctor's program reader; every lefthook configuration file; a gate log bounded in memory.
- An independent audit of the branch found seven more problems, all reproduced, and one plausible; each fix has a test that failed before it: a new worktree starting a task and approving tests over a blocked task's changed frozen files; a remote-tracking ref the writer made turning its own configuration change into one "reviewed there" (a merged change is now only marked `through a merge`, and `git update-ref` asks); `git commit -n` before `&&`, `;` or a redirect, a quoted `core.hooksPath` and `HUSKY='0'` passing the shell guard; with the agent's current directory in one checkout, a sibling checkout below a non-git session folder left unprotected and its failing gate not holding the stop; a nested `.agent/paacm.json` setting up a second set of protect rules; a symbolic link in the task folder hiding the evidence list; `docker build --push` allowed. The plausible one, private file modes on Windows, is documented: the modes apply on Linux and macOS.
- Two Linux accounts sharing one temporary folder (run as two unprivileged uids): with 3.4.1 the second account's session start exits 1 with `EACCES` and emits no context; with 3.5.0 both get their context and each baseline folder is private to its owner.

## Release 3.5.1

Release 3.5.1 fixes what a review of a team project's upgrade to 3.5.0 found in the runtime (R3, R4, R12): an error in the stop hook (an invalid configuration, one project among several) no longer lets the agent stop unverified, a gate log that cannot be written keeps the result, a missing script is an ordinary failure while a missing program stays a missing tool, the protect hook fails closed when git cannot run, an unchanged working tree is neither gated twice nor nudged at every turn, untracked files named like secrets stay out of the review input, a test added after a blocked task's approval does not hold other worktrees, an unreadable task state is reported, and the shell guard's hook-skipping pattern runs in linear time.

Evidence (`npm test`, 179 tests): `test/review-fixes.test.mjs`, nineteen tests. Twelve failed on 3.5.0; one (a program that is not installed stays a missing tool) guards the old behaviour that the missing-script fix keeps. A fresh-context review of the first fixes found five more problems, four of them reproduced, and the last five tests failed before their fixes: an error on a continuation released the stop without a trace (now a hook error), a symbolic link loop broke the fingerprint, a path outside the project or an unrelated earlier message turned a missing program into an ordinary failure, secret-named files outside a sub-folder project went into the review input, and the git error behind the protect hook's refusal was dropped. A second review found that a continuation also reused a failing gate however old it was; the last test failed before that fix.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "paacm",
"version": "3.5.0",
"version": "3.5.1",
"description": "PAACM: the Verified Single-Writer Loop for agentic coding in Claude Code and Cursor. Installer, check runner, hooks and evaluation harness.",
"type": "module",
"license": "Apache-2.0",
Expand Down
2 changes: 1 addition & 1 deletion plugins/paacm/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "paacm",
"version": "3.5.0",
"version": "3.5.1",
"description": "PAACM: the Verified Single-Writer Loop for agentic coding. One writer agent, read-only explorer and reviewer subagents, tests protected after approval, and completion gated on executed checks.",
"author": {
"name": "Hyper AI Lab",
Expand Down
2 changes: 1 addition & 1 deletion plugins/paacm/.cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "paacm",
"version": "3.5.0",
"version": "3.5.1",
"description": "PAACM: the Verified Single-Writer Loop for agentic coding. One writer agent, read-only explorer and reviewer subagents, tests protected after approval, and completion gated on executed checks.",
"author": {
"name": "Hyper AI Lab",
Expand Down
2 changes: 1 addition & 1 deletion plugins/paacm/skills/paacm-verify/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ If `.agent/extensions/07-verify.md` exists, read it first and follow it together
1. **Run the gate:** `paacm gate --quiet`, on its own (no pipe, no `;`). It audits protected paths and runs the check tier for the current task's route; `--quiet` prints the check lines and a failing check's last lines, and with a task the full output is saved as `gate.log` in the task folder. Without a current task it runs the `quick` tier. Add `--tier full` before delivering STANDARD work, and `--tier security` for security-relevant changes.
2. **Read the exit code:**
- **0:** passed.
- **1:** a check failed. Fix the cause and run the gate again. If the check exited 127 (on Windows, cmd's "is not recognized" message), a command was not found: that is the environment, not the code. Record the check as not run and stop with `BLOCKED:` trigger 2 to ask the human for the tool.
- **1:** a check failed. Fix the cause and run the gate again. If the check exited 127 (on Windows, cmd's "is not recognized" message), a command was not found. When it is a program that is not installed, that is the environment, not the code: record the check as not run and stop with `BLOCKED:` trigger 2 to ask the human for the tool. When it is a file of the project (a path such as `./scripts/build.sh`) that the change removed or renamed, fix it like any failure.
- **3:** a tier has no checks. Record it as not run and tell the human it needs configuring.
- **4:** a protected path changed. Undo the change, or escalate if the change is needed.
3. **After three consecutive failures of the same check, stop and escalate** (trigger 5) instead of trying again.
Expand Down
4 changes: 3 additions & 1 deletion plugins/paacm/skills/paacm/references/07-verify.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@

When the gate passes, it prints the next phase: review (phase 8) for STANDARD and DEEP, deliver (phase 9) for FAST, after `paacm task phase verifying` if you have not recorded it. A passing gate at a lower tier than the route's does not count for `paacm task done`.

**A missing tool.** A check that fails with exit 127 (on Windows, cmd's "is not recognized" message) could not find a command, and the gate says so. That is the environment, not the code: do not change code to get around it. The gate cannot pass without the tool, so list the check under CHECKS NOT RUN and stop with `BLOCKED:` trigger 2 (`paacm task block --trigger 2 --reason "<the missing tool>"`) to ask the human to install it.
**A missing tool.** A check that fails with exit 127 (on Windows, cmd's "is not recognized" message) could not find a program, and the gate says so. That is the environment, not the code: do not change code to get around it. The gate cannot pass without the tool, so list the check under CHECKS NOT RUN and stop with `BLOCKED:` trigger 2 (`paacm task block --trigger 2 --reason "<the missing tool>"`) to ask the human to install it.

A command named by a path in the project (such as `./scripts/build.sh`) is not a tool: when the shell cannot find it, the change probably removed or renamed it, and the gate reports an ordinary failure. Fix it like any other.

3. **STANDARD work:** also run `paacm gate --tier full` before delivery. If the `full` tier is not configured, record that under CHECKS NOT RUN.
4. **Security-relevant diffs** (input handling, authentication, permissions, secrets, cryptography, dependency changes): also run `paacm gate --tier security`. Confirm that every new dependency exists in its registry under the exact name you used.
Expand Down
Loading
Loading