Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions template/AGENTS.md.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,22 @@ project:
tailoring is needed. Combine approaches: use `newt-hype` for the common case,
tuple structs for outliers, and `the-newtype` to unify behaviour when
defining traits across wrappers.
- Model mutually exclusive states explicitly. When a state carrier contains
correlated booleans, `Option` fields, sentinel values, or fields that must
change together, ask whether they are disguising an enum with state-specific
payloads.
- Choose state representation by who selects the transition. When the caller
chooses a small, finite sequence of operations, typestate may make illegal
call sequences unrepresentable. When input, a parser token, frame, socket
event, channel event, or scheduler chooses the next state, prefer a runtime
ADT; use an explicit stack or other runtime structure for unbounded state.
- Encapsulate transitions and mandatory finalization in the state owner.
Prefer semantic transition/result enums over mutating several correlated
fields and returning flags; consuming methods should perform required
cleanup rather than making callers remember multi-step ceremony.
- Keep genuinely independent booleans as booleans. Introduce an ADT to remove
impossible combinations or express domain alternatives, not merely to
avoid `bool`.
- Use `cap_std` and `cap_std::fs_utf8` / `camino` in place of `std::fs` and
`std::path` for enhanced cross-platform support and capability oriented
filesystem access.
Expand Down
45 changes: 45 additions & 0 deletions tests/test_agents_state_machine_guidance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Validate conditional state-machine guidance in rendered AGENTS.md files."""

from __future__ import annotations

from pathlib import Path

import pytest
from pytest_copier.plugin import CopierFixture

_STATE_MACHINE_GUIDANCE = (
"Model mutually exclusive states explicitly",
"correlated booleans, `Option` fields, sentinel values",
"disguising an enum with state-specific payloads",
"Choose state representation by who selects the transition",
"prefer a runtime ADT",
"explicit stack or other runtime structure for unbounded state",
"Encapsulate transitions and mandatory finalization in the state owner",
"semantic transition/result enums",
"Keep genuinely independent booleans as booleans",
"not merely to avoid `bool`",
)


@pytest.mark.parametrize("use_rust", [False, True])
def test_state_machine_guidance_is_limited_to_rust_extensions(
copier: CopierFixture,
tmp_path: Path,
*,
use_rust: bool,
) -> None:
"""Require state-machine guidance exactly when the Rust extension is enabled."""
variant = "rust" if use_rust else "python"
project = copier.copy(
tmp_path / variant,
project_name=f"StateMachine{variant.title()}",
package_name=f"state_machine_{variant}",
use_rust=use_rust,
)
agents = (project / "AGENTS.md").read_text(encoding="utf-8")

for fragment in _STATE_MACHINE_GUIDANCE:
assert (fragment in agents) is use_rust, (
"expected state-machine guidance presence to match the Rust-extension "
f"setting for {fragment!r}"
)
Loading