fix(lanes): expire stale stage detections, cover raw test runs in ship-feature gates

withDetected() rendered lane.detected_stage forever once written — the TTL in
recordDetection only stops future writes from advancing past a stale floor, it
never clears the row, so a lane gone quiet kept painting amber nodes from
activity that was no longer current. Also add the shared test-runner regex to
the ship-feature pipeline's `gates` node: Stage 1b's independent-test subagent
runs the repo's test command directly, not through `ccam`, and had no
detection fallback if `ccam stage tests` was skipped.
This commit is contained in:
2026-08-24 10:43:43 +07:00
parent 8bcc30fad6
commit d279af85d5
4 changed files with 35 additions and 0 deletions
+7
View File
@@ -466,8 +466,15 @@ function classifyLiveness({ status, stage, ageSec }, deadSec = DEAD_SEC) {
* would otherwise render as an inference instead of the blue `current` ring.
* Past nodes go through `stageRecords`, which resolves those alias keys — a
* node the agent DECLARED must never be painted as merely detected.
*
* A detection older than the TTL is treated the same as no detection: the TTL
* in recordDetection only stops it from holding the forward-only floor for
* FUTURE writes, it never clears the row, so without this check a lane that
* went quiet would keep painting amber nodes from activity that is no longer
* current — the exact stale-progress illusion detection exists to avoid.
*/
function withDetected(states, pipeline, lane) {
if (detectionIsStale(lane.detected_at)) return states.map((n) => ({ ...n, detected: false }));
const detectedIdx = phaseIdx(pipeline, lane.detected_stage);
if (detectedIdx === -1) return states.map((n) => ({ ...n, detected: false }));
const records = stageRecords(pipeline, lane.stages);