dsh-hashline-edit 0.2.2 → 0.3.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 (118) hide show
  1. package/README.md +57 -45
  2. package/cordis.patch.yml +9 -3
  3. package/lib/client.js +231 -0
  4. package/lib/index.js +3298 -3957
  5. package/lib/types/dsh/contracts.d.ts +12 -3
  6. package/lib/types/dsh/fs.d.ts +3 -0
  7. package/lib/types/dsh/guidance.d.ts +12 -6
  8. package/lib/types/dsh/hide.d.ts +79 -0
  9. package/lib/types/dsh/host-compat.d.ts +7 -78
  10. package/lib/types/dsh/index.d.ts +53 -10
  11. package/lib/types/dsh/metrics/events.d.ts +1 -1
  12. package/lib/types/dsh/metrics/observer.d.ts +1 -1
  13. package/lib/types/dsh/sandbox.d.ts +2 -2
  14. package/lib/types/dsh/shell-hook.d.ts +1 -1
  15. package/lib/types/dsh/tools/apply-patch.d.ts +38 -0
  16. package/lib/types/dsh/tools/read.d.ts +3 -3
  17. package/lib/types/src/apply-patch/commit.d.ts +49 -0
  18. package/lib/types/src/apply-patch/grammar.d.ts +29 -0
  19. package/lib/types/src/apply-patch/lifecycle.d.ts +32 -0
  20. package/lib/types/src/apply-patch/plan.d.ts +50 -0
  21. package/lib/types/src/apply-patch/render.d.ts +51 -0
  22. package/lib/types/src/apply-patch/resolve.d.ts +129 -0
  23. package/lib/types/src/apply-patch/tool.d.ts +54 -0
  24. package/lib/types/src/apply-patch/types.d.ts +362 -0
  25. package/lib/types/src/domain-errors.d.ts +16 -2
  26. package/lib/types/src/edit-undo.d.ts +11 -2
  27. package/lib/types/src/file-content/index.d.ts +1 -1
  28. package/lib/types/src/file-content/preview.d.ts +1 -1
  29. package/lib/types/src/fs-lifecycle.d.ts +44 -0
  30. package/lib/types/src/hashline/alphabet.d.ts +4 -3
  31. package/lib/types/src/hashline/hash-identity.d.ts +12 -7
  32. package/lib/types/src/host-utils.d.ts +63 -0
  33. package/lib/types/src/mutation-engine/edit-request.d.ts +34 -0
  34. package/lib/types/src/mutation-engine/pipeline.d.ts +8 -1
  35. package/lib/types/src/mutation-engine/types.d.ts +40 -50
  36. package/lib/types/src/served-session/serve-render.d.ts +6 -0
  37. package/lib/types/src/undo-store.d.ts +17 -1
  38. package/package.json +37 -21
  39. package/prompts/apply-patch-guidelines.md +4 -0
  40. package/prompts/apply-patch.md +1 -0
  41. package/prompts/read-guidelines.md +6 -6
  42. package/prompts/read.md +1 -1
  43. package/prompts/undo-last-edit-guidelines.md +2 -2
  44. package/prompts/undo-last-edit-snippet.md +1 -1
  45. package/prompts/undo-last-edit.md +1 -1
  46. package/prompts/zh/apply-patch-guidelines.md +4 -0
  47. package/prompts/zh/apply-patch.md +1 -0
  48. package/prompts/zh/read-guidelines.md +6 -0
  49. package/prompts/zh/read-snippet.md +1 -0
  50. package/prompts/zh/read.md +1 -0
  51. package/prompts/zh/undo-last-edit-guidelines.md +2 -0
  52. package/prompts/zh/undo-last-edit-snippet.md +1 -0
  53. package/prompts/zh/undo-last-edit.md +1 -0
  54. package/src/apply-patch/commit.ts +190 -0
  55. package/src/apply-patch/grammar.ts +620 -0
  56. package/src/apply-patch/index.ts +17 -0
  57. package/src/apply-patch/lifecycle.ts +195 -0
  58. package/src/apply-patch/plan.ts +800 -0
  59. package/src/apply-patch/render.ts +137 -0
  60. package/src/apply-patch/resolve.ts +470 -0
  61. package/src/apply-patch/tool.ts +257 -0
  62. package/src/apply-patch/types.ts +387 -0
  63. package/src/cut-repair.ts +77 -11
  64. package/src/domain-errors.ts +35 -3
  65. package/src/edit-undo.ts +379 -25
  66. package/src/file-content/index.ts +1 -1
  67. package/src/file-content/preview.ts +1 -1
  68. package/src/file-content/served-header.ts +1 -1
  69. package/src/fs-lifecycle.ts +201 -0
  70. package/src/hash-store.ts +18 -1
  71. package/src/hashline/alphabet.ts +7 -7
  72. package/src/hashline/hash-identity.ts +12 -7
  73. package/src/host-utils.ts +224 -0
  74. package/src/mutation-engine/edit-request.ts +39 -0
  75. package/src/mutation-engine/pipeline.ts +198 -27
  76. package/src/mutation-engine/types.ts +39 -57
  77. package/src/mutation-queue.ts +1 -1
  78. package/src/prompts.ts +3 -30
  79. package/src/served-session/serve-render.ts +2 -2
  80. package/src/undo-store.ts +74 -5
  81. package/lib/types/dsh/tools/edit.d.ts +0 -10
  82. package/lib/types/src/edit-tool.d.ts +0 -41
  83. package/lib/types/src/mutation-engine/engine.d.ts +0 -31
  84. package/lib/types/src/payload-contract.d.ts +0 -135
  85. package/prompts/edit-guidelines.md +0 -10
  86. package/prompts/edit-snippet.md +0 -1
  87. package/prompts/edit.md +0 -1
  88. package/prompts/read-snippet.md +0 -1
  89. package/src/bash-classifier.ts +0 -1626
  90. package/src/bash-conversion/decide.ts +0 -812
  91. package/src/bash-display-transform.ts +0 -50
  92. package/src/bash-multifile-config.ts +0 -239
  93. package/src/bash-view-config.ts +0 -158
  94. package/src/edit-normalize.ts +0 -8
  95. package/src/edit-render.ts +0 -161
  96. package/src/edit-tool.ts +0 -118
  97. package/src/edit.ts +0 -136
  98. package/src/integrations/pi-lens/command.ts +0 -712
  99. package/src/integrations/pi-lens/config.ts +0 -148
  100. package/src/integrations/pi-lens/io-bridge-adapter.ts +0 -234
  101. package/src/integrations/pi-lens/io-bridge.ts +0 -112
  102. package/src/integrations/pi-lens/settings-overlay.ts +0 -272
  103. package/src/lifecycle-hooks/index.ts +0 -1992
  104. package/src/lifecycle-hooks/types.ts +0 -64
  105. package/src/mutated-files.ts +0 -75
  106. package/src/mutation-engine/engine.ts +0 -239
  107. package/src/mutation-engine/index.ts +0 -17
  108. package/src/payload-contract.ts +0 -685
  109. package/src/preview-controller.ts +0 -84
  110. package/src/read.ts +0 -865
  111. package/src/search-hook.ts +0 -41
  112. package/src/store-config.ts +0 -73
  113. package/src/store-janitor-warning.ts +0 -169
  114. package/src/store-janitor.ts +0 -539
  115. package/src/store-kernel/settings.ts +0 -233
  116. package/src/store.ts +0 -154
  117. package/src/tui-presenter.ts +0 -134
  118. package/src/write-hook.ts +0 -130
@@ -0,0 +1,195 @@
1
+ import { splitLines } from "../utils.js";
2
+ import { lineHashes } from "../hashline/hash-identity.js";
3
+ import { snapshotIOFor } from "../snapshot-store";
4
+ import { loadHashStore, type HashStore } from "../hash-store.js";
5
+ import type { ProcessedEditFile, MemberLifecycle } from "../mutation-engine/types.js";
6
+ import type { FileBaseline, PatchPath, PlannedFile, PlannedMutation } from "./types.js";
7
+ import { applyPlannedMutations, mutationDelta } from "./plan.js";
8
+
9
+ /**
10
+ * apply_patch lifecycle materialization — the plan-to-engine adapter.
11
+ *
12
+ * The planner resolves every mutation against a pre-call baseline; this module turns that plan
13
+ * into the mutation engine's `ProcessedEditFile` member shape (plus the engine-local lifecycle
14
+ * action). It never writes: the correlated transaction in `mutation-engine/pipeline.ts` owns the
15
+ * one commit path. Pure text application (splice at baseline coordinates) is the only work here,
16
+ * and the resulting anchors are always derived under the member's COMMITTED path.
17
+ *
18
+ * @module dsh-hashline-edit/apply-patch/lifecycle
19
+ */
20
+
21
+ /** One materialized member: the plan facts plus the engine member the commit consumes. */
22
+ export interface MaterializedMember {
23
+ readonly planned: PlannedFile;
24
+ readonly member: ProcessedEditFile;
25
+ readonly status: "A" | "M" | "R" | "D";
26
+ /** The committed display path (destination for a move; the pre path otherwise). */
27
+ readonly committedPath: PatchPath;
28
+ /** The pre-transaction display path (move only). */
29
+ readonly fromPath?: PatchPath;
30
+ }
31
+
32
+ /** The union of baseline anchors whose lines this file's mutations retire. */
33
+ function removedHashesOf(
34
+ baseline: FileBaseline,
35
+ mutations: readonly PlannedMutation[],
36
+ ): Set<string> {
37
+ const removed = new Set<string>();
38
+ for (const mutation of mutations) {
39
+ if (mutation.range.startLine > mutation.range.endLine) continue;
40
+ for (let line = mutation.range.startLine; line <= mutation.range.endLine; line++) {
41
+ const hash = baseline.hashes[line - 1];
42
+ if (hash !== undefined) removed.add(hash);
43
+ }
44
+ }
45
+ return removed;
46
+ }
47
+
48
+ /** Sum the semantic line counts one materialized member reports (context lines excluded). */
49
+ function countMutationLines(
50
+ baselineLines: readonly string[],
51
+ mutations: readonly PlannedMutation[],
52
+ ): {
53
+ added: number;
54
+ removed: number;
55
+ } {
56
+ let added = 0;
57
+ let removed = 0;
58
+ for (const mutation of mutations) {
59
+ const delta = mutationDelta(baselineLines, mutation);
60
+ added += delta.added;
61
+ removed += delta.removed;
62
+ }
63
+ return { added, removed };
64
+ }
65
+
66
+ /** The engine lifecycle action for one planned file. */
67
+ function lifecycleOf(planned: PlannedFile): MemberLifecycle {
68
+ switch (planned.lifecycle.kind) {
69
+ case "keep":
70
+ return { kind: "keep" };
71
+ case "add":
72
+ return { kind: "add", createdDirs: [] };
73
+ case "delete":
74
+ return { kind: "delete" };
75
+ case "move":
76
+ return {
77
+ kind: "move",
78
+ fromAbsolutePath: planned.absolutePath,
79
+ toAbsolutePath: planned.lifecycle.toAbsolutePath,
80
+ createdDirs: [],
81
+ };
82
+ }
83
+ }
84
+
85
+ /** The absolute path a member commits to (a move commits at its destination). */
86
+ function committedAbsolutePath(planned: PlannedFile): string {
87
+ return planned.lifecycle.kind === "move"
88
+ ? planned.lifecycle.toAbsolutePath
89
+ : planned.absolutePath;
90
+ }
91
+
92
+ /** The display path a member commits to. */
93
+ function committedDisplayPath(planned: PlannedFile): PatchPath {
94
+ return planned.lifecycle.kind === "move" ? planned.lifecycle.to : planned.path;
95
+ }
96
+
97
+ /**
98
+ * Derive the member's result anchors under its COMMITTED path.
99
+ *
100
+ * Anchors are file-scoped (the path seeds the derivation), so a move must re-derive at the
101
+ * destination instead of carrying the source's anchors across. An in-place edit keeps the
102
+ * baseline's surviving anchors through the engine's prior-identity seam.
103
+ */
104
+ async function resultHashesFor(
105
+ planned: PlannedFile,
106
+ result: string,
107
+ store?: HashStore,
108
+ ): Promise<string[]> {
109
+ if (planned.lifecycle.kind === "delete") return [];
110
+ const resolvedStore = store ?? (await loadHashStore());
111
+ const path = committedAbsolutePath(planned);
112
+ const previous =
113
+ planned.lifecycle.kind === "keep"
114
+ ? {
115
+ content: planned.baseline.text,
116
+ hashes: [...planned.baseline.hashes],
117
+ removedHashes: removedHashesOf(planned.baseline, planned.mutations),
118
+ }
119
+ : undefined;
120
+ return lineHashes(result, path, previous, snapshotIOFor(resolvedStore), false);
121
+ }
122
+
123
+ /** The status letter one member reports in the success summary. */
124
+ function statusOf(planned: PlannedFile): "A" | "M" | "R" | "D" {
125
+ switch (planned.lifecycle.kind) {
126
+ case "add":
127
+ return "A";
128
+ case "delete":
129
+ return "D";
130
+ case "move":
131
+ return "R";
132
+ case "keep":
133
+ return "M";
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Materialize one planned file into the engine's member shape.
139
+ *
140
+ * The result text is produced by applying the plan's baseline-coordinate mutations; the anchors
141
+ * are then derived under the committed path. No file is read or written here — the plan already
142
+ * carries every baseline byte the commit needs.
143
+ */
144
+ export async function materializeMember(
145
+ planned: PlannedFile,
146
+ store?: HashStore,
147
+ ): Promise<MaterializedMember> {
148
+ const lifecycle = planned.lifecycle;
149
+ const isDelete = lifecycle.kind === "delete";
150
+ const isEmptyBaseline = planned.baseline.text === "" && planned.baseline.hashes.length === 0;
151
+ const baselineLines = isEmptyBaseline ? [] : splitLines(planned.baseline.text);
152
+ const resultLines = isDelete ? [] : applyPlannedMutations(baselineLines, planned.mutations);
153
+ const result = isDelete
154
+ ? ""
155
+ : isEmptyBaseline
156
+ ? resultLines.length === 0
157
+ ? ""
158
+ : resultLines.join("\n") + "\n"
159
+ : resultLines.join("\n") + (planned.baseline.text.endsWith("\n") ? "\n" : "");
160
+ const resultHashes = isDelete ? [] : await resultHashesFor(planned, result, store);
161
+ const { added, removed } = isDelete
162
+ ? { added: 0, removed: baselineLines.length }
163
+ : countMutationLines(baselineLines, planned.mutations);
164
+ const member: ProcessedEditFile = {
165
+ path: planned.path,
166
+ absolutePath: committedAbsolutePath(planned),
167
+ originalNormalized: lifecycle.kind === "add" ? "" : planned.baseline.text,
168
+ result,
169
+ bom: planned.baseline.bom,
170
+ originalEnding: planned.baseline.ending,
171
+ warnings: [],
172
+ originalHashes: [...planned.baseline.hashes],
173
+ resultHashes,
174
+ resultLineIds: [],
175
+ removedHashes: removedHashesOf(planned.baseline, planned.mutations),
176
+ appliedCount: 1,
177
+ noopCount: 0,
178
+ totalAddedLines: added,
179
+ totalRemovedLines: removed,
180
+ driftNotice: undefined,
181
+ range: { startLine: 1, endLine: 1, startHash: "", endHash: "", delta: 0 },
182
+ editedIntervals: [],
183
+ literalDeclarations: 0,
184
+ foreignCuts: [],
185
+ lifecycle: lifecycleOf(planned),
186
+ };
187
+ const fromPath = lifecycle.kind === "move" ? planned.path : undefined;
188
+ return {
189
+ planned,
190
+ member,
191
+ status: statusOf(planned),
192
+ committedPath: committedDisplayPath(planned),
193
+ ...(fromPath !== undefined ? { fromPath } : {}),
194
+ };
195
+ }