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,190 @@
1
+ /**
2
+ * apply_patch v4 — commit seam.
3
+ *
4
+ * Commits a `PatchPlan` as ONE correlated transaction through the existing hashline machinery:
5
+ *
6
+ * - pre-mirror every written member (durable pre-images),
7
+ * - one undo row per member carrying the shared transaction id,
8
+ * - the durable intent record,
9
+ * - deterministic member order (primary first), lifecycle actions included,
10
+ * - best-effort rollback of every member on failure,
11
+ * - the per-file store commit and the new-anchor served rows.
12
+ *
13
+ * This module is deliberately thin: it maps `PlannedFile` onto the engine's
14
+ * `ProcessedEditFile`/`commitTransaction` skeleton and never re-implements hashing, leasing,
15
+ * snapshots or undo storage.
16
+ *
17
+ * @module dsh-hashline-edit/apply-patch/commit
18
+ */
19
+ import { SERVED_ROWS_CAP } from "../constants.js";
20
+ import { DomainError } from "../domain-errors.js";
21
+ import { genDiff } from "../edit-diff.js";
22
+ import type { HashStore } from "../hash-store.js";
23
+ import { commitTransaction } from "../mutation-engine/pipeline.js";
24
+ import type { ProcessedEditFile, TransactionRecoveryReport } from "../mutation-engine/types.js";
25
+ import { fmtServedRows, paginationHint } from "../served-session/serve-render.js";
26
+ import { visLines } from "../utils.js";
27
+ import { materializeMember, type MaterializedMember } from "./lifecycle.js";
28
+ import type { ApplyPatchFailure, PatchProblem, PatchPlan, ServedFileBlock } from "./types.js";
29
+
30
+ /** Options for {@link commitPlan}. */
31
+ export interface CommitPlanOptions {
32
+ readonly cwd: string;
33
+ readonly sessionKey: string;
34
+ readonly signal?: AbortSignal;
35
+ readonly store?: HashStore;
36
+ /** POSIX access-mode bitmask; defaults to read+write. */
37
+ readonly accessMode?: number;
38
+ /** TEST-ONLY: fires before the first rename, while the pre-images/undo rows are durable. */
39
+ readonly onBeforeFirstWrite?: () => void | Promise<void>;
40
+ /** TEST-ONLY: fires between two member renames, after the earlier one is durable. */
41
+ readonly onBetweenWrites?: (committedAbsolutePath: string) => void | Promise<void>;
42
+ /** TEST-ONLY: fires after a move rename and before the destination rewrite (mid-member failure). */
43
+ readonly onAfterMoveRename?: (toAbsolutePath: string) => void | Promise<void>;
44
+ }
45
+
46
+ /** One committed file's lifecycle status and line accounting. */
47
+ export interface CommittedFile {
48
+ readonly path: string;
49
+ readonly status: "A" | "M" | "R" | "D";
50
+ /** Original path for a rename (`R` only). */
51
+ readonly fromPath?: string;
52
+ readonly addedLines: number;
53
+ readonly removedLines: number;
54
+ /** New anchors for the changed lines; absent when the member wrote no content. */
55
+ readonly served?: ServedFileBlock;
56
+ }
57
+
58
+ /** Commit outcome: the per-file facts on success, the whole failure on rejection. */
59
+ export type CommitPlanResult =
60
+ | {
61
+ readonly ok: true;
62
+ readonly files: readonly CommittedFile[];
63
+ readonly diff: string;
64
+ readonly warnings: readonly string[];
65
+ }
66
+ | { readonly ok: false; readonly failure: ApplyPatchFailure };
67
+
68
+ /** Build the served block one committed member owes the model: only its actually changed lines. */
69
+ function servedBlockFor(member: ProcessedEditFile, path: string): ServedFileBlock | undefined {
70
+ if (member.resultHashes.length === 0) return undefined;
71
+ // WHY: a success result returns anchors for the changed lines only (§7); the whole-file projection
72
+ // WHY: made a one-line edit dump every unchanged line back at the model.
73
+ const diff = genDiff(
74
+ member.originalNormalized,
75
+ member.result,
76
+ 0,
77
+ member.resultHashes,
78
+ member.originalHashes,
79
+ );
80
+ let rows = diff.servedRows;
81
+ if (rows.length === 0) return undefined;
82
+ let text: string;
83
+ if (rows.length > SERVED_ROWS_CAP) {
84
+ const next = rows[SERVED_ROWS_CAP]!;
85
+ text =
86
+ fmtServedRows(rows.slice(0, SERVED_ROWS_CAP), visLines(member.result)) +
87
+ "\n" +
88
+ paginationHint(next.position + 1, rows.length - SERVED_ROWS_CAP);
89
+ rows = rows.slice(0, SERVED_ROWS_CAP);
90
+ } else {
91
+ text = fmtServedRows(rows, visLines(member.result));
92
+ }
93
+ return { path, rows, text };
94
+ }
95
+
96
+ /** Map a commit-stage thrown value onto the apply-patch failure shape. */
97
+ function failureOf(
98
+ error: unknown,
99
+ plan: PatchPlan,
100
+ recovery: TransactionRecoveryReport | undefined,
101
+ ): ApplyPatchFailure {
102
+ const code = error instanceof DomainError ? error.code : "E_UNKNOWN";
103
+ const baseMessage = error instanceof Error ? error.message : String(error);
104
+ const patchLine = plan.files[0]?.mutations[0]?.patchLine ?? 1;
105
+ const recoveryText =
106
+ recovery === undefined
107
+ ? ""
108
+ : "\nRecovery: restored [" +
109
+ recovery.restored.join(", ") +
110
+ "], remaining [" +
111
+ recovery.remaining.join(", ") +
112
+ "], uncertain [" +
113
+ recovery.uncertain.join(", ") +
114
+ "].";
115
+ const problem: PatchProblem = { code, patchLine, message: baseMessage + recoveryText };
116
+ return {
117
+ ok: false,
118
+ code,
119
+ message: "apply_patch commit failed: " + baseMessage + recoveryText,
120
+ problems: [problem],
121
+ served: [],
122
+ changedNothing: recovery === undefined || recovery.remaining.length === 0,
123
+ ...(recovery !== undefined ? { recovery } : {}),
124
+ };
125
+ }
126
+
127
+ /**
128
+ * Commit one plan atomically (one correlated transaction, one undo record set).
129
+ *
130
+ * The implementation reuses `commitTransaction` — the existing correlated skeleton — and extends
131
+ * its member shape with the plan's lifecycle action; the undo schema gains the matching action.
132
+ *
133
+ * @param plan - the fully resolved plan.
134
+ * @param options - cwd/session/store, cancellation and the test fault seams.
135
+ * @returns the committed facts, or a failure whose `changedNothing` reflects the rollback.
136
+ */
137
+ export async function commitPlan(
138
+ plan: PatchPlan,
139
+ options: CommitPlanOptions,
140
+ ): Promise<CommitPlanResult> {
141
+ const entries: MaterializedMember[] = [];
142
+ for (const planned of plan.files) {
143
+ if (planned.writes) entries.push(await materializeMember(planned, options.store));
144
+ }
145
+ if (entries.length === 0) return { ok: true, files: [], diff: "", warnings: [] };
146
+ const members = entries.map((entry) => entry.member);
147
+ try {
148
+ const outcome = await commitTransaction(
149
+ members,
150
+ members,
151
+ {
152
+ sessionKey: options.sessionKey,
153
+ workspaceRoot: options.cwd,
154
+ ...(options.signal !== undefined ? { signal: options.signal } : {}),
155
+ ...(options.store !== undefined ? { store: options.store } : {}),
156
+ ...(options.accessMode !== undefined ? { accessMode: options.accessMode } : {}),
157
+ ...(options.onBeforeFirstWrite !== undefined
158
+ ? { onBeforeFirstCutWrite: options.onBeforeFirstWrite }
159
+ : {}),
160
+ ...(options.onBetweenWrites !== undefined
161
+ ? { onCutBetweenWrites: options.onBetweenWrites }
162
+ : {}),
163
+ ...(options.onAfterMoveRename !== undefined
164
+ ? { onAfterMoveRename: options.onAfterMoveRename }
165
+ : {}),
166
+ },
167
+ options.sessionKey,
168
+ );
169
+ const files: CommittedFile[] = entries.map((entry) => {
170
+ const served = servedBlockFor(entry.member, entry.committedPath);
171
+ return {
172
+ path: entry.committedPath,
173
+ status: entry.status,
174
+ ...(entry.fromPath !== undefined ? { fromPath: entry.fromPath } : {}),
175
+ addedLines: entry.member.totalAddedLines,
176
+ removedLines: entry.member.totalRemovedLines,
177
+ ...(served !== undefined ? { served } : {}),
178
+ };
179
+ });
180
+ return {
181
+ ok: true,
182
+ files,
183
+ diff: outcome.toolResult.details.diff ?? "",
184
+ warnings: outcome.toolResult.details.warnings ?? [],
185
+ };
186
+ } catch (error) {
187
+ const recovery = (error as Error & { recovery?: TransactionRecoveryReport }).recovery;
188
+ return { ok: false, failure: failureOf(error, plan, recovery) };
189
+ }
190
+ }