Skip to content

feat: add colony stance toggle for task priority weights (#140)#169

Merged
itsmiso-ai merged 2 commits into
mainfrom
saffron/colony-stance-toggle
Jun 4, 2026
Merged

feat: add colony stance toggle for task priority weights (#140)#169
itsmiso-ai merged 2 commits into
mainfrom
saffron/colony-stance-toggle

Conversation

@itsmiso-ai

Copy link
Copy Markdown
Contributor

Fixes #140

Changes

  • New scripts/colony_stance.gd: Pure data model defining 4 stances (Balanced, Build, Gather, Food) with effective priority order computation and food-gather detection.
  • Modified scripts/main.gd: Integrated stance system — stance-aware task selection via get_effective_priority_order(), compact sidebar UI with 4 toggle buttons, persistence in game state, backward-compatible default to Balanced.
  • New tests/test_colony_stance.gd: Tests for stance logic, effective priority order, food-gather detection, integration with choose_task(), and save/load persistence.

Stances

Stance Effect
Balanced Default — uses player's manual priority_order unchanged
Build Puts build tasks first in task selection
Gather Puts gather tasks first in task selection
Food Adds gather_food as a special task kind that prioritizes food resources

UI

A compact stance toggle panel appears in the sidebar when the menu is open, showing 4 toggle buttons with tooltips and a description of the active stance.

Acceptance Criteria

  • ✅ Add a compact stance control (sidebar toggle panel)
  • ✅ Stance affects task priority selection in a predictable way (effective_order computation)
  • ✅ Current stance is visible in compact UI (toggle buttons + description label)
  • ✅ Changing stance produces a short event/log line ("Colony stance changed to X. Workers adjust priorities.")
  • ✅ Add tests for priority weighting behavior
  • ✅ Works in bottom and side dock modes (UI added to menu_actions which is present in both modes)

- Add ColonyStance pure data model with 4 stances: Balanced, Build, Gather, Food
- Integrate stance into choose_task() via effective priority order
- Add compact UI toggle in sidebar with 4 stance buttons and description
- Persist colony_stance in game state; backward-compatible default to Balanced
- Handle gather_food task kind for food-biased stance
- Add tests for stance logic, integration, and persistence
@itsmiso-ai
itsmiso-ai requested a review from joryirving as a code owner June 3, 2026 20:19

@its-saffron its-saffron 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.

AI Automated Review

Analysis engine: MiniMax@https://litellm.jory.dev/v1 (anthropic)

Recommendation: Approve

This PR implements the colony stance toggle feature requested in issue #140 cleanly and completely. All six acceptance criteria are satisfied, the code follows existing repository patterns, tests are comprehensive, and backward compatibility for legacy saves is preserved.


Change-by-Change Findings

scripts/colony_stance.gd (new, 62 lines)

  • Clean, pure data model — no UI/scene dependencies, easy to unit test.
  • 4 stances defined matching the issue's suggested list: Balanced, Build, Gather, Food.
  • get_effective_priority_order() correctly handles all stance cases including:
    • Balanced / empty stance → returns player order unchanged
    • Build / Gather → moves preferred kind to front (no duplication)
    • Food → adds a virtual gather_food kind first, then the rest of the player order
  • is_food_gather_task() is a small, well-scoped helper for food-biased detection.
  • Lint-clean, static, no side effects.

scripts/main.gd (modified, +103 / −4)

  • State: colony_stance defaults to STANCE_BALANCED, included in bootstrap_state() and restored in load_saved_game() with a safe default for legacy saves.
  • Persistence: state["colony_stance"] is written in persist() ✅.
  • Task selection: choose_task() now iterates over effective_order from ColonyStance.get_effective_priority_order(), and adds a gather_food-aware sort that hoists food-resource gather tasks to the front. The reservation call also covers the new kind defensively.
  • tasks_for_kind(): both "gather" and "gather_food" map to gather_gather_tasks(), so food-stance prioritization is purely a sort/sort-key concern, not a task-listing change. Good separation.
  • UI: render_stance_toggle() rebuilds the stance panel under menu_actions on each render_all() call. The existing panel is correctly removed and queue_free()d to avoid leaks. Buttons are toggle-mode, pressed state reflects colony_stance, tooltips sourced from STANCE_INFO.
  • Event log: change_stance() emits the exact log line the PR body advertises: "Colony stance changed to X. Workers adjust priorities." — matches the issue's "short event/log line" requirement.
  • Guard rails: change_stance() early-exits for unknown stances and no-op transitions.

tests/test_colony_stance.gd (new, 204 lines)

  • Covers the static model (Tests 1–9): effective priority order for every stance, no duplication, is_food_gather_task cases, full ALL_STANCES / STANCE_INFO catalog integrity.
  • Covers integration with main.gd (Test 10): drives choose_task() from a constructed main instance and confirms a task is returned.
  • Covers persistence (Tests 11–13): write/read of colony_stance, restore from a saved game, and the legacy-save fallback to STANCE_BALANCED.
  • Test runner pattern matches existing tests (extends SceneTree, custom _assert / _assert_eq, exits with non-zero on failure) so the smoke test harness in tests/test_runner.gd style should pick it up consistently.

Sources

  • PR metadata & diff: 3 files, 369+/4− lines, branch saffron/colony-stance-toggle against main.
  • Linked issue: #140ux: add colony stance toggle for task priority weights (open, in-review).
  • Repository impact scan: confirms references to #140 are limited to the new files; no unrelated files modified.
  • Repository history: head commit f328fe8 is the PR commit itself; no follow-up fixups already in history.

Standards Compliance

  • AGENTS.md — "indirect control systems for priorities, planning, and agent-driven work": ✅ stances are exactly the kind of indirect control the project is designed around.
  • AGENTS.md — "The player plans and places; workers execute": ✅ stances nudge worker behavior without assigning workers directly.
  • AGENTS.md — "Menus should be temporary popup overlays, not persistent sidebars": ✅ the stance panel lives under menu_actions and is rendered as part of the existing menu, not a new persistent sidebar.
  • AGENTS.md — "Save/version migration should be migration-first": ✅ new save field defaults gracefully for legacy saves; no migration scaffolding required because the default is a benign no-op (Balanced = original behavior).
  • CONTRIBUTING.md — test pattern: ✅ test file follows the same SceneTree-based pattern as other tests in tests/.

Linked Issue Fit

Each acceptance criterion from #140 is met:

Issue #140 criterion Status
Add a compact stance control render_stance_toggle() adds a 4-button panel
Stance affects task priority selection in a predictable way get_effective_priority_order() is pure, deterministic, and tested
Current stance is visible in compact UI ✅ toggle button button_pressed + description label reflect current stance
Changing stance produces a short event/log line push_event("Colony stance changed to X. Workers adjust priorities.")
Add tests for priority weighting behavior ✅ 9 dedicated tests on the data model + integration test
Works in bottom and side dock modes ✅ added to menu_actions, which the author states is present in both modes; consistent with how other UI sub-panels are wired

Issue intent ("modify existing task selection priorities only", "must not add direct worker assignment") is honored — the feature is purely a reordering of task-kind selection plus a sort-key tweak for food.

Evidence Provider Findings

  • None configured; no findings to report.

Tool Harness Findings

  • Harness ran 0 planned requests and warned "Could not parse planning response as JSON". This is a harness-side issue, not a PR defect — no blocking findings on the PR itself.

Unknowns / Needs Verification

  • Dock-mode coverage: I did not see the full menu_actions lifecycle in the truncated main.gd diff to confirm it is populated in both bottom and side dock modes. The PR description and prior UI wiring suggest it is, and the test suite doesn't cover UI rendering, so I'd want a quick manual editor check that the stance panel appears in both dock modes. This is a minor follow-up, not a blocker for merge.
  • Dead-code branch in reservation check: String(chosen.kind) == "gather_food" in choose_task()'s reservation is technically unreachable today because gather_gather_tasks() always emits kind: "gather". It is harmless defensive code, but worth a comment in a follow-up.

Packages

[]

No dependency changes in this PR.

Godot 4.2 treats Variant inference from Dictionary.get() as a compile error.
Add explicit :String type annotation to fix headless smoke test.

@its-saffron its-saffron 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.

AI Automated Review

Analysis engine: MiniMax@https://litellm.jory.dev/v1 (anthropic)

PR #169 Review — feat: add colony stance toggle for task priority weights

Recommendation

Approve. This PR cleanly implements issue #140 with a well‑separated data model, a compact sidebar toggle panel, predictable priority weighting, and comprehensive tests. It satisfies all six acceptance criteria from the linked issue and follows repository conventions.

Change‑by‑change Findings

scripts/colony_stance.gd (new, 62 lines)

  • Pure data model with class_name ColonyStance. Good separation from UI.
  • Constants STANCE_BALANCED/BUILD/GATHER/FOOD, ALL_STANCES, STANCE_INFO, and STANCE_PREFERRED_KIND are clearly named and self‑documenting.
  • get_effective_priority_order() is deterministic: balanced returns player_order.duplicate(); build/gather prepend the preferred kind; food prepends a synthetic gather_food kind. The dedup logic (not result.has(kind)) prevents duplication when the preferred kind already exists in the player order. ✅ Correct.
  • is_food_gather_task() is a tiny, well‑scoped predicate. ✅

scripts/main.gd (+103 / −4)

  • Adds const ColonyStance := preload(...) and a colony_stance member defaulting to balanced. Backward compatible.
  • bootstrap_state() seeds colony_stance in the new save state. load_saved_game() uses state.get("colony_stance", STANCE_BALANCED) so legacy saves degrade gracefully. persist() writes the field.
  • render_stance_toggle() builds a compact PanelContainer (title "Colony Stance", 4 toggle buttons, description label) and attaches it to menu_actions so it shows in both bottom and side dock modes. Re‑creates the panel each call to avoid stale state.
  • change_stance() validates input against ALL_STANCES, no‑ops when the value is unchanged, pushes a log line "Colony stance changed to %s. Workers adjust priorities.", and triggers render_all(). This matches the issue requirement for a short event/log line.
  • choose_task() now uses get_effective_priority_order(colony_stance, priority_order) — the integration is minimal and the default (balanced) path is unchanged.
  • tasks_for_kind("gather_food") falls through to gather_gather_tasks(), then choose_task() applies a food‑biased sort_custom using is_food_gather_task(). The chosen task's kind is still "gather", so the reservation branch String(chosen.kind) == "gather" covers it. The extra or String(chosen.kind) == "gather_food" clause is defensive (harmless, slightly redundant).

tests/test_colony_stance.gd (new, 204 lines)

  • 13 test cases covering: balanced/empty pass‑through, build/gather/food ordering, alt player order, food gather detection, stance catalog completeness, label/description non‑emptiness, main‑game integration, persist+load round‑trip, and legacy save defaulting. Strong coverage for the acceptance criteria.
  • Tests use a simple SceneTree harness with pass/fail counters and quit(1) on failure — consistent with other tests in the repo.

Linked Sources

No external sources were linked in the corpus.

Standards Compliance

  • AGENTS.md / Product Direction: The change strengthens "indirect control systems for priorities, planning" and respects the constraint that "the player plans and places; workers execute". No direct worker assignment or micromanagement is added — only priority weight tweaks.
  • AGENTS.md / UX Constraints: The toggle is added inside the existing popup menu (under menu_actions), avoiding a persistent sidebar. It is compact and consistent with the rest of the dock UI.
  • Repo conventions: Pure‑data colony_stance.gd mirrors the pattern used by rotating_goal.gd and layout_math.gd. Test file naming and SceneTree harness match the existing style.
  • Backward compatibility: Legacy saves missing colony_stance default to balanced — consistent with the schema migration guidance in AGENTS.md.

Linked Issue Fit (#140)

Issue requirement Status
Compact stance control ✅ 4 toggle buttons in a PanelContainer
Stance affects task priority in a predictable way get_effective_priority_order() is deterministic and unit‑tested
Current stance visible in compact UI ✅ Pressed‑state button + description label
Changing stance produces a short event/log line push_event("Colony stance changed to %s. Workers adjust priorities.")
Add tests for priority weighting behavior ✅ 13 tests covering catalog, ordering, detection, integration, persistence
Works in bottom and side dock modes ✅ Panel attached to menu_actions (present in both modes)
No direct worker assignment/micromanagement ✅ Only priority weights are adjusted

All acceptance criteria are met.

Evidence Provider Findings

No evidence providers configured — nothing to evaluate.

Tool Harness Findings

Tool harness returned no actionable findings ("Could not parse planning response as JSON"). Treated as a non‑signal.

Unknowns / Needs Verification

  • The menu_actions placement claim (present in both bottom and side dock modes) is consistent with the diff and the issue author's PR description, but I did not independently read scenes/main.tscn to confirm. This is a low‑risk assumption given the existing code already renders other panels into menu_actions and the issue's acceptance check is satisfied by the integration point.
  • The chosen task's kind is "gather" (not "gather_food") because tasks_for_kind returns the original gather tasks; the or String(chosen.kind) == "gather_food" clause in the reservation check is therefore redundant. Harmless, but a minor cleanup opportunity.
  • change_stance() calls render_all() which in turn recreates the stance panel — the previously pressed button may briefly toggle off before being recreated. Not a functional bug, but a small UX micro‑flicker is possible.

Verdict

approve — the implementation is correct, complete against the issue, well‑tested, and aligned with repository standards.

@itsmiso-ai
itsmiso-ai merged commit 5a37c87 into main Jun 4, 2026
4 checks passed
@itsmiso-ai
itsmiso-ai deleted the saffron/colony-stance-toggle branch June 4, 2026 09:53
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.

ux: add colony stance toggle for task priority weights

1 participant