@tritard/waterbrother 0.5.10 → 0.5.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +18 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tritard/waterbrother",
3
- "version": "0.5.10",
3
+ "version": "0.5.12",
4
4
  "description": "Waterbrother: Grok-powered coding CLI with local tools, sessions, operator modes, and approval controls",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -107,14 +107,14 @@ const INTERACTIVE_COMMANDS = [
107
107
  { name: "/profile save <name>", description: "Save current mode/autonomy/profile as a reusable profile" },
108
108
  { name: "/profile load <name>", description: "Load a saved operator profile" },
109
109
  { name: "/profiles", description: "List saved operator profiles" },
110
- { name: "/feature <name>", description: "Start a new task (engineering unit)" },
110
+ { name: "/feature [name]", description: "Start a new task (engineering unit)" },
111
111
  { name: "/tasks", description: "List recent tasks" },
112
112
  { name: "/task", description: "Show active task" },
113
113
  { name: "/close", description: "Close the active task" },
114
114
  { name: "/decide [goal]", description: "Run decision pass for active task" },
115
115
  { name: "/choose <option>", description: "Choose a decision option" },
116
116
  { name: "/redecide", description: "Re-run the decision pass" },
117
- { name: "/build <prompt>", description: "Execute build turn within task contract" },
117
+ { name: "/build [prompt]", description: "Execute build turn within task contract" },
118
118
  { name: "/review", description: "Show the latest review panel" },
119
119
  { name: "/challenge", description: "Adversarial re-review of last receipt" },
120
120
  { name: "/accept", description: "Accept the last receipt and mark task accepted" },
@@ -3995,9 +3995,16 @@ async function readInteractiveLine(options = {}) {
3995
3995
  pasteSuppressUntil = Date.now() + 300;
3996
3996
  }
3997
3997
 
3998
+ // Ensure stdin is in a clean state before attaching listeners.
3999
+ // The interrupt listener may have paused stdin and toggled raw mode
4000
+ // between turns, leaving readline's internal keypress emitter stale.
4001
+ if (input.isTTY) {
4002
+ try { input.setRawMode(false); } catch {}
4003
+ }
4004
+ input.pause();
3998
4005
  readline.emitKeypressEvents(input);
3999
4006
  input.resume();
4000
- if (!initialRaw && input.isTTY) {
4007
+ if (input.isTTY) {
4001
4008
  input.setRawMode(true);
4002
4009
  }
4003
4010
 
@@ -4670,9 +4677,8 @@ async function promptLoop(agent, session, context) {
4670
4677
  continue;
4671
4678
  }
4672
4679
 
4673
- if (line.startsWith("/feature ")) {
4674
- const taskName = line.replace("/feature", "").trim();
4675
- if (!taskName) { console.log("Usage: /feature <name>"); continue; }
4680
+ if (line === "/feature" || line.startsWith("/feature ")) {
4681
+ const taskName = line.replace("/feature", "").trim() || `task-${Date.now().toString(36)}`;
4676
4682
  try {
4677
4683
  const branchPrefix = context.runtime.taskDefaults?.branchPrefix || "wb/";
4678
4684
  const { task, resumed } = await startFeatureTask({
@@ -4777,7 +4783,7 @@ async function promptLoop(agent, session, context) {
4777
4783
  if (!task) { console.log("no active task — run /feature first"); continue; }
4778
4784
  const goalArg = line.replace("/decide", "").trim();
4779
4785
  if (goalArg) task.goal = goalArg;
4780
- if (!task.goal) { console.log("provide a goal: /decide <goal>"); continue; }
4786
+ if (!task.goal) task.goal = task.name;
4781
4787
  const spinner = createProgressSpinner("running decision pass...");
4782
4788
  try {
4783
4789
  const decisionModel = context.runtime.decisionModel || agent.getModel();
@@ -4850,7 +4856,7 @@ async function promptLoop(agent, session, context) {
4850
4856
  if (line === "/redecide") {
4851
4857
  const task = context.runtime.activeTask;
4852
4858
  if (!task) { console.log("no active task"); continue; }
4853
- if (!task.goal) { console.log("no goal set — run /decide <goal> first"); continue; }
4859
+ if (!task.goal) { console.log("no goal set — run /decide first"); continue; }
4854
4860
  task.lastDecision = null;
4855
4861
  task.decisionId = null;
4856
4862
  task.chosenOption = null;
@@ -4863,13 +4869,13 @@ async function promptLoop(agent, session, context) {
4863
4869
  continue;
4864
4870
  }
4865
4871
 
4866
- if (line.startsWith("/build ")) {
4872
+ if (line === "/build" || line.startsWith("/build ")) {
4867
4873
  const task = context.runtime.activeTask;
4868
4874
  if (!task) { console.log("no active task — run /feature first"); continue; }
4869
- const buildPrompt = line.replace("/build", "").trim();
4870
- if (!buildPrompt) { console.log("Usage: /build <prompt>"); continue; }
4875
+ const buildArg = line.replace("/build", "").trim();
4876
+ const buildPrompt = buildArg || (task.chosenOption ? `Execute the chosen approach: ${task.chosenOption}` : `Build: ${task.name}`);
4871
4877
  if (task.state === "decide-required" && context.runtime.taskDefaults?.requireDecisionBeforeBuild) {
4872
- console.log("task needs a decision first — run /decide <goal>");
4878
+ console.log("task needs a decision first — run /decide");
4873
4879
  continue;
4874
4880
  }
4875
4881
 
@@ -5063,10 +5069,6 @@ async function promptLoop(agent, session, context) {
5063
5069
  continue;
5064
5070
  }
5065
5071
 
5066
- if (line === "/build") {
5067
- console.log("Usage: /build <prompt>");
5068
- continue;
5069
- }
5070
5072
 
5071
5073
  if (line === "/review") {
5072
5074
  const receipt = context.runtime.lastReceipt || (await agent.toolRuntime.readReceipt('last'));