Summary
In /map-efficient, the documented per-subtask close order is commit → record_subtask_result → validate_step 2.4. But validate_step 2.4 runs validate_mutation_boundary against the working tree, which is clean right after the commit. It therefore sees "no files changed" and rejects with a False-progress error — even though the subtask's work was genuinely implemented and committed. The operator must call validate_step 2.4 a second time to get past the once-per-subtask nudge.
This happened on every single subtask of a 25-subtask plan.
Environment
- mapify_version:
3.10.0
- template_hash:
25848f38baf5bc9c8a088f332714ef2b654db64048a57defc6605fbc324d93de
- workflow:
/map-efficient (batch mode), resumed from /map-plan
Repro
- Monitor returns a clean verdict (
valid=true, recommendation=proceed).
- Follow the documented flow: create the per-subtask commit, then
record_subtask_result <ST> valid --commit-sha <SHA>.
- Run
python3 .map/scripts/map_orchestrator.py validate_step 2.4 --recommendation proceed.
Actual
{"valid": false, "message": "False-progress (mutation-boundary): MONITOR is closing ST-001 but NO files changed, though its contract declares affected_files=['python/e2e/results.py', 'python/incident_processor/db_client.py']. Implement the change with Edit/Write; OR if it is already satisfied or not needed, STOP and report a blocker for a contract update — do not close a subtask that did nothing."}
A second identical validate_step 2.4 call then returns {"valid": true, ...} (the subtask was added to progress_feedback_subtasks, so the once-per-subtask guard no longer fires).
Root cause (hypothesis)
validate_mutation_boundary compares the uncommitted working-tree diff (git diff / git status) to the contract's affected_files. After the per-subtask commit, the working tree is clean, so scope_report["actual"] is empty while scope_report["expected"] is non-empty → the false-progress branch in map_orchestrator.py (~line 1207-1226) fires. See progress_feedback_subtasks guard at map_orchestrator.py:348.
The validator and the documented close order contradict each other:
- Docs (map-efficient SKILL): "Commit on clean Monitor close (ALLOWED, encouraged) ... before advancing" and "validate_step 2.4 itself now runs validate_mutation_boundary."
- Validator: expects the changes to still be in the working tree at validate time.
Suggested fix (one of)
- In
validate_mutation_boundary, when the working tree is clean, diff the recorded subtask commit (last_subtask_commit_sha / the SHA passed to record_subtask_result) against its parent, instead of git diff of the working tree. That makes "files changed" reflect the committed work.
- OR document the order as validate_step 2.4 BEFORE commit (working tree dirty) — but that collides with the scope-warning for co-authored test files (separate issue) and with
record_subtask_result --commit-sha.
- OR suppress the false-progress check entirely when a
commit_sha was already recorded for the subtask and that commit touches the contract's affected_files.
Impact
Every subtask requires a redundant second validate_step 2.4 call; the first call's scary "did nothing / report a blocker" message is misleading when the work was committed.
Summary
In
/map-efficient, the documented per-subtask close order is commit →record_subtask_result→validate_step 2.4. Butvalidate_step 2.4runsvalidate_mutation_boundaryagainst the working tree, which is clean right after the commit. It therefore sees "no files changed" and rejects with a False-progress error — even though the subtask's work was genuinely implemented and committed. The operator must callvalidate_step 2.4a second time to get past the once-per-subtask nudge.This happened on every single subtask of a 25-subtask plan.
Environment
3.10.025848f38baf5bc9c8a088f332714ef2b654db64048a57defc6605fbc324d93de/map-efficient(batch mode), resumed from/map-planRepro
valid=true,recommendation=proceed).record_subtask_result <ST> valid --commit-sha <SHA>.python3 .map/scripts/map_orchestrator.py validate_step 2.4 --recommendation proceed.Actual
A second identical
validate_step 2.4call then returns{"valid": true, ...}(the subtask was added toprogress_feedback_subtasks, so the once-per-subtask guard no longer fires).Root cause (hypothesis)
validate_mutation_boundarycompares the uncommitted working-tree diff (git diff/git status) to the contract'saffected_files. After the per-subtask commit, the working tree is clean, soscope_report["actual"]is empty whilescope_report["expected"]is non-empty → the false-progress branch inmap_orchestrator.py(~line 1207-1226) fires. Seeprogress_feedback_subtasksguard atmap_orchestrator.py:348.The validator and the documented close order contradict each other:
Suggested fix (one of)
validate_mutation_boundary, when the working tree is clean, diff the recorded subtask commit (last_subtask_commit_sha/ the SHA passed torecord_subtask_result) against its parent, instead ofgit diffof the working tree. That makes "files changed" reflect the committed work.record_subtask_result --commit-sha.commit_shawas already recorded for the subtask and that commit touches the contract'saffected_files.Impact
Every subtask requires a redundant second
validate_step 2.4call; the first call's scary "did nothing / report a blocker" message is misleading when the work was committed.