Background
ADR-0001 §5 c4 ("conflict path covered by a test fixture") requires
pinning conflict semantics, not just the response label. PR #777
(closes #772) backfilled the strict assertion set for Phase B
(Commands). PR #777's review surfaced that Phase A (Skills) — the
oldest of the three phase tests — still asserts only the response
label, leaving the same hygiene gap §5 c4 is designed to prevent.
This is a follow-up to #772 / PR #777, scoped to Phase A only.
Blocked on PR #777 merging. The strictness map below is the
post-merge snapshot. PR #777 is the one that adds the Commands row
entry; until it lands on main, :578 will not exist there. Pick
this up after gh pr view 777 --json mergedAt is non-null and rebase
any line refs against the new main before opening a PR.
Current 409-fixture strictness map (post-PR #777)
| Phase |
Stale-mtime 409 fixture |
status: "aborted" |
no-write content |
mtime_ns echo |
| A Skills |
test_web_routes_context.py:224 (TestUpdateSkill.test_mtime_conflict) |
✓ |
✗ MISSING |
✗ MISSING |
| B Commands |
test_web_routes_context.py:578 (TestCommandCRUD.test_mtime_conflict, after PR #777 merges) |
✓ |
✓ |
✗ (out of scope) |
| C Agents |
test_web_routes_context.py:772 (TestAgentCRUD.test_mtime_conflict_after_external_write) |
✓ |
✓ |
✓ |
The Agents test at :801-802 is the strictest reference shape:
assert data["mtime_ns"] == str(agent_path.stat().st_mtime_ns)
assert "overwritten" not in agent_path.read_text(encoding="utf-8")
A regression that returns 409 + status: "aborted" and then writes
body.content would currently pass TestUpdateSkill.test_mtime_conflict
unchanged.
Scope
Tighten the existing Skills test in place. One file, one method, no
new test.
packages/memtomem/tests/test_web_routes_context.py:224-232 →
TestUpdateSkill.test_mtime_conflict should additionally assert:
data["mtime_ns"] echoes the manifest's on-disk
st_mtime_ns — pins the retry-hint contract from
context_skills.py:199-208.
- The skill manifest content on disk is unchanged after the 409 —
pins the no-write semantics §5 c4 actually targets.
Bind the manifest path explicitly so both assertions reuse the same
variable:
manifest_path = tmp_path / ".memtomem" / "skills" / "conflict" / SKILL_MANIFEST
# ... PUT with stale mtime_ns ...
assert data["mtime_ns"] == str(manifest_path.stat().st_mtime_ns)
assert manifest_path.read_text(encoding="utf-8") == "# Test skill\n"
("# Test skill\n" is the default _make_skill writes — see line 43
of the test file.)
The 409 path itself already exists in production code at
packages/memtomem/src/memtomem/web/routes/context_skills.py:199-208
(current_mtime_ns != body_mtime_ns → 409 + status: "aborted").
This issue is purely test-coverage hardening — no production change.
Suggested mutation-validation step
Before commit, swap the order of atomic_write_text and the
mtime-guard in context_skills.py:199-211 so the write happens
before the conflict check. The hardened test should fail (current
test would still pass). Revert the mutation before commit. PR #777
followed this same pattern.
Acceptance
Out of scope
- Production code changes to
context_skills.py — the 409 path is
already correct.
- Phase B (Commands)
mtime_ns echo assertion — the gap exists
(Commands lacks the echo) but is not a §5 c4 requirement
("conflict semantics" = no-write, which Commands now pins). File
separately if the team wants strict three-phase echo parity.
- Phase C (Agents) — already strict.
Refs: #772 (Phase B sibling), #777 (Phase B PR), #761 (parent RFC),
#769 (ADR §5).
Background
ADR-0001 §5 c4 ("conflict path covered by a test fixture") requires
pinning conflict semantics, not just the response label. PR #777
(closes #772) backfilled the strict assertion set for Phase B
(Commands). PR #777's review surfaced that Phase A (Skills) — the
oldest of the three phase tests — still asserts only the response
label, leaving the same hygiene gap §5 c4 is designed to prevent.
This is a follow-up to #772 / PR #777, scoped to Phase A only.
Current 409-fixture strictness map (post-PR #777)
status: "aborted"mtime_nsechotest_web_routes_context.py:224(TestUpdateSkill.test_mtime_conflict)test_web_routes_context.py:578(TestCommandCRUD.test_mtime_conflict, after PR #777 merges)test_web_routes_context.py:772(TestAgentCRUD.test_mtime_conflict_after_external_write)The Agents test at
:801-802is the strictest reference shape:A regression that returns 409 +
status: "aborted"and then writesbody.contentwould currently passTestUpdateSkill.test_mtime_conflictunchanged.
Scope
Tighten the existing Skills test in place. One file, one method, no
new test.
packages/memtomem/tests/test_web_routes_context.py:224-232→TestUpdateSkill.test_mtime_conflictshould additionally assert:data["mtime_ns"]echoes the manifest's on-diskst_mtime_ns— pins the retry-hint contract fromcontext_skills.py:199-208.pins the no-write semantics §5 c4 actually targets.
Bind the manifest path explicitly so both assertions reuse the same
variable:
(
"# Test skill\n"is the default_make_skillwrites — see line 43of the test file.)
The 409 path itself already exists in production code at
packages/memtomem/src/memtomem/web/routes/context_skills.py:199-208(
current_mtime_ns != body_mtime_ns → 409 + status: "aborted").This issue is purely test-coverage hardening — no production change.
Suggested mutation-validation step
Before commit, swap the order of
atomic_write_textand themtime-guard in
context_skills.py:199-211so the write happensbefore the conflict check. The hardened test should fail (current
test would still pass). Revert the mutation before commit. PR #777
followed this same pattern.
Acceptance
TestUpdateSkill.test_mtime_conflictassertsdata["mtime_ns"]echoes the on-disk mtime AND the manifest content is unchanged.
uv run pytest -m "not ollama" packages/memtomem/tests/test_web_routes_context.pygreen.uv run ruff check packages/memtomem/tests/test_web_routes_context.pygreen.Out of scope
context_skills.py— the 409 path isalready correct.
mtime_nsecho assertion — the gap exists(Commands lacks the echo) but is not a §5 c4 requirement
("conflict semantics" = no-write, which Commands now pins). File
separately if the team wants strict three-phase echo parity.
Refs: #772 (Phase B sibling), #777 (Phase B PR), #761 (parent RFC),
#769 (ADR §5).