Commit c0cc6dd
authored
feat(workspace): gate stale worktree creation + opt-in rebase (#54)
Closes #52
Builds on #53's non-breaking staleness signal. `worktree add` now refuses
to materialize a worktree that would be more than
`datamachine_worktree_stale_threshold` commits (default 50) behind its
upstream, tearing the half-cooked checkout down and returning a
`worktree_stale` WP_Error with remediation options. Pass `--allow-stale`
to opt in, or `--rebase-base` to auto-rebase onto the upstream tip before
returning. On rebase conflicts the rebase is aborted — `--rebase-base`
is not a silent bypass.
## Behavior change
Previously: `worktree add` happily cooked on top of any local branch, no
matter how stale. Agents discovered multi-hundred-commit drift at
PR-review time when GitHub flagged conflicts.
Now: by default, a worktree that would land >50 commits behind upstream
is rolled back at create-time with a WP_Error pointing at four concrete
remediation paths:
Worktree base is 51 commits behind origin/main (threshold: 50).
Options:
- workspace git-pull data-machine-code --allow-primary-mutation
- worktree add … --from=origin/main
- worktree add … --rebase-base
- worktree add … --allow-stale
Threshold is filterable per-site/per-repo via
`datamachine_worktree_stale_threshold`.
## Rebase semantics
`--rebase-base` picks the right target per path:
- Existing-local-branch: rebase onto `@{upstream}`
- New-branch-off-local-base: rebase onto `origin/<base>`
Success clears the behind-count (worktree passes the gate cleanly).
Failure aborts the rebase, the worktree stays at its pre-rebase HEAD,
and `rebase_succeeded: false` + `rebase_error: <tail>` are surfaced.
Critically, the staleness gate STILL fires after a failed rebase —
`--rebase-base` alone on a conflicting rebase isn't a silent
`--allow-stale` bypass.
## Changes
- `Workspace::worktree_add()` — new `$allow_stale` + `$rebase_base`
params. Rebase runs before the gate (success nullifies gate). Gate
runs after staleness probe, computes filterable threshold, tears the
worktree down + returns WP_Error on violation.
- `effective_behind_count()` helper — picks the one behind-count that
matters for gating (existing-branch or new-branch-off-local-base,
whichever is present).
- `try_rebase_worktree()` helper — selects upstream target, runs rebase,
aborts on failure, zeroes the relevant behind-count on success.
- `WorkspaceAbilities` — input schema gains `allow_stale` + `rebase_base`
(both default false). Output schema gains `gate_threshold`,
`rebase_attempted`, `rebase_target`, `rebase_succeeded`, `rebase_error`.
- `WorkspaceCommand` — new `--allow-stale` + `--rebase-base` flags with
full help blocks + examples. `render_worktree_freshness()` gains a
rebase block that renders BEFORE staleness (success: "rebased onto
<target>", failure: "⚠ rebase onto <target> failed" + error tail).
- `tests/smoke-worktree-staleness.php` — 7 new real-git-fixture
assertions for rebase success (branch 2 behind → 0 behind after
rebase, consumer commit preserved) and rebase conflict handling
(non-zero exit, abort restores pre-rebase SHA, behind-count preserved).1 parent 6a5ba52 commit c0cc6dd
4 files changed
Lines changed: 369 additions & 5 deletions
File tree
- inc
- Abilities
- Cli/Commands
- Workspace
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
731 | 731 | | |
732 | 732 | | |
733 | 733 | | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
734 | 742 | | |
735 | 743 | | |
736 | 744 | | |
| |||
779 | 787 | | |
780 | 788 | | |
781 | 789 | | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
782 | 810 | | |
783 | 811 | | |
784 | 812 | | |
| |||
1215 | 1243 | | |
1216 | 1244 | | |
1217 | 1245 | | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
1218 | 1250 | | |
1219 | 1251 | | |
1220 | 1252 | | |
1221 | 1253 | | |
1222 | 1254 | | |
1223 | | - | |
| 1255 | + | |
| 1256 | + | |
| 1257 | + | |
1224 | 1258 | | |
1225 | 1259 | | |
1226 | 1260 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
920 | 920 | | |
921 | 921 | | |
922 | 922 | | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
923 | 941 | | |
924 | 942 | | |
925 | 943 | | |
| |||
976 | 994 | | |
977 | 995 | | |
978 | 996 | | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
979 | 1003 | | |
980 | 1004 | | |
981 | 1005 | | |
| |||
1015 | 1039 | | |
1016 | 1040 | | |
1017 | 1041 | | |
1018 | | - | |
| 1042 | + | |
1019 | 1043 | | |
1020 | 1044 | | |
1021 | 1045 | | |
| |||
1027 | 1051 | | |
1028 | 1052 | | |
1029 | 1053 | | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
1030 | 1058 | | |
1031 | 1059 | | |
1032 | 1060 | | |
| |||
1218 | 1246 | | |
1219 | 1247 | | |
1220 | 1248 | | |
| 1249 | + | |
1221 | 1250 | | |
1222 | 1251 | | |
1223 | 1252 | | |
| |||
1239 | 1268 | | |
1240 | 1269 | | |
1241 | 1270 | | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| 1274 | + | |
| 1275 | + | |
| 1276 | + | |
| 1277 | + | |
| 1278 | + | |
| 1279 | + | |
| 1280 | + | |
| 1281 | + | |
| 1282 | + | |
| 1283 | + | |
| 1284 | + | |
| 1285 | + | |
| 1286 | + | |
| 1287 | + | |
| 1288 | + | |
1242 | 1289 | | |
1243 | 1290 | | |
1244 | 1291 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
871 | 871 | | |
872 | 872 | | |
873 | 873 | | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
874 | 884 | | |
875 | 885 | | |
876 | 886 | | |
877 | 887 | | |
878 | 888 | | |
879 | | - | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
880 | 892 | | |
881 | | - | |
| 893 | + | |
882 | 894 | | |
883 | 895 | | |
884 | 896 | | |
| |||
987 | 999 | | |
988 | 1000 | | |
989 | 1001 | | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + | |
| 1044 | + | |
| 1045 | + | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
990 | 1065 | | |
991 | 1066 | | |
992 | 1067 | | |
| |||
1678 | 1753 | | |
1679 | 1754 | | |
1680 | 1755 | | |
| 1756 | + | |
| 1757 | + | |
| 1758 | + | |
| 1759 | + | |
| 1760 | + | |
| 1761 | + | |
| 1762 | + | |
| 1763 | + | |
| 1764 | + | |
| 1765 | + | |
| 1766 | + | |
| 1767 | + | |
| 1768 | + | |
| 1769 | + | |
| 1770 | + | |
| 1771 | + | |
| 1772 | + | |
| 1773 | + | |
| 1774 | + | |
| 1775 | + | |
| 1776 | + | |
| 1777 | + | |
| 1778 | + | |
| 1779 | + | |
| 1780 | + | |
| 1781 | + | |
| 1782 | + | |
| 1783 | + | |
| 1784 | + | |
| 1785 | + | |
| 1786 | + | |
| 1787 | + | |
| 1788 | + | |
| 1789 | + | |
| 1790 | + | |
| 1791 | + | |
| 1792 | + | |
| 1793 | + | |
| 1794 | + | |
| 1795 | + | |
| 1796 | + | |
| 1797 | + | |
| 1798 | + | |
| 1799 | + | |
| 1800 | + | |
| 1801 | + | |
| 1802 | + | |
| 1803 | + | |
| 1804 | + | |
| 1805 | + | |
| 1806 | + | |
| 1807 | + | |
| 1808 | + | |
| 1809 | + | |
| 1810 | + | |
| 1811 | + | |
| 1812 | + | |
| 1813 | + | |
| 1814 | + | |
| 1815 | + | |
| 1816 | + | |
| 1817 | + | |
| 1818 | + | |
| 1819 | + | |
| 1820 | + | |
| 1821 | + | |
| 1822 | + | |
| 1823 | + | |
| 1824 | + | |
| 1825 | + | |
| 1826 | + | |
| 1827 | + | |
| 1828 | + | |
| 1829 | + | |
| 1830 | + | |
| 1831 | + | |
| 1832 | + | |
| 1833 | + | |
| 1834 | + | |
| 1835 | + | |
| 1836 | + | |
| 1837 | + | |
| 1838 | + | |
| 1839 | + | |
| 1840 | + | |
| 1841 | + | |
| 1842 | + | |
| 1843 | + | |
| 1844 | + | |
| 1845 | + | |
| 1846 | + | |
| 1847 | + | |
| 1848 | + | |
| 1849 | + | |
| 1850 | + | |
| 1851 | + | |
| 1852 | + | |
| 1853 | + | |
| 1854 | + | |
| 1855 | + | |
| 1856 | + | |
1681 | 1857 | | |
1682 | 1858 | | |
1683 | 1859 | | |
| |||
0 commit comments