You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
DMC primary checkouts currently serve three roles at once: default-branch reference, mutable working tree, and base for creating task worktrees. That makes stale reads and accidental default-branch mutations likely.
6
+
7
+
## Target Model
8
+
9
+
- A primary mirror is DMC-owned reference state for a remote default branch.
10
+
- Agents do feature, release, and repair work only in managed `repo@slug` worktrees.
11
+
- Mirror refresh is a narrow operation: fetch and fast-forward to the tracked remote ref.
12
+
- Dangerous operations on mirrors are blocked by default and require explicit operator approval.
13
+
- Read surfaces fail closed when a mirror is stale, diverged, detached, or otherwise unsafe unless the caller opts in with stale-read metadata.
14
+
15
+
## Migration Plan
16
+
17
+
1. Keep existing primary directories as the compatibility mirror path.
18
+
2. Enforce tactical safety first: separate primary refresh from dangerous primary mutation, and guard stale primary reads.
19
+
3. Add mirror metadata to each primary row: remote URL, tracked ref, last refresh result, freshness state, and whether local commits/dirty state block automated conversion.
20
+
4. For clean/current primaries, mark them `mirror_compatible` and allow DMC to refresh them as mirrors.
21
+
5. For dirty/diverged primaries, keep them read-protected and report a non-destructive remediation plan: preserve local commits in a worktree, push/open PR if needed, or archive before mirror conversion.
22
+
6. After migration, create release/default-branch work via explicit managed worktrees, not the mirror.
23
+
24
+
## Command Shape
25
+
26
+
- Investigation: `workspace show <repo>` then `workspace read <repo>@<slug> ...` or `workspace read <repo> ... --allow-stale-primary` when intentionally inspecting stale local state.
Copy file name to clipboardExpand all lines: inc/Abilities/WorkspaceAbilities.php
+47-25Lines changed: 47 additions & 25 deletions
Original file line number
Diff line number
Diff line change
@@ -258,6 +258,10 @@ private function registerAbilities(): void {
258
258
'type' => 'integer',
259
259
'description' => 'Maximum number of lines to return.',
260
260
),
261
+
'allow_stale_primary' => array(
262
+
'type' => 'boolean',
263
+
'description' => 'Explicitly allow reading from a stale, diverged, detached, or otherwise unsafe primary checkout. Worktree reads are unaffected.',
264
+
),
261
265
),
262
266
'required' => array( 'path' ),
263
267
),
@@ -295,6 +299,10 @@ private function registerAbilities(): void {
295
299
'type' => 'string',
296
300
'description' => 'Relative directory path within the repo (omit for root).',
297
301
),
302
+
'allow_stale_primary' => array(
303
+
'type' => 'boolean',
304
+
'description' => 'Explicitly allow listing a stale, diverged, detached, or otherwise unsafe primary checkout. Worktree reads are unaffected.',
305
+
),
298
306
),
299
307
'required' => array(),
300
308
),
@@ -356,6 +364,10 @@ private function registerAbilities(): void {
356
364
'type' => 'integer',
357
365
'description' => 'Number of surrounding lines to include for each match (default 0, max 10).',
358
366
),
367
+
'allow_stale_primary' => array(
368
+
'type' => 'boolean',
369
+
'description' => 'Explicitly allow grepping a stale, diverged, detached, or otherwise unsafe primary checkout. Worktree reads are unaffected.',
370
+
),
359
371
),
360
372
'required' => array( 'pattern' ),
361
373
),
@@ -824,7 +836,7 @@ private function registerAbilities(): void {
824
836
'datamachine-code/workspace-git-pull',
825
837
array(
826
838
'label' => 'Workspace Git Pull',
827
-
'description' => 'Run git pull --ff-only for a workspace handle. Mutating ops on the primary checkout require allow_primary_mutation=true.',
839
+
'description' => 'Run git pull --ff-only for a workspace handle. Primary refresh requires allow_primary_refresh=true; worktrees are always allowed.',
828
840
'category' => 'datamachine-code-workspace',
829
841
'input_schema' => array(
830
842
'type' => 'object',
@@ -837,9 +849,13 @@ private function registerAbilities(): void {
837
849
'type' => 'boolean',
838
850
'description' => 'Allow pull when working tree is dirty.',
839
851
),
852
+
'allow_primary_refresh' => array(
853
+
'type' => 'boolean',
854
+
'description' => 'Permit safe primary refresh with git pull --ff-only. Worktrees are always allowed.',
855
+
),
840
856
'allow_primary_mutation' => array(
841
857
'type' => 'boolean',
842
-
'description' => 'Permit mutation on the primary checkout (default false). Worktrees are always allowed.',
858
+
'description' => 'Legacy alias for allow_primary_refresh on git pull only.',
843
859
),
844
860
'remote' => array(
845
861
'type' => 'string',
@@ -965,7 +981,7 @@ private function registerAbilities(): void {
965
981
'datamachine-code/workspace-git-commit',
966
982
array(
967
983
'label' => 'Workspace Git Commit',
968
-
'description' => 'Commit staged changes in a workspace handle. Mutating ops on the primary checkout require allow_primary_mutation=true.',
984
+
'description' => 'Commit staged changes in a workspace handle. Primary commits require allow_dangerous_primary_mutation=true; use a worktree whenever possible.',
969
985
'category' => 'datamachine-code-workspace',
970
986
'input_schema' => array(
971
987
'type' => 'object',
@@ -978,9 +994,9 @@ private function registerAbilities(): void {
978
994
'type' => 'string',
979
995
'description' => 'Commit message.',
980
996
),
981
-
'allow_primary_mutation' => array(
997
+
'allow_dangerous_primary_mutation' => array(
982
998
'type' => 'boolean',
983
-
'description' => 'Permit mutation on the primary checkout (default false). Worktrees are always allowed.',
999
+
'description' => 'Permit committing on a primary checkout. Use only for an explicitly approved primary mutation.',
984
1000
),
985
1001
),
986
1002
'required' => array( 'name', 'message' ),
@@ -1021,9 +1037,9 @@ private function registerAbilities(): void {
1021
1037
'type' => 'string',
1022
1038
'description' => 'Branch override.',
1023
1039
),
1024
-
'allow_primary_mutation' => array(
1040
+
'allow_dangerous_primary_mutation' => array(
1025
1041
'type' => 'boolean',
1026
-
'description' => 'Permit pushing from the primary checkout (default false). Worktrees are always allowed.',
1042
+
'description' => 'Permit pushing from a primary checkout. Use only for an explicitly approved primary mutation.',
1027
1043
),
1028
1044
'force_with_lease' => array(
1029
1045
'type' => 'boolean',
@@ -1119,9 +1135,9 @@ private function registerAbilities(): void {
1119
1135
'type' => 'boolean',
1120
1136
'description' => 'Continue an in-progress rebase after conflicts were resolved and staged.',
1121
1137
),
1122
-
'allow_primary_mutation' => array(
1138
+
'allow_dangerous_primary_mutation' => array(
1123
1139
'type' => 'boolean',
1124
-
'description' => 'Permit mutation on a primary checkout. Default false.',
1140
+
'description' => 'Permit rebasing a primary checkout. Use only for an explicitly approved primary mutation.',
1125
1141
),
1126
1142
),
1127
1143
'required' => array( 'name' ),
@@ -1159,9 +1175,9 @@ private function registerAbilities(): void {
1159
1175
'type' => 'boolean',
1160
1176
'description' => 'Required for hard reset.',
1161
1177
),
1162
-
'allow_primary_mutation' => array(
1178
+
'allow_dangerous_primary_mutation' => array(
1163
1179
'type' => 'boolean',
1164
-
'description' => 'Permit mutation on a primary checkout. Default false.',
1180
+
'description' => 'Permit resetting a primary checkout. Use only for an explicitly approved primary mutation.',
1165
1181
),
1166
1182
),
1167
1183
'required' => array( 'name' ),
@@ -1242,9 +1258,9 @@ private function registerAbilities(): void {
1242
1258
'items' => array( 'type' => 'string' ),
1243
1259
'description' => 'Glob patterns to resolve by taking the base version during rebase conflicts.',
1244
1260
),
1245
-
'allow_primary_mutation' => array(
1261
+
'allow_dangerous_primary_mutation' => array(
1246
1262
'type' => 'boolean',
1247
-
'description' => 'Permit mutation on a primary checkout. Default false.',
1263
+
'description' => 'Permit rebasing and force-with-lease pushing from a primary checkout. Use only for an explicitly approved primary mutation.',
1248
1264
),
1249
1265
),
1250
1266
'required' => array( 'name' ),
@@ -2568,7 +2584,8 @@ public static function readFile( array $input ): array|\WP_Error {
0 commit comments