workflow: session handover gate 실행환경 모드 분리 (#353) #354
@@ -88,6 +88,10 @@ def _check_handover_entry(
|
||||
if token not in latest:
|
||||
errors.append(f"latest handover entry missing token: {token}")
|
||||
|
||||
if strict:
|
||||
if "- next_ticket: #TBD" in latest:
|
||||
errors.append("latest handover entry must not use placeholder next_ticket (#TBD)")
|
||||
|
||||
if strict and not ci_mode:
|
||||
today_utc = datetime.now(UTC).date().isoformat()
|
||||
if today_utc not in latest:
|
||||
@@ -100,8 +104,6 @@ def _check_handover_entry(
|
||||
"latest handover entry must target current branch "
|
||||
f"({branch_token})"
|
||||
)
|
||||
if "- next_ticket: #TBD" in latest:
|
||||
errors.append("latest handover entry must not use placeholder next_ticket (#TBD)")
|
||||
if "merged_to_feature_branch=no" in latest:
|
||||
errors.append(
|
||||
"process gate indicates not merged; implementation must stay blocked "
|
||||
@@ -122,8 +124,8 @@ def main() -> int:
|
||||
"--ci",
|
||||
action="store_true",
|
||||
help=(
|
||||
"CI mode: keep structural/token checks but skip strict "
|
||||
"today-date/current-branch matching."
|
||||
"CI mode: keep structural/token checks and placeholder guard, "
|
||||
"but skip strict today-date/current-branch/merge-gate checks."
|
||||
),
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
100
tests/test_session_handover_check.py
Normal file
100
tests/test_session_handover_check.py
Normal file
@@ -0,0 +1,100 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _load_module():
|
||||
script_path = Path(__file__).resolve().parents[1] / "scripts" / "session_handover_check.py"
|
||||
spec = importlib.util.spec_from_file_location("session_handover_check", script_path)
|
||||
assert spec is not None
|
||||
assert spec.loader is not None
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
def test_ci_mode_skips_date_branch_and_merge_gate(monkeypatch, tmp_path) -> None:
|
||||
module = _load_module()
|
||||
handover = tmp_path / "session-handover.md"
|
||||
handover.write_text(
|
||||
"\n".join(
|
||||
[
|
||||
"### 2000-01-01 | session=test",
|
||||
"- branch: feature/other-branch",
|
||||
"- docs_checked: docs/workflow.md, docs/commands.md, docs/agent-constraints.md",
|
||||
"- open_issues_reviewed: #1",
|
||||
"- next_ticket: #123",
|
||||
"- process_gate_checked: process_ticket=#1 merged_to_feature_branch=no",
|
||||
]
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
monkeypatch.setattr(module, "HANDOVER_LOG", handover)
|
||||
|
||||
errors: list[str] = []
|
||||
module._check_handover_entry(
|
||||
branch="feature/current-branch",
|
||||
strict=True,
|
||||
ci_mode=True,
|
||||
errors=errors,
|
||||
)
|
||||
assert errors == []
|
||||
|
||||
|
||||
def test_ci_mode_still_blocks_tbd_next_ticket(monkeypatch, tmp_path) -> None:
|
||||
module = _load_module()
|
||||
handover = tmp_path / "session-handover.md"
|
||||
handover.write_text(
|
||||
"\n".join(
|
||||
[
|
||||
"### 2000-01-01 | session=test",
|
||||
"- branch: feature/other-branch",
|
||||
"- docs_checked: docs/workflow.md, docs/commands.md, docs/agent-constraints.md",
|
||||
"- open_issues_reviewed: #1",
|
||||
"- next_ticket: #TBD",
|
||||
"- process_gate_checked: process_ticket=#1 merged_to_feature_branch=no",
|
||||
]
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
monkeypatch.setattr(module, "HANDOVER_LOG", handover)
|
||||
|
||||
errors: list[str] = []
|
||||
module._check_handover_entry(
|
||||
branch="feature/current-branch",
|
||||
strict=True,
|
||||
ci_mode=True,
|
||||
errors=errors,
|
||||
)
|
||||
assert "latest handover entry must not use placeholder next_ticket (#TBD)" in errors
|
||||
|
||||
|
||||
def test_non_ci_strict_enforces_date_branch_and_merge_gate(monkeypatch, tmp_path) -> None:
|
||||
module = _load_module()
|
||||
handover = tmp_path / "session-handover.md"
|
||||
handover.write_text(
|
||||
"\n".join(
|
||||
[
|
||||
"### 2000-01-01 | session=test",
|
||||
"- branch: feature/other-branch",
|
||||
"- docs_checked: docs/workflow.md, docs/commands.md, docs/agent-constraints.md",
|
||||
"- open_issues_reviewed: #1",
|
||||
"- next_ticket: #123",
|
||||
"- process_gate_checked: process_ticket=#1 merged_to_feature_branch=no",
|
||||
]
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
monkeypatch.setattr(module, "HANDOVER_LOG", handover)
|
||||
|
||||
errors: list[str] = []
|
||||
module._check_handover_entry(
|
||||
branch="feature/current-branch",
|
||||
strict=True,
|
||||
ci_mode=False,
|
||||
errors=errors,
|
||||
)
|
||||
assert any("must contain today's UTC date" in e for e in errors)
|
||||
assert any("must target current branch" in e for e in errors)
|
||||
assert any("merged_to_feature_branch=no" in e for e in errors)
|
||||
Reference in New Issue
Block a user