fix(trekendsession): Phase 3 re-reads the arguments instead of splicing the label into the shell line

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-10-26 16:12:44 +01:00
commit 89975a1fd6
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
5 changed files with 223 additions and 15 deletions

View file

@ -135,29 +135,41 @@ to avoid partial-state on crash. The util is ESM, so invoke via
`node --input-type=module -e` with an `import` statement (a CommonJS shim
would throw `ERR_REQUIRE_ESM` on Node 18+ since `atomic-write.mjs` is ESM).
Under `node --input-type=module -e "<script>" arg1 arg2 arg3`, Node sets
`process.argv[0]` to the node binary path and user args start at
`process.argv[1]`. Adjust the destructure if your Node version differs.
This phase ALSO writes a sibling `NEXT-SESSION-PROMPT.local.md` in the
project directory with YAML frontmatter (`produced_by: trekendsession`,
`produced_at: {ISO-8601}`, `project: {project_dir}`). Both files are written
in a single ESM block so the writes succeed or fail together.
Run the block below via the Bash tool at runtime, substituting the resolved
values for the `{curly}` placeholders (Phase 1 gives `{project_dir}`, Phase 2
gives `{next_brief_path}` and `{next_label}`). This is NOT an eager-exec
block — the values do not exist at command-load time. The import path must
stay absolute via `${CLAUDE_PLUGIN_ROOT}` — your Bash cwd is the user's
repo, not the plugin root, so a cwd-relative import throws
`ERR_MODULE_NOT_FOUND`:
Run the block below via the Bash tool at runtime, exactly as written: put no
value from Phase 1 or Phase 2 into it. This is NOT an eager-exec block — the
files do not exist at command-load time. The block takes nothing on its shell
line: it re-reads the arguments as the one line inside the quoted heredoc, on
stdin, never as shell words (the heredoc is the last thing in the command),
parses them with the same `parseArgs` as Phase 0 (the brief path is
`positional[0]`, the label is `tail`), and re-derives the project directory by
Phase 1's enumeration: exactly one `.claude/projects/<dir>/brief.md` under the
cwd, else it prints why and exits 1. The import paths must stay absolute via
`${CLAUDE_PLUGIN_ROOT}` — your Bash cwd is the user's repo, not the plugin
root, so a cwd-relative import throws `ERR_MODULE_NOT_FOUND`:
```bash
node --input-type=module -e "
import path from 'node:path';
import { writeFileSync } from 'node:fs';
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
import { atomicWriteJson } from '${CLAUDE_PLUGIN_ROOT}/lib/util/atomic-write.mjs';
const [, dir, brief, label] = process.argv;
import { parseArgs } from '${CLAUDE_PLUGIN_ROOT}/lib/parsers/arg-parser.mjs';
let text = readFileSync(0, 'utf8');
if (text.endsWith('\\n')) text = text.slice(0, -1);
if (text.endsWith('\\r')) text = text.slice(0, -1);
const args = parseArgs(text, 'trekendsession');
const brief = args.positional[0] || '';
const label = args.tail;
if (brief === '' || label === '') { console.error('Error: missing required args.'); process.exit(1); }
const root = '.claude/projects';
const found = existsSync(root) ? readdirSync(root).filter((d) => existsSync(path.join(root, d, 'brief.md'))).map((d) => path.join(root, d)) : [];
if (found.length === 0) { console.error('no .claude/projects/ directory with a brief.md found under cwd; cannot determine project directory'); process.exit(1); }
if (found.length > 1) { console.error('more than one project directory holds a brief.md; cd into the intended one and retry:\\n' + found.join('\\n')); process.exit(1); }
const dir = found[0];
const now = new Date().toISOString();
const stateObj = { schema_version: 1, project: dir, next_session_brief_path: brief, next_session_label: label, status: 'in_progress', updated_at: now };
const stateFile = path.join(dir, '.session-state.local.json');
@ -167,7 +179,9 @@ const promptBody = '---\\nproduced_by: trekendsession\\nproduced_at: ' + now + '
writeFileSync(promptFile, promptBody);
console.log(stateFile);
console.log(promptFile);
" '{project_dir}' '{next_brief_path}' '{next_label}'
" <<'VOYAGE_ARGS_EOF_7F3C9E'
$ARGUMENTS
VOYAGE_ARGS_EOF_7F3C9E
```
## Phase 4 — Validate + narrate