dsh-git-worktree 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -0
  3. package/README.zh.md +37 -0
  4. package/lib/adapters/files.d.ts +10 -0
  5. package/lib/adapters/files.js +101 -0
  6. package/lib/adapters/files.js.map +1 -0
  7. package/lib/adapters/git.d.ts +18 -0
  8. package/lib/adapters/git.js +172 -0
  9. package/lib/adapters/git.js.map +1 -0
  10. package/lib/adapters/lookup.d.ts +28 -0
  11. package/lib/adapters/lookup.js +41 -0
  12. package/lib/adapters/lookup.js.map +1 -0
  13. package/lib/adapters/registry.d.ts +15 -0
  14. package/lib/adapters/registry.js +242 -0
  15. package/lib/adapters/registry.js.map +1 -0
  16. package/lib/adapters/safe-file.d.ts +19 -0
  17. package/lib/adapters/safe-file.js +94 -0
  18. package/lib/adapters/safe-file.js.map +1 -0
  19. package/lib/commands.d.ts +12 -0
  20. package/lib/commands.js +121 -0
  21. package/lib/commands.js.map +1 -0
  22. package/lib/index.d.ts +76 -0
  23. package/lib/index.js +93 -0
  24. package/lib/index.js.map +1 -0
  25. package/lib/managed-worktree-path.d.ts +27 -0
  26. package/lib/managed-worktree-path.js +53 -0
  27. package/lib/managed-worktree-path.js.map +1 -0
  28. package/lib/ports.d.ts +204 -0
  29. package/lib/ports.js +10 -0
  30. package/lib/ports.js.map +1 -0
  31. package/lib/session-checkout-apply.d.ts +110 -0
  32. package/lib/session-checkout-apply.js +753 -0
  33. package/lib/session-checkout-apply.js.map +1 -0
  34. package/lib/session-checkout-module.d.ts +3 -0
  35. package/lib/session-checkout-module.js +2122 -0
  36. package/lib/session-checkout-module.js.map +1 -0
  37. package/lib/tools.d.ts +12 -0
  38. package/lib/tools.js +384 -0
  39. package/lib/tools.js.map +1 -0
  40. package/lib/types.d.ts +275 -0
  41. package/lib/types.js +40 -0
  42. package/lib/types.js.map +1 -0
  43. package/package.json +60 -0
package/lib/types.d.ts ADDED
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Type surface for dsh-git-worktree, ported from Domi's session-checkout
3
+ * domain (`@proma/shared` types/session-target.ts) with the Domi-specific
4
+ * surface removed: Local preview (preview/rollback_preview/finalize_preview),
5
+ * collaborator delegation, and Electron reveal IPC. The remaining lifecycle
6
+ * is: bind → working → ready_for_review → apply/finish/discard → delivered
7
+ * (or retained/finalized), with journal-based crash recovery and fingerprint
8
+ * CAS throughout.
9
+ * @module dsh-git-worktree/types
10
+ */
11
+ /** Stable session-target reference in the durable layer. Paths and branches are not checkout identity. */
12
+ export type SessionTargetRef = {
13
+ kind: 'unselected';
14
+ } | {
15
+ kind: 'local';
16
+ } | {
17
+ kind: 'isolated';
18
+ checkoutId: string;
19
+ };
20
+ export type SessionCheckoutKind = 'local' | 'isolated';
21
+ export type SessionCheckoutPhase = 'preparing' | 'ready'
22
+ /** @deprecated v1 registry/runtime compatibility; new mutations use mutating. */
23
+ | 'applying' | 'mutating' | 'recovery_required' | 'finalized' | 'retained' | 'discarded';
24
+ export type WorktreeValidationStatus = 'passed' | 'failed' | 'partial' | 'not_run';
25
+ /** cleanup is the default immediate removal; the other values only apply when the user explicitly retains the runtime. */
26
+ export type WorktreeRetentionMode = 'cleanup' | 'retain_24h' | 'retain_3d' | 'retain_manual';
27
+ export type WorktreeCleanupReason = 'directory_busy' | 'modified_after_finalize' | 'identity_changed' | 'detached_residue' | 'quarantine_busy';
28
+ export interface WorktreeValidationItem {
29
+ command: string;
30
+ status: 'passed' | 'failed' | 'not_run';
31
+ summary?: string;
32
+ }
33
+ export interface WorktreeReviewView {
34
+ reviewId: string;
35
+ iteration: number;
36
+ preparedAt: number;
37
+ /** Deterministically rendered full Markdown body before the acceptance card. Historical records may omit it. */
38
+ detailsMarkdown?: string;
39
+ summary: string;
40
+ validationStatus: WorktreeValidationStatus;
41
+ validationSummary?: string;
42
+ tests: WorktreeValidationItem[];
43
+ changedFiles: string[];
44
+ suggestedCommitMessage: string;
45
+ }
46
+ export interface WorktreeDeliveryProofView {
47
+ /** Local branch at commit time; null means detached and automatic finish rejects that state. */
48
+ localBranch: string | null;
49
+ localHeadBefore: string;
50
+ localHeadAfter: string;
51
+ changedFiles: string[];
52
+ /** Whether this round's commit is still an ancestor of Local HEAD at view time. null when there is no commit. */
53
+ commitInLocalHistory: boolean | null;
54
+ }
55
+ export type WorktreeDeliveryView = {
56
+ state: 'working';
57
+ iteration: number;
58
+ } | {
59
+ state: 'ready_for_review';
60
+ review: WorktreeReviewView;
61
+ } | {
62
+ state: 'finalized';
63
+ review: WorktreeReviewView;
64
+ commitOid: string | null;
65
+ proof?: WorktreeDeliveryProofView;
66
+ cleanup: 'pending' | 'blocked';
67
+ cleanupMessage?: string;
68
+ } | {
69
+ state: 'retained';
70
+ review: WorktreeReviewView;
71
+ commitOid: string | null;
72
+ proof?: WorktreeDeliveryProofView;
73
+ retention: Exclude<WorktreeRetentionMode, 'cleanup'>;
74
+ retainedAt: number;
75
+ expiresAt: number | null;
76
+ cleanup: 'scheduled' | 'blocked';
77
+ cleanupMessage?: string;
78
+ } | {
79
+ state: 'delivered';
80
+ iteration: number;
81
+ commitOid: string | null;
82
+ proof?: WorktreeDeliveryProofView;
83
+ deliveredAt: number;
84
+ };
85
+ export type WorktreeApplyPreflightBlockedReason = 'not_owner' | 'not_ready_for_review' | 'stale_target' | 'stale_isolated' | 'project_acceptance_busy' | 'checkout_unavailable' | 'git_error';
86
+ export interface WorktreeApplyPreflightFacts {
87
+ checkoutId: string;
88
+ reviewId: string;
89
+ revision: number;
90
+ configuredBaseOid: string;
91
+ effectiveBaseOid: string;
92
+ baseStrategy: ApplyBaseStrategy;
93
+ localBranch: string | null;
94
+ localHeadOid: string;
95
+ isolatedHeadOid: string;
96
+ changedFiles: string[];
97
+ }
98
+ export type WorktreeApplyPreflightView = ({
99
+ status: 'ready' | 'local_advanced' | 'already_in_local';
100
+ localModified: false;
101
+ } & WorktreeApplyPreflightFacts) | ({
102
+ status: 'conflict';
103
+ localModified: false;
104
+ conflictingFiles: string[];
105
+ } & WorktreeApplyPreflightFacts) | {
106
+ status: 'blocked';
107
+ localModified: false;
108
+ checkoutId: string;
109
+ reviewId: string | null;
110
+ revision: number;
111
+ reason: WorktreeApplyPreflightBlockedReason;
112
+ message: string;
113
+ };
114
+ export interface SessionTargetProjectView {
115
+ id: string;
116
+ name: string;
117
+ }
118
+ export interface SessionTargetCheckoutView {
119
+ id: string;
120
+ kind: SessionCheckoutKind;
121
+ label: string;
122
+ phase: SessionCheckoutPhase;
123
+ }
124
+ export interface SessionTargetSourceView {
125
+ /** Source ref recorded when the target was created; detached sources use HEAD. */
126
+ ref: string;
127
+ oid: string;
128
+ }
129
+ export interface SessionTargetCurrentView {
130
+ /** null explicitly means the checkout is on detached HEAD. */
131
+ branch: string | null;
132
+ oid: string;
133
+ }
134
+ export interface SessionTargetView {
135
+ project: SessionTargetProjectView;
136
+ checkout: SessionTargetCheckoutView;
137
+ source: SessionTargetSourceView;
138
+ current: SessionTargetCurrentView;
139
+ ownership: 'owner' | 'inherited';
140
+ dirty: boolean;
141
+ revision: number;
142
+ /** Delivery state for isolated checkouts; Local targets do not carry it. */
143
+ delivery?: WorktreeDeliveryView;
144
+ }
145
+ export type SessionTargetBindChoice = {
146
+ kind: 'local';
147
+ } | {
148
+ kind: 'isolated';
149
+ };
150
+ interface SessionCheckoutOperationBase {
151
+ sessionId: string;
152
+ expectedRevision: number;
153
+ }
154
+ export interface SessionCheckoutApplyOperation extends SessionCheckoutOperationBase {
155
+ action: 'apply';
156
+ }
157
+ export interface SessionCheckoutFinishOperation extends SessionCheckoutOperationBase {
158
+ action: 'finish';
159
+ commitMessage: string;
160
+ retention?: WorktreeRetentionMode;
161
+ }
162
+ export interface SessionCheckoutRetryCleanupOperation extends SessionCheckoutOperationBase {
163
+ action: 'retry_cleanup';
164
+ }
165
+ export interface SessionCheckoutDiscardOperation extends SessionCheckoutOperationBase {
166
+ action: 'discard';
167
+ confirmDirty: boolean;
168
+ }
169
+ export interface SessionCheckoutRecoverOperation extends SessionCheckoutOperationBase {
170
+ action: 'recover';
171
+ }
172
+ export type SessionCheckoutOperation = SessionCheckoutApplyOperation | SessionCheckoutFinishOperation | SessionCheckoutRetryCleanupOperation | SessionCheckoutDiscardOperation | SessionCheckoutRecoverOperation;
173
+ export interface SessionCheckoutAppliedResult {
174
+ status: 'applied';
175
+ target: SessionTargetView;
176
+ changedFiles: string[];
177
+ }
178
+ export interface SessionCheckoutFinishedResult {
179
+ status: 'finished';
180
+ target: SessionTargetView;
181
+ changedFiles: string[];
182
+ /** null means no task delta, so no empty commit was created. */
183
+ commitOid: string | null;
184
+ /** retained means the commit succeeded and the user explicitly kept the frozen runtime. */
185
+ cleanup: 'discarded' | 'pending' | 'retained';
186
+ cleanupMessage?: string;
187
+ cleanupReason?: WorktreeCleanupReason;
188
+ }
189
+ export type ManagedWorktreeCleanupEligibility = 'safe' | 'retained' | 'blocked';
190
+ export type ManagedWorktreeCleanupBlockReason = 'working' | 'review_pending' | 'retention_active' | 'uncommitted_changes' | 'identity_mismatch' | 'cleanup_failed' | 'unknown';
191
+ /** Read-only inspection conclusion without paths. Bulk mutations re-validate; this result is never authorization. */
192
+ export interface ManagedWorktreeCleanupView {
193
+ eligibility: ManagedWorktreeCleanupEligibility;
194
+ reason: ManagedWorktreeCleanupBlockReason;
195
+ message: string;
196
+ inspectedRevision: number;
197
+ }
198
+ export interface BulkCleanupManagedWorktreeCandidate {
199
+ checkoutId: string;
200
+ expectedRevision: number;
201
+ }
202
+ export interface BulkCleanupManagedWorktreesResult {
203
+ cleaned: Array<{
204
+ checkoutId: string;
205
+ iteration: number;
206
+ commitOid: string | null;
207
+ }>;
208
+ retained: Array<{
209
+ checkoutId: string;
210
+ iteration: number;
211
+ cleanup: ManagedWorktreeCleanupView;
212
+ }>;
213
+ }
214
+ export type ManagedWorktreeSummaryState = 'working' | 'ready_for_review' | 'retained' | 'cleanup_pending' | 'needs_attention' | 'delivered';
215
+ /** Path-free projection for the management surface. */
216
+ export interface ManagedWorktreeSummaryView {
217
+ checkoutId: string;
218
+ revision: number;
219
+ ownerSessionId: string;
220
+ ownerSessionTitle: string;
221
+ project: SessionTargetProjectView;
222
+ iteration: number;
223
+ state: ManagedWorktreeSummaryState;
224
+ phase: SessionCheckoutPhase;
225
+ dirty: boolean;
226
+ commitOid: string | null;
227
+ retention?: Exclude<WorktreeRetentionMode, 'cleanup'>;
228
+ retainedAt?: number;
229
+ expiresAt?: number | null;
230
+ cleanupMessage?: string;
231
+ cleanupReason?: WorktreeCleanupReason;
232
+ approximateBytes: number | null;
233
+ updatedAt: number;
234
+ canCleanup: boolean;
235
+ /** Read-only cleanup inspection; real cleanup re-validates. */
236
+ cleanup?: ManagedWorktreeCleanupView;
237
+ /** Active owner sessions the management surface stops before a forced discard. */
238
+ activeSessionIds?: string[];
239
+ }
240
+ export type ApplyBaseStrategy = 'recorded_base' | 'isolated_contains_local_head' | 'local_contains_isolated_head';
241
+ export interface SessionCheckoutConflictResult {
242
+ status: 'conflict';
243
+ code: 'apply_conflict';
244
+ reason: 'content_conflict';
245
+ target: SessionTargetView;
246
+ baseStrategy: ApplyBaseStrategy;
247
+ effectiveBaseOid: string;
248
+ /** Local HEAD at conflict time; the agent can sync the isolated checkout to this commit and resolve. */
249
+ localHeadOid: string;
250
+ isolatedHeadOid: string;
251
+ canRetryAfterRefresh: false;
252
+ conflictingFiles: string[];
253
+ }
254
+ export interface SessionCheckoutDiscardedResult {
255
+ status: 'discarded';
256
+ target: SessionTargetView;
257
+ }
258
+ export interface SessionCheckoutRecoveredResult {
259
+ status: 'recovered';
260
+ target: SessionTargetView;
261
+ }
262
+ export interface SessionCheckoutOperationErrorResult {
263
+ status: 'error';
264
+ code: SessionCheckoutErrorCode;
265
+ message: string;
266
+ target?: SessionTargetView;
267
+ }
268
+ export type SessionCheckoutOperationResult = SessionCheckoutAppliedResult | SessionCheckoutFinishedResult | SessionCheckoutConflictResult | SessionCheckoutDiscardedResult | SessionCheckoutRecoveredResult | SessionCheckoutOperationErrorResult;
269
+ export declare const SESSION_CHECKOUT_ERROR_CODES: readonly ["session_not_found", "project_not_found", "project_root_missing", "not_git_repository", "target_unselected", "target_already_bound", "project_mismatch", "checkout_missing", "checkout_mismatch", "recovery_required", "registry_corrupt", "git_operation_failed", "not_owner", "stale_target", "dirty_confirmation_required", "apply_conflict", "apply_failed", "invalid_input", "invalid_plan", "stale_local", "stale_isolated", "git_error", "commit_isolation_conflict", "checkout_limit_reached", "project_acceptance_busy", "operation_not_allowed", "recovery_unsafe"];
270
+ export type SessionCheckoutErrorCode = typeof SESSION_CHECKOUT_ERROR_CODES[number];
271
+ export interface SessionCheckoutFailure {
272
+ code: SessionCheckoutErrorCode;
273
+ message: string;
274
+ }
275
+ export {};
package/lib/types.js ADDED
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Type surface for dsh-git-worktree, ported from Domi's session-checkout
3
+ * domain (`@proma/shared` types/session-target.ts) with the Domi-specific
4
+ * surface removed: Local preview (preview/rollback_preview/finalize_preview),
5
+ * collaborator delegation, and Electron reveal IPC. The remaining lifecycle
6
+ * is: bind → working → ready_for_review → apply/finish/discard → delivered
7
+ * (or retained/finalized), with journal-based crash recovery and fingerprint
8
+ * CAS throughout.
9
+ * @module dsh-git-worktree/types
10
+ */
11
+ export const SESSION_CHECKOUT_ERROR_CODES = [
12
+ 'session_not_found',
13
+ 'project_not_found',
14
+ 'project_root_missing',
15
+ 'not_git_repository',
16
+ 'target_unselected',
17
+ 'target_already_bound',
18
+ 'project_mismatch',
19
+ 'checkout_missing',
20
+ 'checkout_mismatch',
21
+ 'recovery_required',
22
+ 'registry_corrupt',
23
+ 'git_operation_failed',
24
+ 'not_owner',
25
+ 'stale_target',
26
+ 'dirty_confirmation_required',
27
+ 'apply_conflict',
28
+ 'apply_failed',
29
+ 'invalid_input',
30
+ 'invalid_plan',
31
+ 'stale_local',
32
+ 'stale_isolated',
33
+ 'git_error',
34
+ 'commit_isolation_conflict',
35
+ 'checkout_limit_reached',
36
+ 'project_acceptance_busy',
37
+ 'operation_not_allowed',
38
+ 'recovery_unsafe',
39
+ ];
40
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAkUH,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,mBAAmB;IACnB,mBAAmB;IACnB,sBAAsB;IACtB,oBAAoB;IACpB,mBAAmB;IACnB,sBAAsB;IACtB,kBAAkB;IAClB,kBAAkB;IAClB,mBAAmB;IACnB,mBAAmB;IACnB,kBAAkB;IAClB,sBAAsB;IACtB,WAAW;IACX,cAAc;IACd,6BAA6B;IAC7B,gBAAgB;IAChB,cAAc;IACd,eAAe;IACf,cAAc;IACd,aAAa;IACb,gBAAgB;IAChB,WAAW;IACX,2BAA2B;IAC3B,wBAAwB;IACxB,yBAAyB;IACzB,uBAAuB;IACvB,iBAAiB;CACT,CAAA"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "dsh-git-worktree",
3
+ "version": "0.1.0",
4
+ "description": "Domi-grade git worktree isolation and delivery for DeepSeek Harness: permanent worktrees, ready-for-review / apply / discard / finish lifecycle, conflict handling, and safe cleanup.",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "types": "lib/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/index.d.ts",
11
+ "default": "./lib/index.js"
12
+ },
13
+ "./manager": {
14
+ "types": "./lib/manager.d.ts",
15
+ "default": "./lib/manager.js"
16
+ },
17
+ "./package.json": "./package.json"
18
+ },
19
+ "files": [
20
+ "lib"
21
+ ],
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/wloops/dsh-git-worktree.git"
26
+ },
27
+ "bugs": {
28
+ "url": "https://github.com/wloops/dsh-git-worktree/issues"
29
+ },
30
+ "homepage": "https://github.com/wloops/dsh-git-worktree#readme",
31
+ "engines": {
32
+ "node": ">=20"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc",
36
+ "typecheck": "tsc --noEmit",
37
+ "test": "vitest run",
38
+ "prepublishOnly": "pnpm run build && pnpm run test"
39
+ },
40
+ "dependencies": {
41
+ "@deepseek-ai/cordis": "4.0.1",
42
+ "@deepseek-ai/dsh-commands": "0.1.0-rc.6",
43
+ "@deepseek-ai/dsh-subprocess": "0.1.0-rc.6",
44
+ "@deepseek-ai/dsh-tools": "0.1.0-rc.6",
45
+ "@deepseek-ai/schemastery": "3.18.1"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^22.0.0",
49
+ "typescript": "^5.6.0",
50
+ "vitest": "^2.1.0"
51
+ },
52
+ "keywords": [
53
+ "deepseek-harness",
54
+ "dsh",
55
+ "cordis",
56
+ "plugin",
57
+ "worktree",
58
+ "git"
59
+ ]
60
+ }