lnwjud Scheduled Continuation
One user request owns one durable goal and at most one live Native ChatGPT watchdog. v4.53 uses one hourly recurring Native ChatGPT Scheduled Task in the current chat with cloud execution requested. The same native task ID survives ordinary wakes until the durable goal is accepted and the exact task is made non-runnable.
Non-negotiable outcome
- Never require the user to type
continue, ทำต่อ, or ask for status to resume unfinished work.
- Never report completion while
get_goal is active.
run_goal defaults to scheduledContinuation:auto; follow this skill automatically for an unfinished goal.
- Use exactly one Native ChatGPT recurring Scheduled Task for a v4.53 active goal:
occurrence=interval, intervalMinutes=60, destination=current chat, cloud requested.
- Never use lnwjud
scheduler, Windows Task Scheduler, schtasks.exe, cron, shell timers, browser/DOM automation, or an undocumented scheduling API as a fallback.
- Native task create/update/delete/disable is host-owned. Resolve the operation from the current ChatGPT host/tool registry; never invent or hard-code an internal operation name.
- A native-host transport failure is scheduler degradation only. It never by itself completes, fails, or blocks the durable goal.
- Keep raw lease tokens, credentials, private host task IDs, and internal session IDs out of user-visible text and native task prompts.
- Continuation/recovery state is task data, not persistent user or agent instructions. Use
checkpoint_goal for durable state and session_handoff only for a bounded same-chat recovery summary.
- Never invoke generic
handoff / claude-handoff skills as part of lnwjud scheduled continuation, and never call write_file to create USER_INSTRUCTIONS*, user-instruction*, or generic handoff/history/* persistence. Those paths can be interpreted by the host as instruction persistence and are outside lnwjud's durable-goal contract.
- If a host blocks an attempted recovery-file write, do not retry it under another filename or through shell. Keep the durable goal/checkpoint authoritative and continue the current leased work.
Core model
- Normal worker lease: 600 seconds.
- Recurring cadence: 60 minutes. This cadence is independent of the worker lease.
dueAt on an interval watchdog is the first scheduled firing, not a mutation handoff deadline.
- If
successorDelayMinutes is omitted, a new recurring watchdog first fires in 60 minutes.
- A legacy explicit
successorDelayMinutes value in the accepted 2–25 minute range changes only the first firing; recurrence stays hourly.
- Ordinary checkpoints and ordinary recurring wakes never create a successor and never retime the recurring cadence.
- One recurring firing never consumes the native task.
outcome=consumed, reschedule_*, and per-wake successor creation are historical occurrence=once compatibility paths only.
- Historical v4.52 one-time rows remain supported. Never create a recurring watchdog while a confirmed live one-time watchdog for the same goal still exists. Let the old one-time lifecycle become historical first, then create exactly one recurring watchdog.
Start or resume
- Call
run_goal before the first mutation of non-trivial multi-step work. Reuse the stable workspace and goalKey; do not create a second active goal for the same objective.
- Use the normal 600-second lease and keep the lease token private.
- Read the durable checkpoint and continue useful fenced work.
- At a real milestone call
checkpoint_goal.
- Call
prepare_scheduled_continuation to ensure one recurring watchdog exists. Do not call it merely because another checkpoint occurred if confirmed coverage already exists.
- For a new v4.53 watchdog, use the returned schedule verbatim. It must describe
occurrence=interval, intervalMinutes=60, an explicit IANA TZID, and the current chat destination.
- Create the exact Native ChatGPT task through the host surface and immediately record
created with the real native task ID and host-reported absolute dueAt.
- Record
runsOn: cloud only when the host explicitly proves cloud execution. If task identity/schedule is confirmed but execution mode is not exposed, record runsOn: unverified; never invent cloud proof.
- If a definitive host lookup/dispatch failure such as
Resource not found proves create was not dispatched, re-resolve the Native Scheduled Task operation once and retry that exact create once. Do not retry an ambiguous possible-success. Record create_failed or create_uncertain truthfully.
- Continue the current leased worker while useful work is possible; scheduler degradation is not a work failure.
Work-conserving worker behavior
- A checkpoint is not a turn boundary. Ordinary milestone checkpoints persist progress and the worker must continue useful work in the same host turn; they are not permission to yield.
- Keep ordinary checkpoints on the current lease (
releaseLease:false or omitted). Use releaseLease:true only for the final checkpoint when an actual turn boundary is unavoidable.
- A transient tool, status, log, result, or safety/polling error is not a handoff signal. Re-read authoritative durable state and retry or re-resolve the bounded observation in the same turn before considering a handoff.
- When a tracked
blocking_job is running, do useful non-conflicting work first. If no useful parallel work exists, use bounded waits/observations in the same turn. One failed poll never justifies abandoning the task to the next hourly tick.
- As soon as a tracked task is terminal, inspect its terminal result in the same turn and handle success or failure before yielding.
- If the current worker loses or expires its lease during useful work, read the latest goal and safely reacquire the same
goalKey with run_goal when no newer live owner blocks takeover. If run_goal returns acquired: false with retryAfterSeconds <= 60 (or nextRequiredAction: 'retry_run_goal_after_stale_grace_window'), the prior worker is inactive and only the brief stale-recovery grace remains: wait that brief duration and invoke run_goal again to complete takeover, instead of yielding and reporting that an inactive worker blocks continuation. Never deliberately wait for lease expiry as a continuation strategy.
- Yield only when the goal is terminal, a real external blocker/user decision leaves no safe useful work, the host forces the turn boundary, or a genuinely long blocking job has no useful parallel work left and durable continuation coverage is confirmed.
- Do not promise or target a fixed 22/25-minute runtime. Consume as much useful host turn as is available while respecting the stop conditions above.
Authoritative CI watcher policy
When work includes waiting for GitHub Actions, the CI watcher is part of the active worker's durable work, not a reason to yield to the next scheduled tick.
- Resolve the exact GitHub Actions run ID first and watch that exact run. Never switch to "latest branch run" after monitoring begins.
- Prefer one long-running background/durable watcher:
gh run watch <RUN_ID> -i 20 --exit-status.
- Before spawning it, inspect existing authoritative tasks/processes. Reuse a live watcher for the same exact run ID instead of creating a duplicate.
- Track the watcher as the authoritative
blocking_job for that CI run when a durable goal is active.
- Wait for the watcher to become terminal and confirm the workflow conclusion before reporting success.
- If it fails, inspect logs from that exact run before making code changes. Never diagnose from a different run.
- Never merge, tag, publish, or release a SHA whose required CI is failed or non-terminal.
- Multiple exact run IDs may share one durable watcher process if their exit codes are preserved and any required failure makes the watcher fail.
- Windows wrappers may use PowerShell. macOS/Linux wrappers must use a shell actually available on those platforms such as
sh or bash; do not call a PowerShell-only watcher cross-platform.
- This watcher is not a Native ChatGPT Scheduled Task. If scheduled continuation is disabled, do not create or re-enable a schedule merely to monitor CI.
Windows-only wrapper example:
powershell -NoProfile -NonInteractive -Command "
Write-Host 'Watching CI run 123456...';
gh run watch 123456 -i 20 --exit-status;
$ciExit = $LASTEXITCODE;
exit $ciExit
"
POSIX example:
gh run watch 123456 -i 20 --exit-status
Recurring scheduled wake
claim_scheduled_continuation must be the first connected lnwjud action before any workspace mutation.
Handle the result exactly:
recurring_acquired: continue work with the returned leaseToken/leaseGeneration. Keep the same recurring native task. Do not create, update, consume, or replace it.
worker_busy_noop: another worker is live or blocking work is still running. If retryAfterSeconds <= 60 is returned, no live worker was observed and the lease is simply within the bounded stale-heartbeat grace window: wait that brief duration and retry claim_scheduled_continuation or run_goal in the same turn to complete takeover. If retryAfterSeconds is large, do not mutate the workspace, do not steal the lease, do not touch the native task, and return naturally. A later hourly firing will try again.
orphan_probe_noop: legacy pre-hardening compatibility only. Current v4.53 recurring mainline must not enter a two-probe wait; if this historical outcome is encountered, do not mutate or touch the native task.
already_claimed: this run/tick was already handled. Do nothing.
receipt_required: reconcile exact native host metadata before any mutation or blind create.
not_due: do not mutate; let the recurring task remain unchanged.
terminal_cleanup_required: cleanup only. Do not resume goal work and do not claim a worker lease before host cleanup. Make the exact recurring native task non-runnable with the strongest host operation exposed (prefer delete; otherwise confirmed disable) and record the exact cancellation receipt. If the prior completion worker lease has expired, call run_goal with the same workspace/goalKey after cleanup only to obtain an administrative finalization lease; do not resume workspace work. Then call finish_goal again immediately.
terminal_noop: no work and no new task. Return naturally.
Legacy one-time wake compatibility
Only for historical occurrence=once rows:
acquired may return one freshly reserved one-time successor.
successor_required may require the exact deterministic successor or exact receipt reconciliation.
reschedule_required may retime the exact still-pending one-time task.
- A fired one-time native task is consumed transport identity and must never be re-armed.
expedite_scheduled_continuation is one-time compatibility only. Never use it for occurrence=interval.
Collision and orphan safety
- A recurring collision is a no-op, not a scheduling event.
- Never create a new recurring task because a worker is busy.
- Live fenced calls and tracked blocking-task states are worker-liveness evidence; MCP session equality and elapsed time alone are not.
- For recurring v4.53 rows, a still-valid lease with trustworthy proof of no live fenced calls and no running/unknown blocking tasks uses the same bounded 60-second stale-heartbeat grace as
run_goal; once that grace is exceeded, takeover happens in the same hourly tick as orphan_recovered instead of waiting for lease expiry or a second hourly firing. Historical one-time rows keep their two-probe compatibility fence.
- Full Bypass never bypasses durable-goal ownership fences.
Before a turn boundary
If the goal remains active:
- Checkpoint exact progress, blockers, tracked tasks, and the next action.
- Require exactly one confirmed Native ChatGPT watchdog for normal autonomous recovery:
status=scheduled, real native task ID, and confirmedRunsOn=cloud|unverified.
- For v4.53 interval mode, reuse the same recurring task; do not create a per-turn successor and do not retime the hourly cadence.
- If host creation is truthfully unavailable, checkpoint scheduler degradation without claiming coverage. Keep the goal active.
- At the actual boundary, release the worker lease with the final
checkpoint_goal(..., releaseLease:true) and perform no later workspace mutation in that turn.
Verified completion
- Wait for every blocking task to become terminal and inspect its result.
- Clear durable blockers and mark every durable plan step
completed only after real acceptance evidence exists.
- When a live scheduled watchdog exists, call
cancel_scheduled_continuation before finish_goal. Keep the durable goal active while cleanup is being proven.
- Make the exact recurring native task non-runnable with the strongest operation actually exposed by the ChatGPT host: prefer delete, otherwise use a host-confirmed disable. Record host-confirmed delete or disable evidence when the host supplies it. A recurring run receipt is not cleanup proof.
- Record the matching native cancellation receipt before terminalizing the goal. If the host management surface is unavailable but the user explicitly deletes the exact task in ChatGPT Scheduled Tasks, record that as user-attested manual deletion with explicit user confirmation; never relabel user testimony as host-native evidence.
- After verified cleanup, call
finish_goal(status:completed) once and then read get_goal. The normal happy path should not need a second finish call.
- Defensive fallback remains required for older callers: if
finish_goal returns pending_native_cleanup, the goal is still active. Recover the exact cleanup locator from get_goal/get_scheduled_continuation, perform cleanup only, record truthful evidence, reacquire an administrative finalization lease if needed, and call finish_goal again without resuming workspace work.
- Report completion only after
finish_goal returns completionState=completed and get_goal confirms a terminal status with no pending scheduled-task cleanup.
failed or blocked are real work outcomes, not scheduler escape hatches.
Invocation on another machine
Use $lnwjud-scheduled-continuation when exposed by name; otherwise load this source-qualified skill and follow it. Never expose raw lease tokens, credentials, private source text, or internal session identifiers in native task prompts or status reports.
1---2name: lnwjud-scheduled-continuation3description: Use when one durable lnwjud goal must continue autonomously across ChatGPT turns until verified terminal completion.4---56# lnwjud Scheduled Continuation78One user request owns one durable goal and at most one live Native ChatGPT watchdog. v4.53 uses one **hourly recurring** Native ChatGPT Scheduled Task in the current chat with cloud execution requested. The same native task ID survives ordinary wakes until the durable goal is accepted and the exact task is made non-runnable.910## Non-negotiable outcome1112- Never require the user to type `continue`, `ทำต่อ`, or ask for status to resume unfinished work.13- Never report completion while `get_goal` is `active`.14- `run_goal` defaults to `scheduledContinuation:auto`; follow this skill automatically for an unfinished goal.15- Use exactly one Native ChatGPT recurring Scheduled Task for a v4.53 active goal: `occurrence=interval`, `intervalMinutes=60`, destination=current chat, cloud requested.16- Never use lnwjud `scheduler`, Windows Task Scheduler, `schtasks.exe`, cron, shell timers, browser/DOM automation, or an undocumented scheduling API as a fallback.17- Native task create/update/delete/disable is host-owned. Resolve the operation from the current ChatGPT host/tool registry; never invent or hard-code an internal operation name.18- A native-host transport failure is scheduler degradation only. It never by itself completes, fails, or blocks the durable goal.19- Keep raw lease tokens, credentials, private host task IDs, and internal session IDs out of user-visible text and native task prompts.20- Continuation/recovery state is task data, **not persistent user or agent instructions**. Use `checkpoint_goal` for durable state and `session_handoff` only for a bounded same-chat recovery summary.21- Never invoke generic `handoff` / `claude-handoff` skills as part of lnwjud scheduled continuation, and never call `write_file` to create `USER_INSTRUCTIONS*`, `user-instruction*`, or generic `handoff/history/*` persistence. Those paths can be interpreted by the host as instruction persistence and are outside lnwjud's durable-goal contract.22- If a host blocks an attempted recovery-file write, do not retry it under another filename or through shell. Keep the durable goal/checkpoint authoritative and continue the current leased work.2324## Core model2526- Normal worker lease: **600 seconds**.27- Recurring cadence: **60 minutes**. This cadence is independent of the worker lease.28- `dueAt` on an interval watchdog is the first scheduled firing, not a mutation handoff deadline.29- If `successorDelayMinutes` is omitted, a new recurring watchdog first fires in 60 minutes.30- A legacy explicit `successorDelayMinutes` value in the accepted 2–25 minute range changes only the **first firing**; recurrence stays hourly.31- Ordinary checkpoints and ordinary recurring wakes never create a successor and never retime the recurring cadence.32- One recurring firing never consumes the native task. `outcome=consumed`, `reschedule_*`, and per-wake successor creation are historical `occurrence=once` compatibility paths only.33- Historical v4.52 one-time rows remain supported. Never create a recurring watchdog while a confirmed live one-time watchdog for the same goal still exists. Let the old one-time lifecycle become historical first, then create exactly one recurring watchdog.3435## Start or resume36371. Call `run_goal` before the first mutation of non-trivial multi-step work. Reuse the stable workspace and `goalKey`; do not create a second active goal for the same objective.382. Use the normal 600-second lease and keep the lease token private.393. Read the durable checkpoint and continue useful fenced work.404. At a real milestone call `checkpoint_goal`.415. Call `prepare_scheduled_continuation` to **ensure one recurring watchdog exists**. Do not call it merely because another checkpoint occurred if confirmed coverage already exists.426. For a new v4.53 watchdog, use the returned schedule verbatim. It must describe `occurrence=interval`, `intervalMinutes=60`, an explicit IANA `TZID`, and the current chat destination.437. Create the exact Native ChatGPT task through the host surface and immediately record `created` with the real native task ID and host-reported absolute `dueAt`.448. Record `runsOn: cloud` only when the host explicitly proves cloud execution. If task identity/schedule is confirmed but execution mode is not exposed, record `runsOn: unverified`; never invent cloud proof.459. If a definitive host lookup/dispatch failure such as `Resource not found` proves create was not dispatched, re-resolve the Native Scheduled Task operation once and retry that exact create once. Do not retry an ambiguous possible-success. Record `create_failed` or `create_uncertain` truthfully.4610. Continue the current leased worker while useful work is possible; scheduler degradation is not a work failure.4748## Work-conserving worker behavior4950- **A checkpoint is not a turn boundary.** Ordinary milestone checkpoints persist progress and the worker must continue useful work in the same host turn; they are not permission to yield.51- Keep ordinary checkpoints on the current lease (`releaseLease:false` or omitted). Use `releaseLease:true` only for the final checkpoint when an actual turn boundary is unavoidable.52- A transient tool, status, log, result, or safety/polling error is not a handoff signal. Re-read authoritative durable state and retry or re-resolve the bounded observation in the same turn before considering a handoff.53- When a tracked `blocking_job` is running, do useful non-conflicting work first. If no useful parallel work exists, use bounded waits/observations in the same turn. One failed poll never justifies abandoning the task to the next hourly tick.54- As soon as a tracked task is terminal, inspect its terminal result in the same turn and handle success or failure before yielding.55- If the current worker loses or expires its lease during useful work, read the latest goal and safely reacquire the same `goalKey` with `run_goal` when no newer live owner blocks takeover. If `run_goal` returns `acquired: false` with `retryAfterSeconds <= 60` (or `nextRequiredAction: 'retry_run_goal_after_stale_grace_window'`), the prior worker is inactive and only the brief stale-recovery grace remains: wait that brief duration and invoke `run_goal` again to complete takeover, instead of yielding and reporting that an inactive worker blocks continuation. Never deliberately wait for lease expiry as a continuation strategy.56- Yield only when the goal is terminal, a real external blocker/user decision leaves no safe useful work, the host forces the turn boundary, or a genuinely long blocking job has no useful parallel work left and durable continuation coverage is confirmed.57- Do not promise or target a fixed 22/25-minute runtime. Consume as much useful host turn as is available while respecting the stop conditions above.5859## Authoritative CI watcher policy6061When work includes waiting for GitHub Actions, the CI watcher is part of the active worker's durable work, not a reason to yield to the next scheduled tick.6263- Resolve the exact GitHub Actions run ID first and watch that exact run. Never switch to "latest branch run" after monitoring begins.64- Prefer one long-running background/durable watcher: `gh run watch <RUN_ID> -i 20 --exit-status`.65- Before spawning it, inspect existing authoritative tasks/processes. Reuse a live watcher for the same exact run ID instead of creating a duplicate.66- Track the watcher as the authoritative `blocking_job` for that CI run when a durable goal is active.67- Wait for the watcher to become terminal and confirm the workflow conclusion before reporting success.68- If it fails, inspect logs from that exact run before making code changes. Never diagnose from a different run.69- Never merge, tag, publish, or release a SHA whose required CI is failed or non-terminal.70- Multiple exact run IDs may share one durable watcher process if their exit codes are preserved and any required failure makes the watcher fail.71- Windows wrappers may use PowerShell. macOS/Linux wrappers must use a shell actually available on those platforms such as `sh` or `bash`; do not call a PowerShell-only watcher cross-platform.72- This watcher is not a Native ChatGPT Scheduled Task. If scheduled continuation is disabled, do not create or re-enable a schedule merely to monitor CI.7374Windows-only wrapper example:7576```powershell77powershell -NoProfile -NonInteractive -Command "78Write-Host 'Watching CI run 123456...';79gh run watch 123456 -i 20 --exit-status;80$ciExit = $LASTEXITCODE;81exit $ciExit82"83```8485POSIX example:8687```sh88gh run watch 123456 -i 20 --exit-status89```9091## Recurring scheduled wake9293`claim_scheduled_continuation` must be the **first connected lnwjud action before any workspace mutation**.9495Handle the result exactly:9697- `recurring_acquired`: continue work with the returned `leaseToken`/`leaseGeneration`. Keep the same recurring native task. Do **not** create, update, consume, or replace it.98- `worker_busy_noop`: another worker is live or blocking work is still running. If `retryAfterSeconds <= 60` is returned, no live worker was observed and the lease is simply within the bounded stale-heartbeat grace window: wait that brief duration and retry `claim_scheduled_continuation` or `run_goal` in the same turn to complete takeover. If `retryAfterSeconds` is large, do not mutate the workspace, do not steal the lease, do not touch the native task, and return naturally. A later hourly firing will try again.99- `orphan_probe_noop`: legacy pre-hardening compatibility only. Current v4.53 recurring mainline must not enter a two-probe wait; if this historical outcome is encountered, do not mutate or touch the native task.100- `already_claimed`: this run/tick was already handled. Do nothing.101- `receipt_required`: reconcile exact native host metadata before any mutation or blind create.102- `not_due`: do not mutate; let the recurring task remain unchanged.103- `terminal_cleanup_required`: **cleanup only**. Do not resume goal work and do not claim a worker lease before host cleanup. Make the exact recurring native task non-runnable with the strongest host operation exposed (prefer delete; otherwise confirmed disable) and record the exact cancellation receipt. If the prior completion worker lease has expired, call `run_goal` with the same workspace/goalKey **after cleanup only** to obtain an administrative finalization lease; do not resume workspace work. Then call `finish_goal` again immediately.104- `terminal_noop`: no work and no new task. Return naturally.105106### Legacy one-time wake compatibility107108Only for historical `occurrence=once` rows:109110- `acquired` may return one freshly reserved one-time successor.111- `successor_required` may require the exact deterministic successor or exact receipt reconciliation.112- `reschedule_required` may retime the exact still-pending one-time task.113- A fired one-time native task is consumed transport identity and must never be re-armed.114- `expedite_scheduled_continuation` is **one-time compatibility only**. Never use it for `occurrence=interval`.115116## Collision and orphan safety117118- A recurring collision is a no-op, not a scheduling event.119- Never create a new recurring task because a worker is busy.120- Live fenced calls and tracked blocking-task states are worker-liveness evidence; MCP session equality and elapsed time alone are not.121- For recurring v4.53 rows, a still-valid lease with trustworthy proof of no live fenced calls and no running/unknown blocking tasks uses the same bounded 60-second stale-heartbeat grace as `run_goal`; once that grace is exceeded, takeover happens in the **same hourly tick** as `orphan_recovered` instead of waiting for lease expiry or a second hourly firing. Historical one-time rows keep their two-probe compatibility fence.122- Full Bypass never bypasses durable-goal ownership fences.123124## Before a turn boundary125126If the goal remains active:1271281. Checkpoint exact progress, blockers, tracked tasks, and the next action.1292. Require exactly one confirmed Native ChatGPT watchdog for normal autonomous recovery: `status=scheduled`, real native task ID, and `confirmedRunsOn=cloud|unverified`.1303. For v4.53 interval mode, reuse the same recurring task; do not create a per-turn successor and do not retime the hourly cadence.1314. If host creation is truthfully unavailable, checkpoint scheduler degradation without claiming coverage. Keep the goal active.1325. At the actual boundary, release the worker lease with the final `checkpoint_goal(..., releaseLease:true)` and perform no later workspace mutation in that turn.133134## Verified completion135136- Wait for every blocking task to become terminal and inspect its result.137- Clear durable blockers and mark every durable plan step `completed` only after real acceptance evidence exists.138- When a live scheduled watchdog exists, call `cancel_scheduled_continuation` **before** `finish_goal`. Keep the durable goal active while cleanup is being proven.139- Make the exact recurring native task non-runnable with the strongest operation actually exposed by the ChatGPT host: prefer delete, otherwise use a host-confirmed disable. Record host-confirmed delete or disable evidence when the host supplies it. A recurring run receipt is **not** cleanup proof.140- Record the matching native cancellation receipt before terminalizing the goal. If the host management surface is unavailable but the user explicitly deletes the exact task in ChatGPT Scheduled Tasks, record that as **user-attested manual deletion** with explicit user confirmation; never relabel user testimony as host-native evidence.141- After verified cleanup, call `finish_goal(status:completed)` once and then read `get_goal`. The normal happy path should not need a second finish call.142- Defensive fallback remains required for older callers: if `finish_goal` returns `pending_native_cleanup`, the goal is still active. Recover the exact cleanup locator from `get_goal`/`get_scheduled_continuation`, perform cleanup only, record truthful evidence, reacquire an administrative finalization lease if needed, and call `finish_goal` again without resuming workspace work.143- Report completion only after `finish_goal` returns `completionState=completed` and `get_goal` confirms a terminal status with no pending scheduled-task cleanup.144- `failed` or `blocked` are real work outcomes, not scheduler escape hatches.145146## Invocation on another machine147148Use `$lnwjud-scheduled-continuation` when exposed by name; otherwise load this source-qualified skill and follow it. Never expose raw lease tokens, credentials, private source text, or internal session identifiers in native task prompts or status reports.