ahead-pi 0.8.4 → 0.8.5
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.
- package/README.md +5 -1
- package/package.json +1 -1
- package/src/index.ts +32 -4
- package/src/review.ts +22 -7
package/README.md
CHANGED
|
@@ -127,7 +127,11 @@ INDEPENDENT HUMAN REVIEWS AND ACCEPTS
|
|
|
127
127
|
|
|
128
128
|
A draft branch or draft PR may exist earlier. The handoff gate is requesting human review or marking the PR ready, not ordinary draft pushes.
|
|
129
129
|
|
|
130
|
-
`/ahead-review` opens the first editor-neutral review workbench. It fingerprints the current Git changeset, shows the changed paths and diff in Pi, can open a selected path in VS Code when detected or configured with `AHEAD_EDITOR=vscode`, requests snapshot-bound AI findings, and opens the required human disposition or independent-review record. Any engineering change produces a new fingerprint and requires review again. `.ahead/**` evidence is excluded from that fingerprint so recording the review does not invalidate it.
|
|
130
|
+
`/ahead-review` opens the first editor-neutral review workbench. It fingerprints the current Git changeset, shows the changed paths and diff in Pi, can open a selected path in VS Code or Zed when detected or configured with `AHEAD_EDITOR=vscode` or `AHEAD_EDITOR=zed`, requests snapshot-bound AI findings, and opens the required human disposition or independent-review record. Any engineering change produces a new fingerprint and requires review again. `.ahead/**` evidence is excluded from that fingerprint so recording the review does not invalidate it.
|
|
131
|
+
|
|
132
|
+
VS Code is detected from its terminal environment. For a deterministic Zed terminal, add `"AHEAD_EDITOR": "zed"` under Zed's `terminal.env` settings; Zed's CLI must be installed. `AHEAD_EDITOR=none` disables external opening.
|
|
133
|
+
|
|
134
|
+
Human-owned plans and other artifacts open in that detected editor as a temporary Markdown draft. Save your work, then close only that temporary tab; AHEAD copies the draft into `.ahead/runs/` after the tab closes and the form passes validation. The host editor stays open, and saving alone does not record the artifact.
|
|
131
135
|
|
|
132
136
|
## Human commands
|
|
133
137
|
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
3
5
|
import { fileURLToPath } from "node:url";
|
|
4
6
|
import type {
|
|
5
7
|
ExtensionAPI,
|
|
@@ -32,6 +34,7 @@ import {
|
|
|
32
34
|
import { showReferenceViewer } from "./reference-viewer.js";
|
|
33
35
|
import {
|
|
34
36
|
collectReviewSnapshot,
|
|
37
|
+
detectEditor,
|
|
35
38
|
extractFindingIds,
|
|
36
39
|
extractReviewFingerprint,
|
|
37
40
|
openInConfiguredEditor,
|
|
@@ -1367,7 +1370,7 @@ async function openReviewWorkbench(pi: ExtensionAPI, ctx: ExtensionCommandContex
|
|
|
1367
1370
|
const path = await ctx.ui.select("Open changed file", snapshot.changed_files);
|
|
1368
1371
|
if (path && !openInConfiguredEditor(store.projectRoot, { path })) {
|
|
1369
1372
|
ctx.ui.notify(
|
|
1370
|
-
`No supported editor was detected. Open ${path} from the repository, or set AHEAD_EDITOR=vscode.`,
|
|
1373
|
+
`No supported editor was detected. Open ${path} from the repository, or set AHEAD_EDITOR=vscode or AHEAD_EDITOR=zed.`,
|
|
1371
1374
|
"info",
|
|
1372
1375
|
);
|
|
1373
1376
|
}
|
|
@@ -1655,7 +1658,8 @@ async function recordHumanArtifact(
|
|
|
1655
1658
|
// "failed" (timeout, unparseable output, transient error) stays silent:
|
|
1656
1659
|
// the plain template is the fallback and needs no apology.
|
|
1657
1660
|
}
|
|
1658
|
-
let content = await
|
|
1661
|
+
let content = await editHumanArtifact(
|
|
1662
|
+
ctx,
|
|
1659
1663
|
`AHEAD mode · ${artifact.title} · write in your own words`,
|
|
1660
1664
|
template,
|
|
1661
1665
|
);
|
|
@@ -1684,7 +1688,8 @@ async function recordHumanArtifact(
|
|
|
1684
1688
|
ctx.ui.notify("Draft discarded. Nothing was saved.", "info");
|
|
1685
1689
|
return;
|
|
1686
1690
|
}
|
|
1687
|
-
const revised = await
|
|
1691
|
+
const revised = await editHumanArtifact(
|
|
1692
|
+
ctx,
|
|
1688
1693
|
`AHEAD mode · ${artifact.title} · finish the required fields`,
|
|
1689
1694
|
content,
|
|
1690
1695
|
);
|
|
@@ -1726,6 +1731,29 @@ async function recordHumanArtifact(
|
|
|
1726
1731
|
);
|
|
1727
1732
|
}
|
|
1728
1733
|
|
|
1734
|
+
async function editHumanArtifact(
|
|
1735
|
+
ctx: ExtensionCommandContext,
|
|
1736
|
+
title: string,
|
|
1737
|
+
content: string,
|
|
1738
|
+
): Promise<string | undefined> {
|
|
1739
|
+
if (!detectEditor()) {
|
|
1740
|
+
return ctx.ui.editor(title, content);
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
const temporaryRoot = await mkdtemp(join(tmpdir(), "ahead-artifact-"));
|
|
1744
|
+
const temporaryPath = join(temporaryRoot, "artifact.md");
|
|
1745
|
+
try {
|
|
1746
|
+
await writeFile(temporaryPath, content, "utf8");
|
|
1747
|
+
if (openInConfiguredEditor(temporaryRoot, { path: "artifact.md" }, { wait: true })) {
|
|
1748
|
+
return await readFile(temporaryPath, "utf8");
|
|
1749
|
+
}
|
|
1750
|
+
ctx.ui.notify("The configured editor could not be opened; using Pi's editor instead.", "info");
|
|
1751
|
+
return await ctx.ui.editor(title, content);
|
|
1752
|
+
} finally {
|
|
1753
|
+
await rm(temporaryRoot, { recursive: true, force: true });
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1729
1757
|
async function humanArtifactTemplate(
|
|
1730
1758
|
store: RunStore,
|
|
1731
1759
|
state: RunState,
|
package/src/review.ts
CHANGED
|
@@ -13,6 +13,8 @@ export interface SourceLocation {
|
|
|
13
13
|
column?: number;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export type EditorKind = "vscode" | "zed";
|
|
17
|
+
|
|
16
18
|
export interface ReviewSnapshot {
|
|
17
19
|
api_version: "ahead.review-snapshot/v0.1";
|
|
18
20
|
base_ref: string;
|
|
@@ -242,16 +244,23 @@ export function validateReviewDisposition(
|
|
|
242
244
|
return errors;
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
export function openInConfiguredEditor(
|
|
246
|
-
|
|
247
|
-
|
|
247
|
+
export function openInConfiguredEditor(
|
|
248
|
+
root: string,
|
|
249
|
+
location: SourceLocation,
|
|
250
|
+
options: { wait?: boolean } = {},
|
|
251
|
+
): boolean {
|
|
252
|
+
const editor = detectEditor();
|
|
253
|
+
if (!editor) {
|
|
248
254
|
return false;
|
|
249
255
|
}
|
|
250
256
|
const absolute = safeRepositoryPath(root, location.path);
|
|
251
257
|
const line = location.line ?? 1;
|
|
252
258
|
const column = location.column ?? 1;
|
|
253
259
|
const target = `${absolute}:${line}:${column}`;
|
|
254
|
-
const
|
|
260
|
+
const command = editor === "zed" ? "zed" : "code";
|
|
261
|
+
const wait = options.wait ? ["--wait"] : [];
|
|
262
|
+
const args = editor === "zed" ? [...wait, target] : [...wait, "--goto", target];
|
|
263
|
+
const result = spawnSync(command, args, { stdio: "ignore" });
|
|
255
264
|
return !result.error && result.status === 0;
|
|
256
265
|
}
|
|
257
266
|
|
|
@@ -280,16 +289,22 @@ function resolveReviewBase(root: string): string {
|
|
|
280
289
|
return "HEAD";
|
|
281
290
|
}
|
|
282
291
|
|
|
283
|
-
function
|
|
292
|
+
export function detectEditor(): EditorKind | undefined {
|
|
284
293
|
const explicit = process.env.AHEAD_EDITOR?.trim();
|
|
285
294
|
if (explicit === "vscode" || explicit === "code") {
|
|
286
|
-
return "
|
|
295
|
+
return "vscode";
|
|
296
|
+
}
|
|
297
|
+
if (explicit === "zed") {
|
|
298
|
+
return "zed";
|
|
287
299
|
}
|
|
288
300
|
if (explicit === "none") {
|
|
289
301
|
return undefined;
|
|
290
302
|
}
|
|
303
|
+
if (process.env.ZED === "1" || process.env.TERM_PROGRAM === "zed") {
|
|
304
|
+
return "zed";
|
|
305
|
+
}
|
|
291
306
|
return process.env.VSCODE_IPC_HOOK_CLI || process.env.TERM_PROGRAM === "vscode"
|
|
292
|
-
? "
|
|
307
|
+
? "vscode"
|
|
293
308
|
: undefined;
|
|
294
309
|
}
|
|
295
310
|
|