fix: headless EXIT_RELOAD case + notification dedup boundary
- src/headless-events.ts: add case "reload" → EXIT_RELOAD (12). EXIT_RELOAD sentinel was defined but unused — "reload" status fell through to EXIT_ERROR (1). - src/resources/extensions/sf/notification-store.ts:109: use <= for dedup window so a second identical notification at exactly DEDUP_WINDOW_MS still gets suppressed (was off-by-one at boundary). - src/resources/extensions/sf/definition-loader.ts: pending docstring tweaks from autonomous sweep. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7824cb527c
commit
038938f2ac
3 changed files with 10 additions and 2 deletions
|
|
@ -43,6 +43,8 @@ export function mapStatusToExitCode(status: string): number {
|
||||||
return EXIT_BLOCKED;
|
return EXIT_BLOCKED;
|
||||||
case "cancelled":
|
case "cancelled":
|
||||||
return EXIT_CANCELLED;
|
return EXIT_CANCELLED;
|
||||||
|
case "reload":
|
||||||
|
return EXIT_RELOAD;
|
||||||
default:
|
default:
|
||||||
return EXIT_ERROR;
|
return EXIT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ import { parse } from "yaml";
|
||||||
|
|
||||||
// ─── Public TypeScript Types (camelCase) ─────────────────────────────────
|
// ─── Public TypeScript Types (camelCase) ─────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step verification policy: content-heuristic, shell-command, prompt-verify, or human-review.
|
||||||
|
*/
|
||||||
export type VerifyPolicy =
|
export type VerifyPolicy =
|
||||||
| { policy: "content-heuristic"; minSize?: number; pattern?: string }
|
| { policy: "content-heuristic"; minSize?: number; pattern?: string }
|
||||||
| { policy: "shell-command"; command: string }
|
| { policy: "shell-command"; command: string }
|
||||||
|
|
@ -32,6 +35,9 @@ export interface IterateConfig {
|
||||||
pattern: string;
|
pattern: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Workflow step definition with prompt, dependencies, produced artifacts, and optional verification.
|
||||||
|
*/
|
||||||
export interface StepDefinition {
|
export interface StepDefinition {
|
||||||
/** Unique step identifier within the workflow. */
|
/** Unique step identifier within the workflow. */
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ export function appendNotification(
|
||||||
: `${_basePath}:${severity}:${source}:${persistedMessage}`;
|
: `${_basePath}:${severity}:${source}:${persistedMessage}`;
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const lastSeen = _recentMessageTimestamps.get(dedupKey);
|
const lastSeen = _recentMessageTimestamps.get(dedupKey);
|
||||||
if (lastSeen !== undefined && now - lastSeen < DEDUP_WINDOW_MS) return;
|
if (lastSeen !== undefined && now - lastSeen <= DEDUP_WINDOW_MS) return;
|
||||||
_recentMessageTimestamps.set(dedupKey, now);
|
_recentMessageTimestamps.set(dedupKey, now);
|
||||||
if (_recentMessageTimestamps.size > DEDUP_PRUNE_THRESHOLD) {
|
if (_recentMessageTimestamps.size > DEDUP_PRUNE_THRESHOLD) {
|
||||||
for (const [key, ts] of _recentMessageTimestamps) {
|
for (const [key, ts] of _recentMessageTimestamps) {
|
||||||
|
|
@ -347,7 +347,7 @@ function _withLock<T>(basePath: string, fn: () => T): T {
|
||||||
try {
|
try {
|
||||||
const stat = readFileSync(lockPath, "utf-8");
|
const stat = readFileSync(lockPath, "utf-8");
|
||||||
const lockTime = parseInt(stat, 10);
|
const lockTime = parseInt(stat, 10);
|
||||||
if (Date.now() - lockTime > 5000) {
|
if (Number.isFinite(lockTime) && Date.now() - lockTime > 5000) {
|
||||||
try {
|
try {
|
||||||
unlinkSync(lockPath);
|
unlinkSync(lockPath);
|
||||||
} catch {
|
} catch {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue