diff --git a/plugins/ultraplan-local/commands/ultracontinue-local.md b/plugins/ultraplan-local/commands/ultracontinue-local.md index 2159c79..85f154e 100644 --- a/plugins/ultraplan-local/commands/ultracontinue-local.md +++ b/plugins/ultraplan-local/commands/ultracontinue-local.md @@ -119,21 +119,45 @@ resumable state wins. ## Phase 2 — Validate the state file -Run the validator from a Bash invocation: +Phase 1 resolved a concrete state-file path. That path is a real string in +your working context — never a template. Phase 2 must read and validate the +state file without any placeholder substitution. -```bash -!`node lib/validators/session-state-validator.mjs --json {state-file-path}` +### Step 2.a — Read the file with the Read tool (no Bash) + +Use the **Read tool** on the resolved state-file path from Phase 1. Do NOT use +Bash for the read. The Read tool is deterministic and not subject to +shell-substitution errors. Parse the returned JSON body programmatically. + +### Step 2.b — Schema-validate the parsed object + +Verify the schema by invoking the existing validator CLI shim. Emit the +resolved absolute path as a literal string token in the Bash command — the +exact same string you just passed to the Read tool. The validator accepts +`--json ` and prints a `{valid, errors, warnings}` JSON record: + +``` +node lib/validators/session-state-validator.mjs --json ``` -Interpret the result: +Replace `` with the actual path string at +the time you issue the Bash call. There is no template engine; the string is +substituted by you, the model, before the Bash tool sees the command. + +**Anti-substitution invariant.** If you ever find yourself about to emit a +literal angle-bracket placeholder, or any other unresolved variable name, to +the Bash tool — STOP. The resolved path is a concrete value you already have +from Phase 1; emit the value, not a placeholder for it. + +### Step 2.c — Interpret the result - **Validator exit code != 0 OR `valid: false` in JSON output:** print the - structured `errors[]` (each `[code] message` on its own line) and exit. Do not - proceed to narration. Suggest running the validator directly for follow-up: - `node lib/validators/session-state-validator.mjs `. -- **`valid: true` AND any warning has `code: SESSION_STATE_NOT_RESUMABLE`** (i.e. - `status: completed`): print "no further sessions to resume; project complete" - and exit cleanly. + structured `errors[]` (each `[code] message` on its own line) and exit. Do + not proceed to narration. Suggest running the validator directly for + follow-up: `node lib/validators/session-state-validator.mjs `. +- **`valid: true` AND any warning has `code: SESSION_STATE_NOT_RESUMABLE`** + (i.e. `status: completed`): print "no further sessions to resume; project + complete" and exit cleanly. - **`valid: true` AND status is one of `in_progress | partial | failed | stopped`:** proceed to Phase 3.