faberun 0.26.2 → 0.26.3
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "faberun",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.3",
|
|
4
4
|
"description": "Faberun is a development orchestration system that turns intent into verified software: harness- and model-agnostic, it keeps the intent, coordinates the work, verifies the result and decides what happens next.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/contract/runtime.mjs
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { assertObject, nonNegativeNumber, positiveInteger, positiveNumber, rejectUnknown, requireId, requireString, requireStringArray, requireTimestamp } from "./assert.mjs";
|
|
13
13
|
import { composeAssignments } from "../engine/runtime-discovery.mjs";
|
|
14
|
-
import { harnessCapabilities, resolvePermissionExecution, resolveVendor, validateCapabilityRequirements, writesWorkspace } from "../harnesses/index.mjs";
|
|
14
|
+
import { harnessCapabilities, readOnlyModeOf, resolvePermissionExecution, resolveVendor, validateCapabilityRequirements, writesWorkspace } from "../harnesses/index.mjs";
|
|
15
15
|
import { canonicalProvider } from "./provider.mjs";
|
|
16
16
|
import { stableJson } from "../util.mjs";
|
|
17
17
|
/** @typedef {import("./index.mjs").NodeStatus} NodeStatus */
|
|
@@ -246,8 +246,9 @@ export function judgeWriteWarnings(runtimes, defaults, nodes) {
|
|
|
246
246
|
const runtime = runtimes[/** @type {string} */ (id)];
|
|
247
247
|
const execution = resolvePermissionExecution(runtime);
|
|
248
248
|
if (!execution.field || runtime[execution.field] === undefined || !writesWorkspace(runtime)) return [];
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
const readOnlyMode = readOnlyModeOf(runtime);
|
|
250
|
+
if (readOnlyMode === null) return [];
|
|
251
|
+
return [`judge runtime ${id} declares ${execution.field} ${execution.mode}; a judge's verdict reaches the gate without writing, so declare ${execution.field} ${readOnlyMode}`];
|
|
251
252
|
});
|
|
252
253
|
}
|
|
253
254
|
/**
|
|
@@ -52,8 +52,11 @@ export const claudeHarness = {
|
|
|
52
52
|
signalsProcesses: true,
|
|
53
53
|
},
|
|
54
54
|
|
|
55
|
-
// Headless acceptEdits denies Bash; bypassPermissions executes commands
|
|
56
|
-
|
|
55
|
+
// Headless acceptEdits denies Bash; bypassPermissions executes commands;
|
|
56
|
+
// plan neither edits nor runs anything, the mode a judge or a preflight ask
|
|
57
|
+
// needs (measured 2026-09-27: an Opus judge left on the acceptEdits default
|
|
58
|
+
// edited the review it was grading and was blocked judge_protocol).
|
|
59
|
+
permissionExecution: { field: "permissionMode", executingModes: ["bypassPermissions"], defaultMode: "acceptEdits", readOnlyModes: ["plan"] },
|
|
57
60
|
|
|
58
61
|
/** @param {import("../index.mjs").HarnessRuntime} runtime @returns {string} */
|
|
59
62
|
executable(runtime) {
|
package/src/harnesses/index.mjs
CHANGED
|
@@ -157,6 +157,17 @@ export function resolvePermissionExecution(runtime) {
|
|
|
157
157
|
return { executes: policy.executingModes.includes(mode), field: policy.field, mode, executingModes: policy.executingModes };
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
/**
|
|
161
|
+
* The mode in which a runtime's harness cannot write its workspace, or `null`
|
|
162
|
+
* when the harness declares none.
|
|
163
|
+
*
|
|
164
|
+
* @param {{harness: string}} runtime
|
|
165
|
+
* @returns {string|null}
|
|
166
|
+
*/
|
|
167
|
+
export function readOnlyModeOf(runtime) {
|
|
168
|
+
return getHarness(runtime.harness).permissionExecution?.readOnlyModes?.[0] ?? null;
|
|
169
|
+
}
|
|
170
|
+
|
|
160
171
|
/**
|
|
161
172
|
* Whether a runtime can write its workspace. False only in a mode its adapter
|
|
162
173
|
* declares read-only; RM-058 measured a codex reviewer under `read-only`
|
package/src/plan/template.mjs
CHANGED
|
@@ -236,6 +236,25 @@ function readFilesForKind(kind, inputs) {
|
|
|
236
236
|
return [/** @type {string} */ (inputs.specPath)];
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
+
/**
|
|
240
|
+
* The wall clock one planning stage gets, from the reasoning effort of the
|
|
241
|
+
* runtime that runs it. A stage is a single long turn over the whole plan, so
|
|
242
|
+
* the contract default (2400 s) fits a draft at ordinary effort but not a
|
|
243
|
+
* revise at high effort. Measured 2026-09-27: Opus 5.5 at `xhigh` revising
|
|
244
|
+
* a 20-node plan against 13 findings was still reasoning when the 2400 s wall
|
|
245
|
+
* clock ended the stage, and the pipeline, which cannot resume a stage, lost
|
|
246
|
+
* the draft and review it had already paid for.
|
|
247
|
+
*
|
|
248
|
+
* @param {Record<string, unknown>|undefined} runtime
|
|
249
|
+
* @returns {number}
|
|
250
|
+
*/
|
|
251
|
+
export function planningStageTimeoutSec(runtime) {
|
|
252
|
+
const reasoning = runtime?.reasoning;
|
|
253
|
+
if (reasoning === "xhigh" || reasoning === "max") return 7200;
|
|
254
|
+
if (reasoning === "high") return 3600;
|
|
255
|
+
return 2400;
|
|
256
|
+
}
|
|
257
|
+
|
|
239
258
|
/**
|
|
240
259
|
* Build one of the planning pipeline's one-node discovery contracts. Pure:
|
|
241
260
|
* no file is read or written, and no model is invoked. The returned object is
|
|
@@ -273,10 +292,13 @@ export function buildPlanningContract(kind, inputs) {
|
|
|
273
292
|
verification: [],
|
|
274
293
|
};
|
|
275
294
|
|
|
295
|
+
const stageRuntime = runtimeId === undefined ? undefined : /** @type {Record<string, unknown>|undefined} */ (inputs.runtimes[runtimeId]);
|
|
296
|
+
|
|
276
297
|
return {
|
|
277
298
|
schemaVersion: PROTOCOL_SCHEMA_VERSION,
|
|
278
299
|
contractVersion: CONTRACT_VERSION,
|
|
279
300
|
id: `${inputs.campaignId}-plan-${inputs.phase}-${kind}-${inputs.n}`,
|
|
301
|
+
timeoutSec: planningStageTimeoutSec(stageRuntime),
|
|
280
302
|
campaignId: inputs.campaignId,
|
|
281
303
|
goal: inputs.goal ?? `Plan ${kind} for phase ${inputs.phase}`,
|
|
282
304
|
cwd: inputs.cwd ?? ".",
|