LearnNewsExamplesServices
Frontmatter
id13767
titleDream skipped outcomes must not mark successful runs
stateClosed
labels
bugaiarchitecturemodel-experience
assigneesneo-gpt
createdAtJun 21, 2026, 2:43 PM
updatedAtJun 21, 2026, 3:06 PM
githubUrlhttps://github.com/neomjs/neo/issues/13767
authorneo-gpt
commentsCount0
parentIssue13755
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJun 21, 2026, 3:06 PM

Dream skipped outcomes must not mark successful runs

Closed v13.1.0/archive-v13-1-0-chunk-5 bugaiarchitecturemodel-experience
neo-gpt
neo-gpt commented on Jun 21, 2026, 2:43 PM

Context

#13755 tracks orchestrator heavy-maintenance regression hardening after the reboot-stability push. During exact-head review of #13764, a separate accounting gap showed up in the Dream typed-outcome path: a no-op skipped result is currently recorded through the same task-state success path as a completed run.

This matters because the Agent OS scheduler now relies on durable task-state freshness for heavy-maintenance fairness. A skipped/deferred run should be observable as a skip, not as a successful maintenance completion.

Problem

ai/daemons/orchestrator/scheduling/pipeline.mjs:476-486 handles outcome.status === "skipped" by calling services.taskStateService.markCompleted(taskName).

ai/daemons/orchestrator/services/TaskStateService.mjs:190-196 documents and implements markCompleted() as a successful completion and writes lastSuccessAt.

The same service already has markSkipped() at ai/daemons/orchestrator/services/TaskStateService.mjs:211-221, documented as marking a task skipped "without treating the no-op as a successful run". The scheduler is not using that contract for typed Dream skips.

Net effect: a deferred/no-op Dream cycle can look like a successful run in durable task state, which can mask stale work and pollute the freshness signals used by the heavy-maintenance scheduler.

Architectural Reality

  • pipeline.mjs already distinguishes typed outcomes: completed, skipped, and failed. The bug is not lack of typed outcome support; it is the task-state write chosen for skipped.
  • TaskStateService already exposes the intended non-success skip primitive. This is a wiring/accounting fix, not a new state-model invention.
  • ADR 0022 defines the heavy-maintenance fairness model around freshness/staleness signals, including (now - lastRunAt) / cadenceMs ranking for lease-competing maintenance tasks. Skipped work must not be collapsed into success accounting.

Fix Direction

Route typed skipped outcomes through a non-success task-state path, preferably the existing TaskStateService.markSkipped(taskName), while preserving the current health outcome record of skipped plus skipReason.

If implementation proves lastRunAt start-time semantics also need adjustment for this exact path, document that separately in the PR body and keep the leaf bounded to typed skip accounting. Do not redesign the whole scheduler freshness model in this ticket.

Contract Ledger Matrix

Contract Current behavior Required behavior
Typed completed outcome markCompleted() + health completed unchanged
Typed skipped outcome markCompleted() + health skipped non-success task-state write + health skipped
lastSuccessAt updated for skipped outcomes via markCompleted() must not be updated by skipped outcomes
skipReason health payload recorded preserved

Acceptance Criteria

  1. runDreamTask() / scheduler typed skipped handling no longer calls the successful-completion task-state path.
  2. A skipped outcome does not update lastSuccessAt.
  3. Health-service reporting still records skipped and preserves skipReason.
  4. Focused unit coverage proves completed, skipped, and failed outcomes keep distinct task-state semantics.
  5. PR body states whether lastRunAt start-time semantics were inspected and whether they remain intentionally out of scope.

Out of Scope

  • Replacing the ADR 0022 fairness model.
  • Changing lease acquisition, lease watchdog, inherited-token handling, or wrapper crash safety. Those are covered by sibling lanes under #13755.
  • Broad task-state schema migration unless the focused test demonstrates it is necessary for this typed-outcome bug.

Avoided Traps

  • Do not treat health skipped as sufficient while task-state still says success. Both surfaces are consumed differently.
  • Do not paper over this with warning text only; the durable accounting must stop marking skips successful.
  • Do not close or supersede #13755; this is one leaf under that stability parent.

Evidence / Duplicate Sweep

  • Live code anchor checked on 2026-06-21: pipeline.mjs:481-486 routes skipped through markCompleted().
  • Live code anchor checked on 2026-06-21: TaskStateService.mjs:211-221 already provides markSkipped().
  • Live open-issue sweep checked on 2026-06-21 for #13755, deferred lastRunAt, lastRunAt skipped, markSkipped dream, and runDreamTask skipped; no equivalent open leaf found.
  • A2A recent-message sweep checked on 2026-06-21; no competing recent claim for this deferred-run accounting lane found.
  • Memory Core semantic prior-art sweep attempted, but query tools are currently degraded: embedding write canary timed out after 5000ms.

Related

  • Parent stability epic: #13755
  • Orchestrator stability root: #13624
  • Serialization/revert companion: #13762
  • Lease-status companion: #13764
  • Hung-lease watchdog companion: #13766
  • Authority: learn/agentos/decisions/0022-heavy-maintenance-scheduling-fairness.md

Handoff Retrieval Hints

Search anchors: runDreamTask skipped markCompleted, TaskStateService markSkipped, lastSuccessAt skipped outcome, ADR 0022 staleness-ratio.

tobiu referenced in commit 7c311be - "fix(ai): keep Dream skips out of success accounting (#13767) (#13769)" on Jun 21, 2026, 3:06 PM
tobiu closed this issue on Jun 21, 2026, 3:06 PM