Skip to content

fix: reconcile RALPLAN HUD final state#772

Merged
Yeachan-Heo merged 2 commits into
devfrom
issue-770-ralplan-hud-stale-revision
Jun 16, 2026
Merged

fix: reconcile RALPLAN HUD final state#772
Yeachan-Heo merged 2 commits into
devfrom
issue-770-ralplan-hud-stale-revision

Conversation

@Yeachan-Heo

Copy link
Copy Markdown
Owner

Summary

  • Make visible skill active-state reconciliation consult canonical RALPLAN mode-state for terminal/locked phases so final/handoff win over stale raw or derived active entries.
  • Keep raw per-skill active entries authoritative over derived skill-active-state.json cache, then apply canonical RALPLAN terminal phase to the visible entry and HUD stage chip.
  • Add RALPLAN doctor drift detection for raw active entries and derived snapshots whose phase differs from canonical mode-state, and expose gjc ralplan doctor --json through the native RALPLAN command.

Tests

  • bun test packages/coding-agent/test/gjc-runtime/ralplan-runtime.test.ts packages/coding-agent/test/gjc-runtime/state-doctor.test.ts
  • bun --cwd=packages/coding-agent run check:types

Fixes #770

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f7af1d32f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +427 to +429
const filePath = normalizedSessionId
? path.join(stateDir, "sessions", encodePathSegment(normalizedSessionId), `${skill}-state.json`)
: path.join(stateDir, `${skill}-state.json`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use root RALPLAN phase for global HUD rows

When readVisibleSkillActiveState(cwd, sessionId) is used, session-less root active rows are still intentionally visible to that session, but this lookup switches to only .gjc/state/sessions/<id>/ralplan-state.json whenever a session id is present. For a RALPLAN run seeded without --session-id, the canonical final/handoff phase is stored in root .gjc/state/ralplan-state.json, so a session-scoped HUD read gets no canonical phase and keeps showing the stale revision active entry this change is meant to override; please fall back to the root mode-state when the visible row is global or no session mode-state exists.

Useful? React with 👍 / 👎.

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

REQUEST_CHANGES

CI is green and the final regression covers stale .gjc/state/active/ralplan.json plus stale skill-active-state.json, but the prior blocker is not fully fixed for the required terminal/locked phase set. readModeStatePhase() currently returns undefined when canonical ralplan-state.json.active === false, so a canonical terminal current_phase: "handoff"/"complete" demotion can still fail to override stale raw/derived active entries that say revision. The requirement explicitly calls out terminal/locked phases such as final/handoff; canonical terminal phase should win even when the canonical mode-state is inactive/handed off, or stale active entries should be suppressed equivalently. Add a regression with canonical current_phase: "handoff" and active: false (or the real handoff-shaped state), while raw and derived active entries remain revision, and make visible HUD/status and doctor behavior sane for that case.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

Fixed the REQUEST_CHANGES blocker in 74247b84.

Evidence:

  • readModeStatePhase() now returns canonical RALPLAN terminal/locked phases even when canonical ralplan-state.json.active === false; non-terminal inactive phases still do not override active entries.
  • Doctor drift comparison now uses the same terminal-phase rule, so inactive canonical handoff can report stale raw/derived revision entries.
  • Added regression with canonical { current_phase: "handoff", active: false } while both .gjc/state/active/ralplan.json and skill-active-state.json remain at revision; visible state/HUD renders handoff.
  • Added doctor regression for stale raw + derived active entries against canonical inactive handoff.

Verification run:

  • bunx biome check --write packages/coding-agent/src/gjc-runtime/state-runtime.ts packages/coding-agent/src/skill-state/active-state.ts packages/coding-agent/test/gjc-runtime/ralplan-runtime.test.ts
  • bun test packages/coding-agent/test/gjc-runtime/ralplan-runtime.test.ts packages/coding-agent/test/gjc-runtime/state-doctor.test.ts (53 pass)
  • bun --cwd=packages/coding-agent run check:types


[repo owner's gaebal-gajae (clawdbot) 🦞]

@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

REVIEW_PENDING_CI

Current head 74247b849b360b69dd9e39a21d393ebe906f2618 resolves the prior blocker on code review: inactive canonical RALPLAN terminal phases are now considered authoritative, and the added regressions cover canonical { current_phase: "handoff", active: false } overriding stale raw .gjc/state/active/ralplan.json plus stale derived skill-active-state.json, with doctor drift reporting for both. However, current-head GitHub checks are still pending (native-build and gjc-state-gates lanes), so merge readiness is held until CI completes green.


[repo owner's gaebal-gajae (clawdbot) 🦞]

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 74247b849b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +620 to +623
const canonicalRalplanPhase = await readModeStatePhase(cwd, sessionId, "ralplan");
return dedupeVisibleBySkill([...merged.values()], sessionId)
.filter(entry => entry.active !== false)
.map(entry => withCanonicalRalplanPhase(entry, canonicalRalplanPhase));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid applying root RALPLAN terminals to session rows

When this is called without a session id, readModeStatePhase reads the session-less .gjc/state/ralplan-state.json and then applies that terminal phase to every visible ralplan entry, including root active entries that were copied there for a session-scoped run and still carry session_id. If an older global run left the root mode-state at final or handoff, a newer gjc ralplan --session-id ... run in planner gets displayed by the root-scope HUD as terminal and has its stage chip rewritten; only apply the canonical phase to entries from the same scope/run, or skip root canonical overrides for entries with session_id.

Useful? React with 👍 / 👎.

Comment on lines +613 to +615
entryPhase: phaseFromActiveValue(entry.value),
statePhase: modeStatePhase(state.value),
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match doctor drift checks to the entry session

During an all-scope gjc ralplan doctor, the root active directory can contain a session-owned ralplan row because session-scoped activations are also copied to .gjc/state/active/ralplan.json. This new drift comparison still uses the root mode-state while inspecting that root entry, so an old global final/handoff state causes a false stale_active_state finding for a session run whose own session mode-state is correctly still planner; resolve the canonical state from the entry's session_id before comparing phases.

Useful? React with 👍 / 👎.

@Yeachan-Heo Yeachan-Heo merged commit 8989da5 into dev Jun 16, 2026
12 checks passed
@Yeachan-Heo Yeachan-Heo deleted the issue-770-ralplan-hud-stale-revision branch June 16, 2026 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant