dsh-hashline-edit 0.2.0 → 0.2.2

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 (109) hide show
  1. package/README.md +59 -55
  2. package/cordis.patch.yml +1 -1
  3. package/lib/index.js +7225 -6445
  4. package/lib/types/dsh/contracts.d.ts +3 -12
  5. package/lib/types/dsh/fs.d.ts +0 -3
  6. package/lib/types/dsh/guidance.d.ts +5 -5
  7. package/lib/types/dsh/host-compat.d.ts +78 -7
  8. package/lib/types/dsh/index.d.ts +7 -17
  9. package/lib/types/dsh/metrics/events.d.ts +1 -1
  10. package/lib/types/dsh/metrics/observer.d.ts +1 -1
  11. package/lib/types/dsh/sandbox.d.ts +2 -2
  12. package/lib/types/dsh/shell-hook.d.ts +1 -1
  13. package/lib/types/dsh/tools/edit.d.ts +10 -0
  14. package/lib/types/dsh/tools/read.d.ts +3 -3
  15. package/lib/types/src/domain-errors.d.ts +2 -16
  16. package/lib/types/src/edit-tool.d.ts +41 -0
  17. package/lib/types/src/edit-undo.d.ts +2 -11
  18. package/lib/types/src/file-content/index.d.ts +1 -1
  19. package/lib/types/src/file-content/preview.d.ts +1 -1
  20. package/lib/types/src/hash-store.d.ts +2 -2
  21. package/lib/types/src/hashline/alphabet.d.ts +16 -1
  22. package/lib/types/src/hashline/hash-identity.d.ts +10 -4
  23. package/lib/types/src/mutation-engine/engine.d.ts +31 -0
  24. package/lib/types/src/mutation-engine/pipeline.d.ts +1 -8
  25. package/lib/types/src/mutation-engine/types.d.ts +50 -40
  26. package/lib/types/src/payload-contract.d.ts +135 -0
  27. package/lib/types/src/served-session/serve-render.d.ts +0 -6
  28. package/lib/types/src/undo-store.d.ts +1 -17
  29. package/package.json +21 -10
  30. package/prompts/edit-guidelines.md +10 -0
  31. package/prompts/edit-snippet.md +1 -0
  32. package/prompts/edit.md +1 -0
  33. package/prompts/read-guidelines.md +4 -4
  34. package/prompts/read.md +1 -1
  35. package/prompts/undo-last-edit-guidelines.md +2 -2
  36. package/prompts/undo-last-edit-snippet.md +1 -1
  37. package/prompts/undo-last-edit.md +1 -1
  38. package/src/bash-classifier.ts +1626 -0
  39. package/src/bash-conversion/decide.ts +812 -0
  40. package/src/bash-display-transform.ts +50 -0
  41. package/src/bash-multifile-config.ts +239 -0
  42. package/src/bash-view-config.ts +158 -0
  43. package/src/cut-repair.ts +11 -77
  44. package/src/domain-errors.ts +3 -35
  45. package/src/edit-normalize.ts +8 -0
  46. package/src/edit-render.ts +161 -0
  47. package/src/edit-tool.ts +118 -0
  48. package/src/edit-undo.ts +25 -379
  49. package/src/edit.ts +136 -0
  50. package/src/file-content/index.ts +1 -1
  51. package/src/file-content/preview.ts +1 -1
  52. package/src/file-content/served-header.ts +1 -1
  53. package/src/hash-store.ts +1 -18
  54. package/src/hashline/alphabet.ts +42 -1
  55. package/src/hashline/hash-identity.ts +12 -3
  56. package/src/integrations/pi-lens/command.ts +712 -0
  57. package/src/integrations/pi-lens/config.ts +148 -0
  58. package/src/integrations/pi-lens/io-bridge-adapter.ts +234 -0
  59. package/src/integrations/pi-lens/io-bridge.ts +112 -0
  60. package/src/integrations/pi-lens/settings-overlay.ts +272 -0
  61. package/src/lifecycle-hooks/index.ts +1992 -0
  62. package/src/lifecycle-hooks/types.ts +64 -0
  63. package/src/mutated-files.ts +75 -0
  64. package/src/mutation-engine/engine.ts +239 -0
  65. package/src/mutation-engine/index.ts +17 -0
  66. package/src/mutation-engine/pipeline.ts +27 -198
  67. package/src/mutation-engine/types.ts +57 -39
  68. package/src/mutation-queue.ts +1 -1
  69. package/src/payload-contract.ts +685 -0
  70. package/src/preview-controller.ts +84 -0
  71. package/src/prompts.ts +43 -10
  72. package/src/read.ts +865 -0
  73. package/src/search-hook.ts +41 -0
  74. package/src/served-session/serve-render.ts +2 -2
  75. package/src/store-config.ts +73 -0
  76. package/src/store-janitor-warning.ts +169 -0
  77. package/src/store-janitor.ts +539 -0
  78. package/src/store-kernel/settings.ts +233 -0
  79. package/src/store.ts +154 -0
  80. package/src/tui-presenter.ts +134 -0
  81. package/src/undo-store.ts +5 -74
  82. package/src/write-hook.ts +130 -0
  83. package/lib/types/dsh/hide.d.ts +0 -78
  84. package/lib/types/dsh/tools/apply-patch.d.ts +0 -38
  85. package/lib/types/src/apply-patch/commit.d.ts +0 -49
  86. package/lib/types/src/apply-patch/grammar.d.ts +0 -29
  87. package/lib/types/src/apply-patch/lifecycle.d.ts +0 -32
  88. package/lib/types/src/apply-patch/plan.d.ts +0 -50
  89. package/lib/types/src/apply-patch/render.d.ts +0 -51
  90. package/lib/types/src/apply-patch/resolve.d.ts +0 -129
  91. package/lib/types/src/apply-patch/tool.d.ts +0 -54
  92. package/lib/types/src/apply-patch/types.d.ts +0 -362
  93. package/lib/types/src/fs-lifecycle.d.ts +0 -44
  94. package/lib/types/src/host-utils.d.ts +0 -63
  95. package/lib/types/src/mutation-engine/edit-request.d.ts +0 -34
  96. package/prompts/apply-patch-guidelines.md +0 -10
  97. package/prompts/apply-patch.md +0 -1
  98. package/src/apply-patch/commit.ts +0 -190
  99. package/src/apply-patch/grammar.ts +0 -620
  100. package/src/apply-patch/index.ts +0 -17
  101. package/src/apply-patch/lifecycle.ts +0 -195
  102. package/src/apply-patch/plan.ts +0 -800
  103. package/src/apply-patch/render.ts +0 -137
  104. package/src/apply-patch/resolve.ts +0 -470
  105. package/src/apply-patch/tool.ts +0 -257
  106. package/src/apply-patch/types.ts +0 -387
  107. package/src/fs-lifecycle.ts +0 -201
  108. package/src/host-utils.ts +0 -224
  109. package/src/mutation-engine/edit-request.ts +0 -39
@@ -1,362 +0,0 @@
1
- /**
2
- * apply_patch v4 — shared contract types.
3
- *
4
- * This module is the frozen vocabulary every apply-patch lane compiles against:
5
- *
6
- * - the **patch AST** the grammar layer produces (`PatchDocument`),
7
- * - the **plan IR** the planner produces and the transaction layer commits
8
- * (`PatchPlan`, `PlannedFile`, `PlannedMutation`),
9
- * - the **result / error** types the renderer and the host adapter consume.
10
- *
11
- * The engine underneath is the existing hashline kernel: content-addressed 4-char
12
- * anchors, served leases, MVCC snapshots, correlated multi-file transactions and
13
- * the undo store. Nothing here re-declares those primitives; the plan IR only
14
- * adds the addressing and lifecycle vocabulary apply_patch needs.
15
- *
16
- * Vocabulary (see GLOSSARY.md): anchor, served row, lease, fragment hunk,
17
- * identity hunk, reference hunk, patch line, plan.
18
- *
19
- * @module dsh-hashline-edit/apply-patch/types
20
- */
21
- import type { DomainErrorCode, ServedRow } from "../domain-errors.js";
22
- import type { LineEnding } from "../edit-diff.js";
23
- import type { HashStore } from "../hash-store.js";
24
- import type { TransactionRecoveryReport } from "../mutation-engine/types.js";
25
- /** Patch AST (grammar layer output). */
26
- /** A 4-character anchor: `[A-Za-z0-9]{4}` (the hashline alphabet). */
27
- export type Anchor = string;
28
- /** A 1-based line number in the submitted patch text, used by every diagnostic. */
29
- export type PatchLineNumber = number;
30
- /** A path exactly as written in the patch: workspace-relative or workspace-absolute. */
31
- export type PatchPath = string;
32
- /** A closed anchor span; both anchors must have been served for the same file. */
33
- export interface AnchorSpan {
34
- readonly from: Anchor;
35
- readonly to: Anchor;
36
- }
37
- /** One parsed `*** Begin Patch` … `*** End Patch` document. */
38
- export interface PatchDocument {
39
- /** File operations in submission order. */
40
- readonly files: readonly PatchFileOp[];
41
- /** Total number of lines in the input (1-based diagnostics may point at EOF). */
42
- readonly lineCount: number;
43
- }
44
- export type PatchFileOp = AddFileOp | DeleteFileOp | UpdateFileOp;
45
- /** `*** Add File: <path>` — every following line is a '+' content line. */
46
- export interface AddFileOp {
47
- readonly kind: "add";
48
- readonly path: PatchPath;
49
- readonly headerLine: PatchLineNumber;
50
- /** Content lines WITHOUT the leading '+', in file order. Empty means an empty file. */
51
- readonly contentLines: readonly string[];
52
- }
53
- /** `*** Delete File: <path>` */
54
- export interface DeleteFileOp {
55
- readonly kind: "delete";
56
- readonly path: PatchPath;
57
- readonly headerLine: PatchLineNumber;
58
- }
59
- /** `*** Update File: <path>` with its optional `*** Move to:` and zero or more hunks. */
60
- export interface UpdateFileOp {
61
- readonly kind: "update";
62
- readonly path: PatchPath;
63
- readonly headerLine: PatchLineNumber;
64
- /** `*** Move to: <path>`; the parser only accepts it directly after the update header. */
65
- readonly moveTo?: MoveDirective;
66
- /** Hunks in submission order; each hunk's window starts after the previous hunk's end. */
67
- readonly hunks: readonly PatchHunk[];
68
- }
69
- /** `*** Move to: <path>` */
70
- export interface MoveDirective {
71
- readonly path: PatchPath;
72
- readonly line: PatchLineNumber;
73
- }
74
- export type PatchHunk = FragmentHunk | IdentityHunk | ReferenceHunk;
75
- /**
76
- * The addressing a hunk opens with.
77
- *
78
- * `start` is the bare `@@` (fragment mode, search from the file start);
79
- * `context` is `@@ <line>` (fragment mode, search window starts after that
80
- * line's unique hit); `anchors` is `@@<a>` / `@@<a>-<b>` (identity mode).
81
- */
82
- export type HunkAddress = {
83
- readonly kind: "start";
84
- } | {
85
- readonly kind: "context";
86
- readonly text: string;
87
- } | {
88
- readonly kind: "anchors";
89
- readonly span: AnchorSpan;
90
- };
91
- /** A context/line matcher hunk: `@@` or `@@ <context>` followed by ' '/'+'/'-' lines. */
92
- export interface FragmentHunk {
93
- readonly kind: "fragment";
94
- /** Grammar guarantees this is `start` or `context`; `anchors` never appears here. */
95
- readonly address: HunkAddress;
96
- readonly headerLine: PatchLineNumber;
97
- /** Body lines, in submission order; at least one is required. */
98
- readonly lines: readonly FragmentLine[];
99
- /** `*** End of File` line number when the hunk is tail-pinned, absent otherwise. */
100
- readonly endOfFile?: PatchLineNumber;
101
- }
102
- /** One body line of a fragment hunk. */
103
- export interface FragmentLine {
104
- readonly op: "context" | "remove" | "add";
105
- /** Line content without the leading marker (' ', '-', '+'). */
106
- readonly text: string;
107
- readonly line: PatchLineNumber;
108
- }
109
- /** An identity hunk: `@@<a>` / `@@<a>-<b>` followed by '+' lines only (empty body = delete). */
110
- export interface IdentityHunk {
111
- readonly kind: "identity";
112
- readonly span: AnchorSpan;
113
- readonly headerLine: PatchLineNumber;
114
- /** '+' lines without the marker; empty means the span is deleted. */
115
- readonly addedLines: readonly string[];
116
- }
117
- /** A copy/cut hunk: the content comes from another file's served span; no body lines allowed. */
118
- export interface ReferenceHunk {
119
- readonly kind: "reference";
120
- /**
121
- * The hunk's own addressing (`@@`, `@@ <context>`, `@@<a>` or `@@<a>-<b>`),
122
- * which determines the destination position (see docs/apply-patch-v4-internals.md §4).
123
- */
124
- readonly address: HunkAddress;
125
- readonly source: ReferenceSource;
126
- readonly headerLine: PatchLineNumber;
127
- }
128
- /** `*** Copy From:` / `*** Cut From:` source span. */
129
- export interface ReferenceSource {
130
- readonly mode: "copy" | "cut";
131
- readonly path: PatchPath;
132
- readonly span: AnchorSpan;
133
- readonly line: PatchLineNumber;
134
- }
135
- /** Plan IR (planner output / transaction input). */
136
- /**
137
- * An inclusive 1-based line range in a file's pre-call baseline.
138
- *
139
- * A zero-width insertion uses the engine's inverted convention:
140
- * `startLine = point + 1` and `endLine = point` (insert after line `point`;
141
- * point 0 inserts at the start of the file).
142
- */
143
- export interface LineRange {
144
- readonly startLine: number;
145
- readonly endLine: number;
146
- }
147
- /** The file-lifecycle action planned for one target. */
148
- export type LifecyclePlan = {
149
- readonly kind: "keep";
150
- } | {
151
- readonly kind: "add";
152
- } | {
153
- readonly kind: "delete";
154
- } | {
155
- readonly kind: "move";
156
- readonly to: PatchPath;
157
- readonly toAbsolutePath: string;
158
- };
159
- /** One file's state at call time — the single baseline every mutation resolves against. */
160
- export interface FileBaseline {
161
- /** The path as written in the patch. */
162
- readonly path: PatchPath;
163
- /** The resolved absolute path the engine reads/writes. */
164
- readonly absolutePath: string;
165
- /** LF-normalized text; `""` for an Add File target. */
166
- readonly text: string;
167
- /** 4-char anchors parallel to the file's lines; empty for an Add File target. */
168
- readonly hashes: readonly string[];
169
- /** Byte-order mark the file carried ("" when none). */
170
- readonly bom: string;
171
- /** The file's original line ending. */
172
- readonly ending: LineEnding;
173
- /** False for `*** Add File:` targets, true for every other existing target. */
174
- readonly exists: boolean;
175
- }
176
- /** One resolved content mutation against `FileBaseline.text`, in baseline coordinates. */
177
- export interface PlannedMutation {
178
- readonly kind: "replace" | "insert" | "delete";
179
- readonly range: LineRange;
180
- /** Replacement lines (LF-joined at commit); empty for `delete` and for an empty insertion. */
181
- readonly lines: readonly string[];
182
- /** The patch line that produced this mutation (diagnostics and ordering evidence). */
183
- readonly patchLine: PatchLineNumber;
184
- }
185
- /** One Copy/Cut source span materialized from a baseline. */
186
- export interface PlannedReferenceUse {
187
- readonly mode: "copy" | "cut";
188
- readonly path: PatchPath;
189
- readonly absolutePath: string;
190
- readonly range: LineRange;
191
- /** The source bytes, line-split and LF-normalized. */
192
- readonly lines: readonly string[];
193
- readonly patchLine: PatchLineNumber;
194
- }
195
- /** One file in the plan, with every mutation expressed against its own pre-call baseline. */
196
- export interface PlannedFile {
197
- readonly path: PatchPath;
198
- readonly absolutePath: string;
199
- readonly lifecycle: LifecyclePlan;
200
- readonly baseline: FileBaseline;
201
- /** Non-overlapping mutations in baseline coordinates, ordered by `range.startLine`. */
202
- readonly mutations: readonly PlannedMutation[];
203
- /** Copy/Cut sources this target consumes. */
204
- readonly references: readonly PlannedReferenceUse[];
205
- /** True when committing this member changes bytes or the namespace. */
206
- readonly writes: boolean;
207
- }
208
- /** The full plan one apply_patch call commits as one correlated transaction. */
209
- export interface PatchPlan {
210
- /** Written members in commit order: the primary file leads, the rest follow deterministically. */
211
- readonly files: readonly PlannedFile[];
212
- /** Files read only as Copy/Cut sources (never written). */
213
- readonly referenceFiles: readonly FileBaseline[];
214
- readonly stats: PatchStats;
215
- }
216
- /** Aggregate line/file counts the success summary reports. */
217
- export interface PatchStats {
218
- readonly filesChanged: number;
219
- readonly addedLines: number;
220
- readonly removedLines: number;
221
- }
222
- /** Result and error types. */
223
- /**
224
- * The two error codes apply_patch adds to the shared registry.
225
- *
226
- * `E_STALE_ANCHOR` is NOT new: `src/domain-errors.ts` already registers it with
227
- * the served-rows payload this feature reuses. The registry lane must add these
228
- * two codes (payload + producer) before the surface lane registers the tool.
229
- */
230
- export type ApplyPatchNewErrorCode = "E_PATCH_SYNTAX" | "E_UNIQUE_MATCH";
231
- /** Every code a patch problem may carry. */
232
- export type ApplyPatchErrorCode = DomainErrorCode | ApplyPatchNewErrorCode;
233
- /** One candidate row for an ambiguous fragment match, served back to the model. */
234
- export interface PatchCandidate {
235
- /** 1-based line number in the baseline. */
236
- readonly line: number;
237
- readonly hash: Anchor;
238
- readonly text: string;
239
- }
240
- /** One collectable problem in a rejection; every problem carries its patch line and code. */
241
- export interface PatchProblem {
242
- readonly code: ApplyPatchErrorCode;
243
- readonly patchLine: PatchLineNumber;
244
- readonly path?: PatchPath;
245
- readonly message: string;
246
- /** Candidate rows when the failure is an ambiguous fragment match. */
247
- readonly candidates?: readonly PatchCandidate[];
248
- /** 1-based target line used to center the rejection serve window when known. */
249
- readonly line?: number;
250
- }
251
- /** One file's current rows rendered `HASH│content` for reject-and-serve. */
252
- export interface ServedFileBlock {
253
- readonly path: PatchPath;
254
- readonly rows: readonly ServedRow[];
255
- /** Rendered block, one `HASH│content` row per line. */
256
- readonly text: string;
257
- }
258
- /** One file's lifecycle status and line counts in the success summary. */
259
- export interface AppliedFileSummary {
260
- /** A = added, M = modified, R = renamed, D = deleted. */
261
- readonly status: "A" | "M" | "R" | "D";
262
- readonly path: PatchPath;
263
- /** Original path for a rename (`R` only). */
264
- readonly fromPath?: PatchPath;
265
- readonly addedLines: number;
266
- readonly removedLines: number;
267
- }
268
- /** Metrics one committed call reports (mirrors the existing RMetrics intent). */
269
- export interface PatchMetrics {
270
- readonly files: number;
271
- readonly hunks: number;
272
- readonly addedLines: number;
273
- readonly removedLines: number;
274
- readonly durationMs?: number;
275
- }
276
- /** Successful apply_patch outcome. */
277
- export interface ApplyPatchSuccess {
278
- readonly ok: true;
279
- /** File-level summary, e.g. `Updated 2 files:\nA src/new.ts\nM src/a.ts`. */
280
- readonly summary: string;
281
- /** Annotated diff for the UI/details (never the model's primary text). */
282
- readonly diff: string;
283
- readonly files: readonly AppliedFileSummary[];
284
- /** New anchors for every changed line, per file — the second call needs no read. */
285
- readonly served: readonly ServedFileBlock[];
286
- readonly warnings: readonly string[];
287
- readonly metrics: PatchMetrics;
288
- }
289
- /** Rejected apply_patch outcome: one transaction, zero disk writes. */
290
- export interface ApplyPatchFailure {
291
- readonly ok: false;
292
- /** Primary code for the envelope; every problem still carries its own code. */
293
- readonly code: ApplyPatchErrorCode;
294
- readonly message: string;
295
- /** Every independently diagnosable problem, in patch order. */
296
- readonly problems: readonly PatchProblem[];
297
- /** Current rows for every file named by a problem (reject-and-serve). */
298
- readonly served: readonly ServedFileBlock[];
299
- /** A rejection is pre-commit: the disk is unchanged by construction. */
300
- /**
301
- * True when the commit left the disk byte-identical (every written member rolled back). A
302
- * mid-commit failure that could not be rolled back sets this false and reports exactly which
303
- * members were restored, remain, or are uncertain.
304
- */
305
- readonly changedNothing: boolean;
306
- /** The rollback's three-way outcome, when the failure happened after a member was written. */
307
- readonly recovery?: TransactionRecoveryReport;
308
- }
309
- export type ApplyPatchResult = ApplyPatchSuccess | ApplyPatchFailure;
310
- /** The grammar seam's total result: a document or every syntax problem found. */
311
- export type ParsePatchResult = {
312
- readonly ok: true;
313
- readonly document: PatchDocument;
314
- } | {
315
- readonly ok: false;
316
- readonly problems: readonly PatchProblem[];
317
- };
318
- /** The planner seam's total result. */
319
- export type PlanPatchResult = {
320
- readonly ok: true;
321
- readonly plan: PatchPlan;
322
- } | {
323
- readonly ok: false;
324
- readonly problems: readonly PatchProblem[];
325
- /** Current rows for every problem file, so the rejection needs no read to retry. */
326
- readonly served: readonly ServedFileBlock[];
327
- };
328
- /** The model-facing tool envelope returned by the renderer / tool use case. */
329
- export interface ApplyPatchToolResult {
330
- readonly content: ReadonlyArray<{
331
- readonly type: "text";
332
- readonly text: string;
333
- }>;
334
- readonly details: ApplyPatchDetails;
335
- /** True when this envelope renders a rejection (nothing was written). */
336
- readonly isError?: boolean;
337
- }
338
- /** The structured details half of {@link ApplyPatchToolResult}. */
339
- export interface ApplyPatchDetails {
340
- readonly summary: string;
341
- readonly diff: string;
342
- readonly files: readonly AppliedFileSummary[];
343
- readonly servedByPath: readonly ServedFileBlock[];
344
- readonly warnings: readonly string[];
345
- readonly metrics: PatchMetrics;
346
- }
347
- /** Execution facts every apply_patch seam shares. */
348
- export interface ApplyPatchContext {
349
- /** Absolute directory relative request paths resolve against (the live session directory). */
350
- readonly cwd: string;
351
- /** Session identity that keys served anchors and leases; never empty. */
352
- readonly sessionKey: string;
353
- /** Caller cancellation forwarded into every async file operation. */
354
- readonly signal?: AbortSignal;
355
- }
356
- /** Options for the planner/commit seams over the existing hash store. */
357
- export interface ApplyPatchEngineOptions extends ApplyPatchContext {
358
- /** Hash store override for tests; the default opens the configured store. */
359
- readonly store?: HashStore;
360
- /** POSIX access-mode bitmask; commit defaults to read+write, plan to read-only. */
361
- readonly accessMode?: number;
362
- }
@@ -1,44 +0,0 @@
1
- /**
2
- * Filesystem primitives for apply_patch's file lifecycle: classify, create directories, delete a
3
- * regular file and rename one. Every entry point resolves through {@link resolveTarget}, the same
4
- * symlink-resolving boundary every read/write uses, so a lifecycle action can never escape it.
5
- *
6
- * These are primitives, not a second write engine: file CONTENTS still go through writeAtomic;
7
- * this module only owns namespace operations that writeAtomic deliberately does not express.
8
- *
9
- * @module dsh-hashline-edit/fs-lifecycle
10
- */
11
- /** The physical kind of a path as the file layer sees it (symlinks resolved first). */
12
- export type PathKind = "file" | "directory" | "other" | "absent";
13
- /** Classify one path through the file layer's symlink-resolving boundary. */
14
- export declare function pathKind(path: string): Promise<PathKind>;
15
- /**
16
- * True when `path` resolves inside `root` once every existing symlink/junction component is
17
- * followed. A missing tail is checked against its nearest existing ancestor: an Add File under a
18
- * junction ancestor therefore fails before mkdir can create anything outside the workspace.
19
- */
20
- export declare function isPathWithinWorkspace(root: string, path: string): Promise<boolean>;
21
- /** Throw the E_PATCH_SYNTAX boundary refusal for one escaping lifecycle path. */
22
- export declare function assertPathWithinWorkspace(root: string, path: string): Promise<void>;
23
- /** Create one directory (and missing parents), through the symlink-resolving boundary. */
24
- export declare function mkdirp(path: string, workspaceRoot?: string): Promise<void>;
25
- /**
26
- * Delete one regular file. Deliberately NOT recursive: a lifecycle delete targets a file, and a
27
- * directory at the same path is a caller bug that must surface, never be removed wholesale.
28
- */
29
- export declare function removeFile(path: string, signal?: AbortSignal): Promise<void>;
30
- /**
31
- * Rename one regular file, creating the destination parent first. The destination must not exist:
32
- * a move never clobbers another file (spec §6: target-exists is a rejection, not an overwrite).
33
- */
34
- export declare function renameFile(from: string, to: string, signal?: AbortSignal, workspaceRoot?: string): Promise<void>;
35
- /**
36
- * The directories on the way to `path` that do not exist yet, OUTERMOST FIRST. Captured before a
37
- * lifecycle add writes, so an undo removes exactly the directories the add created and no others.
38
- */
39
- export declare function missingAncestorDirs(path: string): Promise<string[]>;
40
- /**
41
- * Best-effort removal of directories a lifecycle add created, deepest first. Returns the removed
42
- * paths. A directory that is no longer empty (an outside writer put something there) is kept.
43
- */
44
- export declare function pruneEmptyDirs(dirs: readonly string[]): Promise<string[]>;
@@ -1,63 +0,0 @@
1
- /** Retained line budget, matching pi's `DEFAULT_MAX_LINES`. */
2
- export declare const DEFAULT_MAX_LINES = 2000;
3
- /** Retained byte budget, matching pi's `DEFAULT_MAX_BYTES` (50KB). */
4
- export declare const DEFAULT_MAX_BYTES: number;
5
- /** The truncation report the core's read page renders. */
6
- export interface TruncationResult {
7
- /** The truncated content. */
8
- content: string;
9
- /** Whether truncation occurred. */
10
- truncated: boolean;
11
- /** Which limit was hit: `"lines"`, `"bytes"`, or `null` when nothing was cut. */
12
- truncatedBy: "lines" | "bytes" | null;
13
- /** Total number of lines in the original content. */
14
- totalLines: number;
15
- /** Total number of bytes in the original content. */
16
- totalBytes: number;
17
- /** Number of complete lines in the truncated output. */
18
- outputLines: number;
19
- /** Number of bytes in the truncated output. */
20
- outputBytes: number;
21
- /** Whether the last line was partially truncated (tail truncation only). */
22
- lastLinePartial: boolean;
23
- /** Whether the first line exceeded the byte limit (head truncation only). */
24
- firstLineExceedsLimit: boolean;
25
- /** The line limit that was applied. */
26
- maxLines: number;
27
- /** The byte limit that was applied. */
28
- maxBytes: number;
29
- }
30
- /** The two independent limits a truncation call applies. */
31
- export interface TruncationOptions {
32
- /** Maximum number of lines; defaults to {@link DEFAULT_MAX_LINES}. */
33
- maxLines?: number;
34
- /** Maximum number of bytes; defaults to {@link DEFAULT_MAX_BYTES}. */
35
- maxBytes?: number;
36
- }
37
- /**
38
- * Format bytes as a human-readable size (`512B`, `1.5KB`, `2.0MB`).
39
- * @param bytes - the byte count to render.
40
- * @returns the pi-compatible size label.
41
- */
42
- export declare function formatSize(bytes: number): string;
43
- /**
44
- * Truncate content from the head (keep the first N lines / bytes).
45
- *
46
- * WHY: the read page's oversize and truncation warnings must agree with the pi
47
- * implementation the rest of the contract was written against, so this is a
48
- * faithful port including its two edge rules: complete lines only, and an
49
- * over-long first line yields empty content with `firstLineExceedsLimit`.
50
- * @param content - the text to truncate.
51
- * @param options - the line and byte limits.
52
- * @returns the truncation report.
53
- */
54
- export declare function truncateHead(content: string, options?: TruncationOptions): TruncationResult;
55
- /**
56
- * Serialize file mutation operations that target the same file; different files still run
57
- * in parallel. A faithful port of pi's queue so the core's cut transaction keeps its
58
- * lock ordering guarantees under the dsh host.
59
- * @param filePath - the file the mutation targets.
60
- * @param run - the critical section to run once the path is free.
61
- * @returns the critical section's result.
62
- */
63
- export declare function withFileMutationQueue<T>(filePath: string, run: () => Promise<T>): Promise<T>;
@@ -1,34 +0,0 @@
1
- /** The internal payload vocabulary the mutation engine consumes; no wire schema lives here. */
2
- type SpanRef = {
3
- anchor_from: string;
4
- anchor_to: string;
5
- file?: string;
6
- mode: "copy" | "cut";
7
- };
8
- type EditMode = "general" | "literal";
9
- type Placement = "in-place" | "before" | "after";
10
- export type DesiredContent = {
11
- kind: "literal";
12
- text: string;
13
- } | {
14
- kind: "reference";
15
- span: SpanRef;
16
- mode: "copy" | "cut";
17
- } | {
18
- kind: "empty";
19
- };
20
- export type NormalizedEditItem = {
21
- target: {
22
- anchor_from: string;
23
- anchor_to: string;
24
- };
25
- at: Placement;
26
- payload: DesiredContent;
27
- file?: string;
28
- };
29
- export type NormalizedEditRequest = {
30
- file: string;
31
- edits: NormalizedEditItem[];
32
- mode?: EditMode;
33
- };
34
- export {};
@@ -1,10 +0,0 @@
1
- - apply_patch: one call = one transaction. Collect every related file change (code, tests, docs, config) into one patch; split only when an earlier RESULT must decide a later edit.
2
- - apply_patch: two addressing modes. Fragment mode (`@@` or `@@ <context>`) locates by exact content and needs no served state. Identity mode (`@@<a>` / `@@<a>-<b>`) targets rows this session served and never writes the old text back.
3
- - apply_patch: the character after `@@` selects the mode. `@@` followed immediately by exactly four anchor characters is identity mode; `@@` followed by a space is Codex context mode (`@@ <line>`); a bare `@@` starts the search at the file start. Any other token is a syntax rejection.
4
- - apply_patch: fragment mode must match exactly once. Zero or several hits reject and serve the candidate rows; add surrounding context to disambiguate, never guess.
5
- - apply_patch: identity mode accepts only `+` lines; an empty body deletes the span. A `-` or context line in an identity hunk, or body lines in a Copy/Cut hunk, rejects at admission with its patch line number.
6
- - apply_patch: every hunk resolves against the file as it was before the call; later windows begin after the previous hunk's end. Overlapping target ranges in one file reject the whole batch.
7
- - apply_patch: lifecycle joins the same transaction and undo. `*** Add File:` content lines all start with `+`; `*** Delete File:` removes the file; `*** Move to:` must immediately follow `*** Update File:` and renames before its hunks apply; an existing move target rejects.
8
- - apply_patch: a rejection writes nothing. Read the `- patch line N ([E_*], path): ...` lines, then use the immediately following `HASH│content` block — those are the current rows and anchors; retry directly without issuing a separate `read`.
9
- - apply_patch: a success starts with `Updated N files:` and ends with the changed lines' fresh anchors per file; use those anchors directly in the next identity hunk. `[W_*]` lines are informational.
10
- - apply_patch: paths are workspace-relative or workspace-absolute; `..`, `.git`, and symlink targets reject. Whole-file replacement stays with `write`.
@@ -1 +0,0 @@
1
- Apply one Codex-format patch to one or more files in a single transaction: `{ input: string }`. `input` is the complete patch text: `*** Begin Patch` ... `*** End Patch`, with `*** Add File:`, `*** Delete File:`, `*** Update File:` (plus optional `*** Move to:`) and hunks addressed either by content (`@@` or `@@ <context>` with ` `/`-`/`+` lines) or by served anchors (`@@<a>` / `@@<a>-<b>` with `+` lines only). `*** Copy From:` / `*** Cut From:` copy or move a served span from another file. Every target validates before anything is written; a rejection changes nothing and returns the current rows with anchors. On success the result lists the changed files and the new anchors for the changed lines, so a follow-up call needs no `read`. `write` stays for whole-file replacement.