pstack-claude-mirror 0.9.133 → 0.9.135
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGES.md +16 -0
- package/README.md +23 -7
- package/UPSTREAM-README.md +7 -1
- package/bin/pstack-claude.mjs +278 -130
- package/docs/reference.md +4 -4
- package/package.json +27 -9
- package/plugins/pstack/.antigravity-plugin/plugin.json +1 -1
- package/plugins/pstack/.claude-plugin/plugin.json +1 -1
- package/plugins/pstack/.codex-plugin/plugin.json +1 -1
- package/plugins/pstack/.github/plugin/plugin.json +1 -1
- package/plugins/pstack/.grok-plugin/plugin.json +1 -1
- package/plugins/pstack/.muse-plugin/plugin.json +1 -1
- package/plugins/pstack/LICENSE +22 -0
- package/plugins/pstack/hooks/copilot-hooks.json +4 -2
- package/plugins/pstack/hooks/session-start.ps1 +76 -12
- package/plugins/pstack/hooks/session-start.sh +6 -0
- package/plugins/pstack/models.json +1 -1
- package/plugins/pstack/package.json +1 -1
- package/plugins/pstack/pi/slash.ts +19 -5
- package/plugins/pstack/skills/poteto-mode/SKILL.md +1 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/bug-fix.md +17 -0
- package/plugins/pstack/skills/poteto-mode/references/agy-tools.md +5 -4
- package/plugins/pstack/skills/poteto-mode/references/codex-tools.md +3 -2
- package/plugins/pstack/skills/poteto-mode/references/copilot-tools.md +2 -1
- package/plugins/pstack/skills/poteto-mode/references/pi-tools.md +1 -1
- package/plugins/pstack/skills/poteto-mode/scripts/.prettierignore +1 -1
- package/plugins/pstack/skills/poteto-mode/scripts/codex-session-effort.mjs +35 -7
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/github.port.test.ts +427 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/github.test.ts +3 -399
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/policy.port.test.ts +708 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/policy.test.ts +7 -666
- package/plugins/pstack/skills/poteto-mode/scripts/worktree-audit.mjs +42 -1
- package/plugins/pstack/skills/reflect/scripts/find-transcript.mjs +2 -2
- package/plugins/pstack/skills/setup-pstack/SKILL.md +6 -4
- package/plugins/pstack/skills/setup-pstack/references/runtimes.md +1 -1
- package/tools/forks.json +5 -5
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
// and archived_sessions under $CODEX_HOME, and Pi's sessions and pstack subagent
|
|
13
13
|
// sessions under $PI_CODING_AGENT_DIR (defaults: ~/.claude, ~/.codex, ~/.pi/agent).
|
|
14
14
|
//
|
|
15
|
+
// Compressed rollouts use native Zstd when it reads complete streams. Other
|
|
16
|
+
// runtimes fall back to zstd on PATH. A decode failure makes the whole chat
|
|
17
|
+
// scan unknown, so no worktree can be declared safe from that scan.
|
|
18
|
+
//
|
|
15
19
|
// Every probe yields a Fact, { known: true, value } or { known: false }. A hold
|
|
16
20
|
// bucket needs only its own fact; `safe` needs every fact known.
|
|
17
21
|
import { execFileSync } from "node:child_process";
|
|
@@ -20,6 +24,7 @@ import { homedir } from "node:os";
|
|
|
20
24
|
import { basename, dirname, join } from "node:path";
|
|
21
25
|
import process from "node:process";
|
|
22
26
|
import { fileURLToPath } from "node:url";
|
|
27
|
+
import zlib from "node:zlib";
|
|
23
28
|
|
|
24
29
|
import { candidates, rethrowUnlessRemoved } from "../../reflect/scripts/find-transcript.mjs";
|
|
25
30
|
|
|
@@ -199,11 +204,38 @@ function transcriptNeedles(spellings) {
|
|
|
199
204
|
return [...new Set(forms)].map((form) => Buffer.from(JSON.stringify(form).slice(1, -1)));
|
|
200
205
|
}
|
|
201
206
|
|
|
207
|
+
// Bun 1.4.4 returns the partial output of a truncated frame without an error,
|
|
208
|
+
// and nodejs/node#64592 reports the same for Node. The check also turns down a
|
|
209
|
+
// decoder that stops after the first frame. It runs once, not once per transcript.
|
|
210
|
+
function nativeZstdDecoder() {
|
|
211
|
+
const decode = zlib.zstdDecompressSync;
|
|
212
|
+
if (typeof decode !== "function") return undefined;
|
|
213
|
+
// A complete Zstd frame containing "a", independent of compressor availability.
|
|
214
|
+
const frame = Buffer.from("28b52ffd200109000061", "hex");
|
|
215
|
+
const joined = Buffer.concat([frame, frame]);
|
|
216
|
+
try {
|
|
217
|
+
if (decode(joined).toString() !== "aa") return undefined;
|
|
218
|
+
} catch {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
for (const partial of [frame.subarray(0, -1), joined.subarray(0, -1)]) {
|
|
222
|
+
try {
|
|
223
|
+
decode(partial);
|
|
224
|
+
return undefined;
|
|
225
|
+
} catch { /* A complete-stream decoder must reject an unfinished frame. */ }
|
|
226
|
+
}
|
|
227
|
+
return decode;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const decodeZstd = nativeZstdDecoder() ?? ((input) => execFileSync("zstd", ["-d", "-c"], {
|
|
231
|
+
input, stdio: ["pipe", "pipe", "pipe"], maxBuffer: Infinity, timeout: 30_000,
|
|
232
|
+
}));
|
|
233
|
+
|
|
202
234
|
// `spellings` maps each worktree path to every spelling a session could use.
|
|
203
235
|
export function lastChats(roots, spellings) {
|
|
204
236
|
const needles = [...spellings].map(([path, forms]) => [path, transcriptNeedles(forms)]);
|
|
205
237
|
const latest = new Map();
|
|
206
|
-
for (const { path: file } of roots.flatMap((root) => candidates(root, Infinity))) {
|
|
238
|
+
for (const { path: file } of roots.flatMap((root) => candidates(root, Infinity, { includeCompressed: true }))) {
|
|
207
239
|
let text, mtime;
|
|
208
240
|
try {
|
|
209
241
|
text = readFileSync(file);
|
|
@@ -214,6 +246,15 @@ export function lastChats(roots, spellings) {
|
|
|
214
246
|
rethrowUnlessRemoved(error);
|
|
215
247
|
continue;
|
|
216
248
|
}
|
|
249
|
+
if (file.endsWith(".jsonl.zst")) {
|
|
250
|
+
try {
|
|
251
|
+
text = decodeZstd(text);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
// A missing fallback executable is not a transcript removed during enumeration.
|
|
254
|
+
const hint = error.code === "ENOENT" ? " Use a runtime with complete native Zstd support or install zstd." : "";
|
|
255
|
+
throw new Error(`cannot decode ${file}: ${String(error.stderr ?? "").trim() || error.message}${hint}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
217
258
|
for (const [path, forms] of needles) {
|
|
218
259
|
if (mtime > (latest.get(path) ?? 0) && forms.some((needle) => mentions(text, needle))) latest.set(path, mtime);
|
|
219
260
|
}
|
|
@@ -38,12 +38,12 @@ export function rethrowUnlessRemoved(error) {
|
|
|
38
38
|
if (error.code !== "ENOENT") throw error;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export function candidates(projectsDir, maxDepth = 2) {
|
|
41
|
+
export function candidates(projectsDir, maxDepth = 2, { includeCompressed = false } = {}) {
|
|
42
42
|
const files = [];
|
|
43
43
|
const walk = (dir, depth) => {
|
|
44
44
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
45
45
|
const full = join(dir, entry.name);
|
|
46
|
-
if (entry.isFile() && entry.name.endsWith(".jsonl")) files.push(full);
|
|
46
|
+
if (entry.isFile() && (entry.name.endsWith(".jsonl") || (includeCompressed && entry.name.endsWith(".jsonl.zst")))) files.push(full);
|
|
47
47
|
else if (entry.isDirectory() && depth < maxDepth) {
|
|
48
48
|
try {
|
|
49
49
|
walk(full, depth + 1);
|
|
@@ -17,13 +17,13 @@ Write the current runtime's per-role model override sheet. Each pstack skill nam
|
|
|
17
17
|
|
|
18
18
|
On any runtime other than Claude Code, read [Other runtimes](references/runtimes.md) first. Its table gives the sheet path, how the sheet loads, and how to list models, and your runtime's section says which steps change. The rest of this file describes Claude Code.
|
|
19
19
|
|
|
20
|
-
On Claude Code the config directory is `$CLAUDE_CONFIG_DIR` when that variable is set and `~/.claude` otherwise. This skill calls it `<config>`, and the sheet is `<config>/pstack-models.md`. Claude Code has no auto-applied "rules" mechanism like Cursor's `.mdc`, so inclusion is explicit: the user adds a line to `<config>/CLAUDE.md`
|
|
20
|
+
On Claude Code the config directory is `$CLAUDE_CONFIG_DIR` when that variable is set and `~/.claude` otherwise. This skill calls it `<config>`, and the user sheet is `<config>/pstack-models.md`. A project sheet, `.claude/pstack-models.md` at the repository root (`git rev-parse --show-toplevel`; outside a repository, the directory Claude Code starts in), is committed with the repository and replaces the user sheet in that project. The session hook reads it whenever it exists. The model rows defer to it through the line step 6 writes under its heading, so a hand-written project sheet needs that line too. Claude Code has no auto-applied "rules" mechanism like Cursor's `.mdc`, so inclusion is explicit: the user adds a line to `<config>/CLAUDE.md` such as:
|
|
21
21
|
|
|
22
22
|
```text
|
|
23
23
|
@<config>/pstack-models.md
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
with `<config>` written as the resolved path, so the file is loaded as context for every session.
|
|
26
|
+
with `<config>` written as the resolved path, so the file is loaded as context for every session. A project sheet loads from `@.claude/pstack-models.md` in the `CLAUDE.md` at the repository root.
|
|
27
27
|
|
|
28
28
|
## Steps
|
|
29
29
|
|
|
@@ -33,6 +33,8 @@ Enumerate the model names the `Agent` tool's `model` parameter accepts in this s
|
|
|
33
33
|
|
|
34
34
|
### 2. Load current state
|
|
35
35
|
|
|
36
|
+
On Claude Code, first ask whether to configure the user sheet, for every project, or the project sheet, for this repository on any machine. The rest of the steps use the chosen sheet.
|
|
37
|
+
|
|
36
38
|
The default role-to-model mapping is the rule shape shown in the Write the override sheet step below. If the current runtime's sheet already exists, read it and treat its values as the current choices. Otherwise start from those defaults. A line whose role is not in that shape, such as `how critics`, is from a retired role. Drop it. An older sheet may name full model IDs that start with `claude-`, which the `Agent` tool rejects. Replace each with its family name, the word after `claude-`.
|
|
37
39
|
|
|
38
40
|
### 3. Map and confirm
|
|
@@ -51,7 +53,7 @@ Every real slug written must be in the detected set. `inherit-parent` and `auto`
|
|
|
51
53
|
|
|
52
54
|
### 6. Write the override sheet
|
|
53
55
|
|
|
54
|
-
Write the current runtime's sheet with the shape below. Overwrite the whole file so re-runs stay idempotent.
|
|
56
|
+
Write the current runtime's sheet with the shape below. Overwrite the whole file so re-runs stay idempotent. A project sheet also gets this line under its heading, so a session that loads both sheets knows which one counts: `This project's sheet. In this repository it replaces the user's pstack-models.md; ignore that sheet's lines.`
|
|
55
57
|
|
|
56
58
|
```markdown
|
|
57
59
|
# pstack model configuration
|
|
@@ -84,7 +86,7 @@ session hook: on
|
|
|
84
86
|
|
|
85
87
|
### 7. Wire it in
|
|
86
88
|
|
|
87
|
-
On Claude Code, if `<config>/CLAUDE.md` does not already include `<config>/pstack-models.md`, append an `@` line naming the sheet's resolved path, such as `@~/.claude/pstack-models.md`, so the model rows load on every session.
|
|
89
|
+
On Claude Code, if `<config>/CLAUDE.md` does not already include `<config>/pstack-models.md`, append an `@` line naming the sheet's resolved path, such as `@~/.claude/pstack-models.md`, so the model rows load on every session. For a project sheet, append `@.claude/pstack-models.md` to the `CLAUDE.md` at the repository root instead, if it is not there, and tell the user to commit both files.
|
|
88
90
|
|
|
89
91
|
### 8. Confirm
|
|
90
92
|
|
|
@@ -6,7 +6,7 @@ The role lines are the same everywhere. What differs is the sheet path, how the
|
|
|
6
6
|
|
|
7
7
|
| Runtime | Sheet | Load | List models | Status |
|
|
8
8
|
| --- | --- | --- | --- | --- |
|
|
9
|
-
| Claude Code | `<config>/pstack-models.md` | `@<config>/pstack-models.md` in `<config>/CLAUDE.md` | the `Agent` tool's model parameter | verified live |
|
|
9
|
+
| Claude Code | `<config>/pstack-models.md`, or `.claude/pstack-models.md` at the repository root, which replaces it in that project | `@<config>/pstack-models.md` in `<config>/CLAUDE.md`, or `@.claude/pstack-models.md` in the repository root's `CLAUDE.md` | the `Agent` tool's model parameter | verified live |
|
|
10
10
|
| Codex | `<codex-home>/pstack-models.md` | model rows: paste into `<codex-home>/AGENTS.md`; hook setting: read by the plugin | your configured Codex models, see [codex-tools.md](../../poteto-mode/references/codex-tools.md#model-names) | hook contract tested; discovery verified |
|
|
11
11
|
| Pi | `pstack-models.md` in the Pi agent directory, `$PI_CODING_AGENT_DIR` or `~/.pi/agent` | read by the pstack Pi extension, model rows and hook setting both; no include line | `pi --list-models`, see [pi-tools.md](../../poteto-mode/references/pi-tools.md#model-names) and its `setup-pstack` note | extension contract tested offline; live results in the repository's `docs/pi-equivalence.md` |
|
|
12
12
|
| GitHub Copilot (CLI and app) | `${COPILOT_HOME:-~/.copilot}/pstack-models.md` | the plugin hook checks it and injects its role lines at session start; skills-only installs read it with `view` | the `task` tool's `model` enum, see [copilot-tools.md](../../poteto-mode/references/copilot-tools.md#model-names) | hook contract tested; CLI install smoke-tested |
|
package/tools/forks.json
CHANGED
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"plugins/pstack/skills/poteto-mode/SKILL.md": {
|
|
58
58
|
"kind": "policy",
|
|
59
|
-
"why": "Adds the Platform Adaptation section, whose runtime sentence the generator stamps from RUNTIMES, with its task-tool and todo.md fallback (per task slug when sessions share a checkout, and beside the desktop app's short update_plan list), the run-or-verify driver line, the deploy-platform and defect-severity triggers, the port's principle summaries, the project playbooks paragraph, and the closed-review-gate rule that the Codex and Pi mappings point to, and it points the Agent-call defaults at the Models section with full tool access and the namespaced pstack:poteto-agent name, requires stopping an abandoned agent before replacing it, renders every reply item as prose, layers technical-writing on top of unslop, and describes Autopilot-full as stopping at merge-ready for the operator's click and Autopilot-stack as Autopilot-full for PRs that build on each other.",
|
|
59
|
+
"why": "Adds the Platform Adaptation section, whose runtime sentence the generator stamps from RUNTIMES, with its task-tool and todo.md fallback (per task slug when sessions share a checkout, and beside the desktop app's short update_plan list), the run-or-verify driver line, the deploy-platform and defect-severity triggers, the focused-fix exception to the how and architect triggers, the port's principle summaries, the project playbooks paragraph, and the closed-review-gate rule that the Codex and Pi mappings point to, and it points the Agent-call defaults at the Models section with full tool access and the namespaced pstack:poteto-agent name, requires stopping an abandoned agent before replacing it, renders every reply item as prose, layers technical-writing on top of unslop, and describes Autopilot-full as stopping at merge-ready for the operator's click and Autopilot-stack as Autopilot-full for PRs that build on each other.",
|
|
60
60
|
"since": "0.9.2",
|
|
61
61
|
"upstream": "not-proposed"
|
|
62
62
|
},
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
},
|
|
81
81
|
"plugins/pstack/skills/poteto-mode/playbooks/bug-fix.md": {
|
|
82
82
|
"kind": "policy",
|
|
83
|
-
"why": "
|
|
83
|
+
"why": "Quotes decisive failing and passing output trimmed to the assertion and counts, separates verified code, publication, observed runtime behavior, and blockers, selects non-sensitive diagnostic fields before printing, and adds a focused-fix exception with explicit architecture and independent correctness review triggers for higher-risk fixes.",
|
|
84
84
|
"since": "0.9.10",
|
|
85
85
|
"upstream": "not-proposed"
|
|
86
86
|
},
|
|
@@ -170,7 +170,7 @@
|
|
|
170
170
|
},
|
|
171
171
|
"plugins/pstack/skills/poteto-mode/scripts/watch-pr/github.test.ts": {
|
|
172
172
|
"kind": "policy",
|
|
173
|
-
"why": "
|
|
173
|
+
"why": "Adapts upstream's cases to the port's GitHub reader: a `reported` helper that narrows each check read to reported checks, rollup pages tagged `contexts`, the base revision read from `baseRef`, an empty `reviewDecision` rejected like any other unknown enum value, the `missing-field` query failure, `orderStack` taking the default branch and each head's repository in place of `isCrossRepository`, and a reader built with the shared deadline. The port's own cases are in `github.port.test.ts`.",
|
|
174
174
|
"since": "0.9.24",
|
|
175
175
|
"upstream": "not-proposed"
|
|
176
176
|
},
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
},
|
|
183
183
|
"plugins/pstack/skills/poteto-mode/scripts/watch-pr/policy.test.ts": {
|
|
184
184
|
"kind": "policy",
|
|
185
|
-
"why": "
|
|
185
|
+
"why": "Adapts upstream's cases to the port's policy: the second facts read in the snapshot plan and the read it adds to each sweep, a stack wait that carries its reason, `evaluateQueue` without a clock reading, and the shared deadline in the poll loop. The port's own cases are in `policy.port.test.ts`.",
|
|
186
186
|
"since": "0.9.24",
|
|
187
187
|
"upstream": "not-proposed"
|
|
188
188
|
},
|
|
@@ -242,7 +242,7 @@
|
|
|
242
242
|
},
|
|
243
243
|
"plugins/pstack/skills/setup-pstack/SKILL.md": {
|
|
244
244
|
"kind": "port-feature",
|
|
245
|
-
"why": "Writes the override sheet at each runtime's own path, loaded by @-include on Claude Code, pasted into AGENTS.md on Codex, and read directly by the Muse plugin hook since none has Cursor's always-applied rules, replaces Cursor's budget step with a default effort and per-role effort levels and explains Codex's active-turn metadata requirement for session effort, adds the SessionStart hook toggle and names the Pi extension and OpenCode plugin as readers of it, keeps every runtime's sheet path table and per-runtime step changes in references/runtimes.md, routing GitHub Copilot to copilot.md, Kimi and Grok to runtime-specific setup, and OMP to native model configuration and its global routing toggle, and numbers its verification and formal verification offers as steps 9 and 10.",
|
|
245
|
+
"why": "Writes the override sheet at each runtime's own path, loaded by @-include on Claude Code with a committed project sheet that replaces the user's, pasted into AGENTS.md on Codex, and read directly by the Muse plugin hook since none has Cursor's always-applied rules, replaces Cursor's budget step with a default effort and per-role effort levels and explains Codex's active-turn metadata requirement for session effort, adds the SessionStart hook toggle and names the Pi extension and OpenCode plugin as readers of it, keeps every runtime's sheet path table and per-runtime step changes in references/runtimes.md, routing GitHub Copilot to copilot.md, Kimi and Grok to runtime-specific setup, and OMP to native model configuration and its global routing toggle, and numbers its verification and formal verification offers as steps 9 and 10.",
|
|
246
246
|
"since": "0.9.2",
|
|
247
247
|
"upstream": "not-proposed"
|
|
248
248
|
},
|