fix: bound follower debug json output
This commit is contained in:
@@ -34,6 +34,8 @@ When a repeated runtime pitfall or visibility defect is found during branch-foll
|
||||
|
||||
`debug-step` wrappers must be failure-visible and non-crashing. If the target-side Job fails, returns an older schema, or omits optional summary fields, the operator-facing CLI must render `-`/null plus the target error and Job identity; it must not throw a local TypeError before showing the target evidence.
|
||||
|
||||
`debug-step` output must stay bounded in both text and JSON modes. The default machine payload should include step result, compact state/status/decision/write summaries, target Job identity and short error/timing fields only. Full target Job logs, full target JSON and long stdout/stderr tails belong behind explicit drill-down, not in the default `--json` payload.
|
||||
|
||||
## Source Authority
|
||||
|
||||
- Follower decisions must not read host source worktrees, target dev directories, `.worktree/*`, local git state, or direct GitHub branch refs.
|
||||
|
||||
@@ -157,16 +157,65 @@ function runTargetDebugStepJob(registry: BranchFollowerRegistry, options: Parsed
|
||||
exitCode: result.exitCode,
|
||||
timedOut: result.timedOut,
|
||||
parsed: parsed !== null,
|
||||
stdoutTail: redactText(tailText(result.stdout, options.full ? 4000 : 1000)),
|
||||
stderrTail: redactText(tailText(result.stderr, options.full ? 2000 : 800)),
|
||||
stdoutTail: redactText(tailText(result.stdout, 1000)),
|
||||
stderrTail: redactText(tailText(result.stderr, 800)),
|
||||
},
|
||||
targetResult: parsed,
|
||||
targetResult: compactTargetDebugResult(parsed),
|
||||
stateAfter: asOptionalRecord(parsed?.stateAfter) ?? stateSnapshot(state, followerId),
|
||||
parsedDownstreamCliOutput: false,
|
||||
next: debugNext(followerId),
|
||||
};
|
||||
}
|
||||
|
||||
function compactTargetDebugResult(parsed: Record<string, unknown> | null): Record<string, unknown> | null {
|
||||
if (parsed === null) return null;
|
||||
const stateBefore = asOptionalRecord(parsed.stateBefore);
|
||||
const status = asOptionalRecord(parsed.status);
|
||||
const decision = asOptionalRecord(parsed.decision);
|
||||
const stateWrite = asOptionalRecord(parsed.stateWrite);
|
||||
const stateAfter = asOptionalRecord(parsed.stateAfter);
|
||||
return {
|
||||
ok: parsed.ok === true,
|
||||
action: stringOrNull(parsed.action),
|
||||
step: stringOrNull(parsed.step),
|
||||
follower: stringOrNull(parsed.follower),
|
||||
stateBefore: compactStateLike(stateBefore),
|
||||
status: status === null ? null : {
|
||||
ok: status.ok === true,
|
||||
phase: stringOrNull(status.phase),
|
||||
observedSha: stringOrNull(status.observedSha),
|
||||
targetSha: stringOrNull(status.targetSha),
|
||||
aligned: status.aligned === true ? true : status.aligned === false ? false : null,
|
||||
pipelineRun: stringOrNull(status.pipelineRun),
|
||||
message: stringOrNull(status.message),
|
||||
},
|
||||
decision: decision === null ? null : {
|
||||
phase: stringOrNull(decision.phase),
|
||||
observedSha: stringOrNull(decision.observedSha),
|
||||
targetSha: stringOrNull(decision.targetSha),
|
||||
decision: stringOrNull(decision.decision),
|
||||
totalSeconds: numberOrNull(asOptionalRecord(decision.timings)?.totalSeconds),
|
||||
totalStatus: stringOrNull(asOptionalRecord(decision.timings)?.totalStatus),
|
||||
},
|
||||
stateWrite,
|
||||
stateAfter: compactStateLike(stateAfter),
|
||||
};
|
||||
}
|
||||
|
||||
function compactStateLike(value: Record<string, unknown> | null): Record<string, unknown> | null {
|
||||
if (value === null) return null;
|
||||
const metadata = asOptionalRecord(value.metadata);
|
||||
return {
|
||||
ok: value.ok === true,
|
||||
phase: stringOrNull(value.phase),
|
||||
observedSha: stringOrNull(value.observedSha),
|
||||
targetSha: stringOrNull(value.targetSha),
|
||||
totalSeconds: numberOrNull(value.totalSeconds),
|
||||
timingStatus: stringOrNull(value.timingStatus),
|
||||
resourceVersion: stringOrNull(metadata?.resourceVersion),
|
||||
};
|
||||
}
|
||||
|
||||
function debugDecisionOptions(options: ParsedOptions): ParsedOptions {
|
||||
return { ...options, confirm: false, dryRun: true, wait: false, recordState: false };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user