@rosthq/cli 0.7.110 → 0.7.111
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/dist/index.js +36 -9
- package/dist/index.js.map +3 -3
- package/dist/runner-serve.d.ts +4 -0
- package/dist/runner-serve.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -50253,7 +50253,7 @@ Agents can suggest commitments and report progress. They should not create a new
|
|
|
50253
50253
|
order: 61,
|
|
50254
50254
|
title: "Signal guide",
|
|
50255
50255
|
summary: "How to define and read measurables so the company runs on evidence instead of status theater.",
|
|
50256
|
-
version: "2026-07-20.
|
|
50256
|
+
version: "2026-07-20.2",
|
|
50257
50257
|
public: true,
|
|
50258
50258
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
50259
50259
|
stages: ["operating_rhythm"],
|
|
@@ -50312,7 +50312,7 @@ Avoid vanity numbers, manual-only status fields, and metrics nobody can act on.
|
|
|
50312
50312
|
- Add a measurable: \`measurable.create\` (scope: seat) defines a measurable a seat owns \u2014 name, unit, direction, target, cadence. The seat owns it; readings attach to it afterward.
|
|
50313
50313
|
- Record a reading: \`{{cli}} status record --measurable-id <id> --value <n>\` (\`status.record\`, scope: seat) writes a status event with the reading. This is not gated. An agent's \`status.record\` never downgrades a human-confirmed reading: a routine agent read that lands on a period a human already confirmed leaves the confirmed value and its confirmation intact (invariants #7/#8 \u2014 agents recommend; humans decide).
|
|
50314
50314
|
- Confirm a reading: \`{{cli}} signal confirm\` / \`signal.confirm_reading\` / \`rost_confirm_signal_reading\` marks a reading human-verified. \`signal.correct_reading\` / \`rost_correct_signal_reading\` overwrites a reading with a human-confirmed value.
|
|
50315
|
-
- Draft first readings from a connected source: \`signal.draft_first_readings\` pulls a measurable's bound source once (read-only, SSRF-guarded \u2014 the same pull path as \`signal.preview\`) and lands the value as a DRAFT reading for the current period, for a human to confirm. It is for a measurable that has a connected source but
|
|
50315
|
+
- Draft first readings from a connected source: \`signal.draft_first_readings\` pulls a measurable's bound source once (read-only, SSRF-guarded \u2014 the same pull path as \`signal.preview\`) and lands the value as a DRAFT reading for the current period, for a human to confirm. It is strictly for a measurable that has a connected source but has never had a confirmed reading \u2014 in ANY period, not just the current one. A measurable that already carries a confirmed reading (even an older one) is rejected with an "already has readings" outcome and no pull happens, so the first-reading flow can never be repurposed as an ongoing draft source; use \`signal.report\` to add a current-period datapoint or \`signal.correct_reading\` to change a confirmed value instead. The Signal page shows a "Draft first readings" button on the eligible (never-measured) rows so the row stops being a permanent blank. Nothing is published \u2014 a human clears the draft with \`signal.confirm_reading\` (invariant #7) \u2014 and it never fabricates a value: a non-numeric or blocked pull drafts nothing and says so.
|
|
50316
50316
|
|
|
50317
50317
|
## Run Signal without an agent
|
|
50318
50318
|
|
|
@@ -57737,6 +57737,7 @@ ${usage()}
|
|
|
57737
57737
|
let failed = false;
|
|
57738
57738
|
let activeSessions = 0;
|
|
57739
57739
|
const activeTurnExecutionIds = /* @__PURE__ */ new Set();
|
|
57740
|
+
let serverHeartbeatContractVersion = null;
|
|
57740
57741
|
do {
|
|
57741
57742
|
const detectedCapabilities = await detectCapabilities(cliVersion, env, homeDir, config2.maxSessionsOverride);
|
|
57742
57743
|
const capabilities = capabilitiesForConfiguredRuntime(detectedCapabilities, config2.runtime);
|
|
@@ -57745,7 +57746,8 @@ ${usage()}
|
|
|
57745
57746
|
const heartbeat = await post2(fetchImpl, options.appUrl, "/api/runner/heartbeat", buildHeartbeatBody({
|
|
57746
57747
|
capabilities,
|
|
57747
57748
|
telemetry: detectTelemetry(capabilities, env, activeSessions, cliVersion),
|
|
57748
|
-
activeTurnExecutionIds: [...activeTurnExecutionIds]
|
|
57749
|
+
activeTurnExecutionIds: [...activeTurnExecutionIds],
|
|
57750
|
+
serverContractVersion: serverHeartbeatContractVersion
|
|
57749
57751
|
}), state.runner_secret);
|
|
57750
57752
|
if (heartbeat.status !== 200) {
|
|
57751
57753
|
options.io.stderr.write(`heartbeat ${heartbeat.status}: ${redactForLog(JSON.stringify(heartbeat.json))}
|
|
@@ -57753,6 +57755,10 @@ ${usage()}
|
|
|
57753
57755
|
failed = true;
|
|
57754
57756
|
} else {
|
|
57755
57757
|
heartbeatSucceeded = true;
|
|
57758
|
+
const learnedVersion = readHeartbeatContractVersion(heartbeat.json);
|
|
57759
|
+
if (learnedVersion !== null) {
|
|
57760
|
+
serverHeartbeatContractVersion = learnedVersion;
|
|
57761
|
+
}
|
|
57756
57762
|
options.io.stdout.write(`heartbeat ok #${beat} runner_id=${state.runner_id} claude=${capabilities.claude.installed} codex=${capabilities.codex.installed}
|
|
57757
57763
|
`);
|
|
57758
57764
|
}
|
|
@@ -57766,7 +57772,11 @@ ${usage()}
|
|
|
57766
57772
|
capabilities,
|
|
57767
57773
|
io: options.io,
|
|
57768
57774
|
telemetry: () => detectTelemetry(capabilities, env, activeSessions, cliVersion),
|
|
57769
|
-
activeTurnIds: () => [...activeTurnExecutionIds]
|
|
57775
|
+
activeTurnIds: () => [...activeTurnExecutionIds],
|
|
57776
|
+
serverContractVersion: () => serverHeartbeatContractVersion,
|
|
57777
|
+
recordServerContractVersion: (v) => {
|
|
57778
|
+
serverHeartbeatContractVersion = v;
|
|
57779
|
+
}
|
|
57770
57780
|
});
|
|
57771
57781
|
try {
|
|
57772
57782
|
await claimAndExecute(fetchImpl, options.appUrl, state, config2, options.io, localRuntime, activeTurnExecutionIds);
|
|
@@ -57791,13 +57801,17 @@ ${usage()}
|
|
|
57791
57801
|
localRuntime,
|
|
57792
57802
|
capabilities,
|
|
57793
57803
|
() => detectTelemetry(capabilities, env, activeSessions, cliVersion),
|
|
57794
|
-
activeTurnExecutionIds
|
|
57804
|
+
activeTurnExecutionIds,
|
|
57805
|
+
() => serverHeartbeatContractVersion,
|
|
57806
|
+
(v) => {
|
|
57807
|
+
serverHeartbeatContractVersion = v;
|
|
57808
|
+
}
|
|
57795
57809
|
);
|
|
57796
57810
|
}
|
|
57797
57811
|
} while (!config2.once);
|
|
57798
57812
|
return heartbeatSucceeded && !failed ? 0 : 1;
|
|
57799
57813
|
}
|
|
57800
|
-
async function waitForNextHeartbeat(fetchImpl, appUrl2, state, config2, io, runtime, capabilities, telemetry, activeTurnExecutionIds) {
|
|
57814
|
+
async function waitForNextHeartbeat(fetchImpl, appUrl2, state, config2, io, runtime, capabilities, telemetry, activeTurnExecutionIds, serverContractVersion, recordServerContractVersion) {
|
|
57801
57815
|
const deadline = Date.now() + config2.heartbeatMs;
|
|
57802
57816
|
const stopWait = runtime ? startTurnHeartbeat({
|
|
57803
57817
|
fetchImpl,
|
|
@@ -57807,7 +57821,9 @@ async function waitForNextHeartbeat(fetchImpl, appUrl2, state, config2, io, runt
|
|
|
57807
57821
|
capabilities,
|
|
57808
57822
|
io,
|
|
57809
57823
|
telemetry,
|
|
57810
|
-
activeTurnIds: () => [...activeTurnExecutionIds]
|
|
57824
|
+
activeTurnIds: () => [...activeTurnExecutionIds],
|
|
57825
|
+
serverContractVersion,
|
|
57826
|
+
recordServerContractVersion
|
|
57811
57827
|
}) : null;
|
|
57812
57828
|
try {
|
|
57813
57829
|
while (Date.now() < deadline) {
|
|
@@ -57827,12 +57843,17 @@ async function waitForNextHeartbeat(fetchImpl, appUrl2, state, config2, io, runt
|
|
|
57827
57843
|
stopWait?.();
|
|
57828
57844
|
}
|
|
57829
57845
|
}
|
|
57846
|
+
var HEARTBEAT_ACTIVE_TURN_MIN_CONTRACT_VERSION = 2;
|
|
57847
|
+
function readHeartbeatContractVersion(json2) {
|
|
57848
|
+
const value = json2.heartbeat_contract_version;
|
|
57849
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
57850
|
+
}
|
|
57830
57851
|
function buildHeartbeatBody(input) {
|
|
57831
57852
|
const body = {
|
|
57832
57853
|
capabilities: input.capabilities,
|
|
57833
57854
|
telemetry: input.telemetry
|
|
57834
57855
|
};
|
|
57835
|
-
if (input.activeTurnExecutionIds.length > 0) {
|
|
57856
|
+
if (input.activeTurnExecutionIds.length > 0 && (input.serverContractVersion ?? 0) >= HEARTBEAT_ACTIVE_TURN_MIN_CONTRACT_VERSION) {
|
|
57836
57857
|
body.active_turn_execution_ids = input.activeTurnExecutionIds;
|
|
57837
57858
|
}
|
|
57838
57859
|
return body;
|
|
@@ -57853,11 +57874,17 @@ function startTurnHeartbeat(deps) {
|
|
|
57853
57874
|
const response = await post2(deps.fetchImpl, deps.appUrl, "/api/runner/heartbeat", buildHeartbeatBody({
|
|
57854
57875
|
capabilities: deps.capabilities,
|
|
57855
57876
|
telemetry: deps.telemetry(),
|
|
57856
|
-
activeTurnExecutionIds: deps.activeTurnIds()
|
|
57877
|
+
activeTurnExecutionIds: deps.activeTurnIds(),
|
|
57878
|
+
serverContractVersion: deps.serverContractVersion()
|
|
57857
57879
|
}), deps.secret, controller.signal);
|
|
57858
57880
|
if (!stopped && response.status !== 200) {
|
|
57859
57881
|
deps.io.stderr.write(`turn heartbeat ${response.status}: ${redactForLog(JSON.stringify(response.json))}
|
|
57860
57882
|
`);
|
|
57883
|
+
} else if (!stopped && response.status === 200) {
|
|
57884
|
+
const learnedVersion = readHeartbeatContractVersion(response.json);
|
|
57885
|
+
if (learnedVersion !== null) {
|
|
57886
|
+
deps.recordServerContractVersion(learnedVersion);
|
|
57887
|
+
}
|
|
57861
57888
|
}
|
|
57862
57889
|
} catch (error51) {
|
|
57863
57890
|
if (!stopped) {
|