Skip to content
Open
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
4 changes: 2 additions & 2 deletions harness/pstack/claude-code/skills/reflect/SKILL.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pstack/skills/reflect/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ Invoke when the user says "reflect" or "/reflect". Skip when the conversation is
Before fanning out, find this conversation's transcript in the `agent-transcripts/` directory the system prompt names. Do not glob across `~/.cursor/projects/*/`. That crosses workspace boundaries and reads private chats from unrelated projects.

```bash
ls -t <agent-transcripts>/*.jsonl <agent-transcripts>/*/*.jsonl <agent-transcripts>/*/subagents/*.jsonl 2>/dev/null | head -10
bash -c 'shopt -s nullglob; files=("$1"/*.jsonl "$1"/*/*.jsonl "$1"/*/subagents/*.jsonl); if ((${#files[@]})); then ls -t "${files[@]}" | head -10; fi' bash "<agent-transcripts>"
```

That covers the legacy flat (`<id>.jsonl`), current nested (`<id>/<id>.jsonl`), and subagent (`<parent>/subagents/<child>.jsonl`) layouts. For each candidate, read the first JSONL line. Take the file whose `message.content[0].text` contains the conversation's opening user prompt. If none matches, pass a tight digest of the session instead.
`nullglob` drops a layout that is not on disk. Without it, zsh aborts on the first missing pattern, the pipe to `head` still exits 0, and a transcript that exists is left out. That covers the legacy flat (`<id>.jsonl`), current nested (`<id>/<id>.jsonl`), and subagent (`<parent>/subagents/<child>.jsonl`) layouts. For each candidate, read the first JSONL line. Take the file whose `message.content[0].text` contains the conversation's opening user prompt. If none matches, pass a tight digest of the session instead.

## 2. Spawn three reviewers in parallel

Expand Down
48 changes: 48 additions & 0 deletions pstack/skills/reflect/scripts/test/locate.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";

const skillPath = fileURLToPath(new URL("../../SKILL.md", import.meta.url));

function locateCommand(dir) {
const text = readFileSync(skillPath, "utf8");
const fence = text.match(/```bash\n([\s\S]*?)```/);
assert.ok(fence, "reflect should show the transcript listing");
return fence[1].trim().replaceAll("<agent-transcripts>", dir);
}

function run(shell, prefix, command) {
return spawnSync(shell, [...prefix, command], { encoding: "utf8" });
}

test("a missing layout does not hide the transcripts that exist", () => {
const parent = mkdtempSync(join(tmpdir(), "reflect-locate-"));
const dir = join(parent, "agent transcripts");
mkdirSync(join(dir, "abc"), { recursive: true });
writeFileSync(join(dir, "abc", "abc.jsonl"), "{\"k\":1}\n");
const command = locateCommand(dir);
try {
const bash = run(
"bash",
["--noprofile", "--norc", "-c"],
`shopt -s failglob; ${command}`
);
assert.equal(bash.error, undefined, bash.stderr);
assert.equal(bash.status, 0, bash.stderr);
assert.match(bash.stdout, /abc\.jsonl/);
assert.doesNotMatch(bash.stderr, /no match/);

const zsh = spawnSync("zsh", ["-f", "-c", "exit 0"]);
if (zsh.error) return;
const listed = run("zsh", ["-f", "-c"], command);
assert.equal(listed.status, 0, listed.stderr);
assert.match(listed.stdout, /abc\.jsonl/);
assert.doesNotMatch(listed.stderr, /no matches found/);
} finally {
rmSync(parent, { recursive: true, force: true });
}
});
Loading