@tritard/waterbrother 0.16.20 → 0.16.21

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/tools.js +87 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tritard/waterbrother",
3
- "version": "0.16.20",
3
+ "version": "0.16.21",
4
4
  "description": "Waterbrother: bring-your-own-model coding CLI with local tools, sessions, operator modes, and approval controls",
5
5
  "type": "module",
6
6
  "bin": {
package/src/tools.js CHANGED
@@ -1112,6 +1112,87 @@ export function createToolRuntime({
1112
1112
  currentTurn.touchedPaths = uniqueStrings([...(currentTurn.touchedPaths || []), ...normalizePathList(paths)]);
1113
1113
  }
1114
1114
 
1115
+ async function buildImplicitVerificationEntries(toolName, args = {}, parsedResult = null) {
1116
+ if (!args?.path) return [];
1117
+
1118
+ const writeRoots = [...getCurrentWriteRoots(), ...getContractWriteRoots()];
1119
+ const commandLabel = `${toolName} ${String(args.path)}`;
1120
+
1121
+ try {
1122
+ if (toolName === "make_directory") {
1123
+ const target = resolveSandboxPath(cwd, args.path, allowOutsideCwd, {
1124
+ allowedWriteRoots: writeRoots
1125
+ });
1126
+ const stat = await fs.stat(target);
1127
+ return [{
1128
+ command: commandLabel,
1129
+ ok: stat.isDirectory(),
1130
+ implicit: true,
1131
+ tool: toolName,
1132
+ path: args.path,
1133
+ detail: stat.isDirectory() ? "directory exists" : "target exists but is not a directory"
1134
+ }];
1135
+ }
1136
+
1137
+ if (toolName === "write_file" || toolName === "replace_in_file") {
1138
+ const target = resolveSandboxPath(cwd, args.path, allowOutsideCwd, {
1139
+ allowedWriteRoots: writeRoots
1140
+ });
1141
+ const stat = await fs.stat(target);
1142
+ const entries = [{
1143
+ command: commandLabel,
1144
+ ok: stat.isFile(),
1145
+ implicit: true,
1146
+ tool: toolName,
1147
+ path: args.path,
1148
+ detail: stat.isFile() ? "file exists after write" : "target exists but is not a file"
1149
+ }];
1150
+ if (toolName === "write_file" && parsedResult?.bytes != null) {
1151
+ entries.push({
1152
+ command: `${toolName} bytes ${String(args.path)}`,
1153
+ ok: stat.size === Number(parsedResult.bytes),
1154
+ implicit: true,
1155
+ tool: toolName,
1156
+ path: args.path,
1157
+ detail: `expected ${Number(parsedResult.bytes)} bytes, found ${stat.size}`
1158
+ });
1159
+ }
1160
+ return entries;
1161
+ }
1162
+
1163
+ if (toolName === "delete_path") {
1164
+ const target = resolveSandboxPath(cwd, args.path, allowOutsideCwd, {
1165
+ allowedWriteRoots: writeRoots
1166
+ });
1167
+ let exists = true;
1168
+ try {
1169
+ await fs.access(target);
1170
+ } catch {
1171
+ exists = false;
1172
+ }
1173
+ return [{
1174
+ command: commandLabel,
1175
+ ok: !exists,
1176
+ implicit: true,
1177
+ tool: toolName,
1178
+ path: args.path,
1179
+ detail: exists ? "path still exists" : "path no longer exists"
1180
+ }];
1181
+ }
1182
+ } catch (error) {
1183
+ return [{
1184
+ command: commandLabel,
1185
+ ok: false,
1186
+ implicit: true,
1187
+ tool: toolName,
1188
+ path: args.path,
1189
+ detail: error instanceof Error ? error.message : String(error)
1190
+ }];
1191
+ }
1192
+
1193
+ return [];
1194
+ }
1195
+
1115
1196
  function recordToolCall(entry = {}) {
1116
1197
  currentTurn.toolCalls.push({
1117
1198
  startedAt: new Date().toISOString(),
@@ -2246,6 +2327,12 @@ ${clipped}`;
2246
2327
  if ((MUTATING_TOOLS.has(name) || name === "restore_checkpoint") && toolEntry.status === "ok") {
2247
2328
  currentTurn.mutated = true;
2248
2329
  }
2330
+ if (toolEntry.status === "ok") {
2331
+ const implicitVerification = await buildImplicitVerificationEntries(name, args, parsed);
2332
+ if (implicitVerification.length > 0) {
2333
+ currentTurn.verification = [...(currentTurn.verification || []), ...implicitVerification];
2334
+ }
2335
+ }
2249
2336
  return result;
2250
2337
  } catch (error) {
2251
2338
  toolEntry.status = "error";