{"record":{"id":"9912c83e6ca0736f","repo":"affaan-m/ECC","slug":"typing-requires-a-file-path","errorCode":null,"errorMessage":"typing requires a file path","messagePattern":"typing requires a file path","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/plan-canvas.js","lineNumber":302,"sourceCode":"  process.stderr.write('[plan-canvas] waiting for human feedback... leave this running (re-run if interrupted; queued feedback is never lost)\\n');\n  const result = await awaitRequest(port, sessionKeyFor(canonicalizeArtifactPath(file)), timeoutMs);\n  if (result.status === 'feedback') {\n    result.next_step = result.sessionEnded\n      ? 'The user sent this feedback and ended the session. Address it and report in chat; do not reopen the canvas uninvited.'\n      : 'Address the feedback, then run `ecc-plan-canvas await <file> --reply \"<what you changed>\"` to answer in the canvas and keep listening.';\n  } else if (result.status === 'ended') {\n    result.next_step =\n      result.endedBy === 'user'\n        ? 'The user ended this review. Stop polling and deliver any remaining updates in chat; do not reopen uninvited.'\n        : 'Session ended. Stop polling.';\n  }\n  return result;\n}\n\n// Show the human an activity indicator in the canvas chat. Cheap and\n// fire-and-forget: a failed signal must never derail the actual work.\nasync function cmdTyping(file, args, { port }) {\n  if (!file) throw new Error('typing requires a file path');\n  const state = valueAfter(args, '--state') || 'typing';\n  if (!(await healthCheck(port))) return { status: 'no-server' };\n  const key = sessionKeyFor(canonicalizeArtifactPath(file));\n  const res = await request(port, 'POST', `/api/session/${key}/typing`, { state });\n  if (res.statusCode !== 200) throw new Error(res.body.error || `typing failed (HTTP ${res.statusCode})`);\n  return { status: 'ok', state, presence: res.body.presence };\n}\n\n// Report feedback the human sent that no agent has picked up yet. Reads state\n// directly so it answers even when the server has idled out.\nfunction cmdPending({ stateDir }) {\n  const store = createSessionStore({ stateDir });\n  const waiting = store\n    .list()\n    .filter(session => session.status !== 'ended' && session.pending > 0)\n    .map(session => ({ file: session.file, pending: session.pending, updatedAt: session.updatedAt }));\n  return {\n    status: waiting.length ? 'pending' : 'clear',","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/plan-canvas.js#L284-L320","documentation":"cmdTyping shows a typing/activity indicator in the canvas chat for the session associated with a plan file. The file path is required to compute the session key; when the positional argument is absent the command throws 'typing requires a file path' before any server contact. The intent is that typing signals are best-effort, but the CLI still refuses to run without knowing which session to signal.","triggerScenarios":"Calling `ecc-plan-canvas typing` without a file positional — omitting the argument entirely, or an agent harness invoking the subcommand with only `--state thinking` and no path.","commonSituations":"Automating presence indicators from a script where the plan path lives in a variable that is empty; calling the subcommand from the wrong working directory and assuming it infers the file; mixing up argument order so the path lands where a flag expects it and is consumed.","solutions":["Invoke as `ecc-plan-canvas typing <file> [--state typing|thinking|idle]`, passing the same path used with `open`.","In scripts, assert the path variable is set before calling the command.","If the wrapper drops arguments, pass them after `--` or fix the wrapper's argument forwarding.","Remember typing is fire-and-forget: only the missing-file case throws here; once a path is supplied a dead server just yields status 'no-server'."],"exampleFix":"// before (agent script)\nexec(`ecc-plan-canvas typing --state ${state}`);\n\n// after\nif (!planPath) throw new Error('planPath required for typing signal');\nexec(`ecc-plan-canvas typing ${JSON.stringify(planPath)} --state ${state}`);","handlingStrategy":"validation","validationCode":"if (!file) throw new Error('typing requires a file path');\nif (!fs.existsSync(file)) throw new Error(`plan file not found: ${file}`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Thread the plan path through agent scripts as a single validated variable.","Pass --state only with values the server understands (typing/thinking/idle).","Treat typing signals as optional: guard the call site so missing paths degrade to a no-op in non-interactive runs."],"tags":["cli","missing-argument","plan-canvas"],"backgroundTag":"missing-required-argument","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}