← back to Dw Sku Integrity
TK-10896: fix remote-shell quoting — feed SQL via stdin not -c (works over ssh)
cab27665acd7229773ec7f7873876827b525de90 · 2026-08-31 01:09:02 -0700 · codex-10896
Over 'ssh <host> psql -c <sql>' the remote bash re-parses the SQL and chokes on
parens/quotes. psql reads stdin when given no -c/-f, identical local + remote.
Fixed in preflight-check.mjs + dwsku-backlog-scan.mjs. 47 tests green. First
canonical Kamatera preflight run now works and CONFIRMS mirror drift: a-s-cr-ation's
planned row is ALREADY_TARGET on Kamatera (dw_sku already populated) while the mirror
showed it blank — Phase-1 self-copies landed on canonical, mirror never got them.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M dwsku-backlog-scan.mjsM preflight-check.mjs
Diff
commit cab27665acd7229773ec7f7873876827b525de90
Author: codex-10896 <steve@designerwallcoverings.com>
Date: Mon Aug 31 01:09:02 2026 -0700
TK-10896: fix remote-shell quoting — feed SQL via stdin not -c (works over ssh)
Over 'ssh <host> psql -c <sql>' the remote bash re-parses the SQL and chokes on
parens/quotes. psql reads stdin when given no -c/-f, identical local + remote.
Fixed in preflight-check.mjs + dwsku-backlog-scan.mjs. 47 tests green. First
canonical Kamatera preflight run now works and CONFIRMS mirror drift: a-s-cr-ation's
planned row is ALREADY_TARGET on Kamatera (dw_sku already populated) while the mirror
showed it blank — Phase-1 self-copies landed on canonical, mirror never got them.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
dwsku-backlog-scan.mjs | 7 +++++--
preflight-check.mjs | 7 +++++--
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/dwsku-backlog-scan.mjs b/dwsku-backlog-scan.mjs
index bb3fc5b..038cd16 100644
--- a/dwsku-backlog-scan.mjs
+++ b/dwsku-backlog-scan.mjs
@@ -34,8 +34,11 @@ const OUT = outArg >= 0 ? argv[outArg + 1] : null;
const emitPlan = argv.includes('--plan'); // also emit per-row plan JSONL next to --out
function psql(sql) {
- const args = [...PSQL.slice(1), '-tA', '-F', US, '-R', RS, '-c', sql];
- const raw = execFileSync(PSQL[0], args, { maxBuffer: 1 << 30, encoding: 'utf8' });
+ // Feed SQL via STDIN, not -c: over `ssh <host> psql ...` the -c argument would be
+ // re-parsed by the REMOTE shell and choke on SQL parens/quotes. psql reads stdin
+ // when given no -c/-f, which works identically local and over ssh.
+ const args = [...PSQL.slice(1), '-tA', '-F', US, '-R', RS];
+ const raw = execFileSync(PSQL[0], args, { input: sql, maxBuffer: 1 << 30, encoding: 'utf8' });
return raw.split(RS).map((r) => r.replace(/\n$/, '')).filter((r) => r.length).map((r) => r.split(US));
}
diff --git a/preflight-check.mjs b/preflight-check.mjs
index f8b1722..62d15fb 100644
--- a/preflight-check.mjs
+++ b/preflight-check.mjs
@@ -39,8 +39,11 @@ function sqlEscape(v) { return String(v).replace(/'/g, "''"); }
function defaultChunkReader(shopifyIds) {
const inList = shopifyIds.map((s) => `'${sqlEscape(s)}'`).join(',');
const sql = `SELECT shopify_id, coalesce(dw_sku,'') FROM shopify_products WHERE shopify_id IN (${inList});`;
- const out = execFileSync(PSQL[0], [...PSQL.slice(1), '-tA', '-F', US, '-R', RS, '-c', sql], {
- maxBuffer: 1 << 30, encoding: 'utf8',
+ // Feed SQL via STDIN, not -c: over `ssh <host> psql ...` the -c argument would be
+ // re-parsed by the REMOTE shell and choke on the SQL's parens/quotes. psql with no
+ // -c/-f reads from stdin, which works identically local and over ssh.
+ const out = execFileSync(PSQL[0], [...PSQL.slice(1), '-tA', '-F', US, '-R', RS], {
+ input: sql, maxBuffer: 1 << 30, encoding: 'utf8',
});
const rows = new Map();
for (const rec of out.split(RS)) {
← e941614 TK-10896: add post-apply verify mode + turnkey per-vendor fi
·
back to Dw Sku Integrity
·
TK-10896: CANONICAL correction — mirror was stale, real back 74251ab →