agentplane 0.6.9 → 0.6.10

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/bin/agentplane.js CHANGED
@@ -415,9 +415,15 @@ async function assertDistUpToDate() {
415
415
  });
416
416
  }
417
417
 
418
+ const freshnessResults = await Promise.all(
419
+ checks.map(async (check) => ({
420
+ check,
421
+ result: await isPackageBuildFresh(check.root, { watchedPaths: check.watchedPaths }),
422
+ })),
423
+ );
424
+
418
425
  const staleReasons = [];
419
- for (const check of checks) {
420
- const result = await isPackageBuildFresh(check.root, { watchedPaths: check.watchedPaths });
426
+ for (const { check, result } of freshnessResults) {
421
427
  if (!result.ok) {
422
428
  const detail =
423
429
  Array.isArray(result.changedPaths) && result.changedPaths.length > 0
package/bin/dist-guard.js CHANGED
@@ -32,7 +32,13 @@ async function readJsonIfExists(p) {
32
32
 
33
33
  function resolveGitHead(cwd) {
34
34
  try {
35
- return execFileSync("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8" }).trim() || null;
35
+ return (
36
+ execFileSync("git", ["rev-parse", "HEAD"], {
37
+ cwd,
38
+ encoding: "utf8",
39
+ stdio: ["ignore", "pipe", "ignore"],
40
+ }).trim() || null
41
+ );
36
42
  } catch {
37
43
  return null;
38
44
  }
@@ -41,7 +47,11 @@ function resolveGitHead(cwd) {
41
47
  function listGitPaths(cwd, args, options = {}) {
42
48
  const trimLines = options.trimLines ?? true;
43
49
  try {
44
- const out = execFileSync("git", args, { cwd, encoding: "utf8" });
50
+ const out = execFileSync("git", args, {
51
+ cwd,
52
+ encoding: "utf8",
53
+ stdio: ["ignore", "pipe", "ignore"],
54
+ });
45
55
  return out
46
56
  .split(/\r?\n/u)
47
57
  .map((line) => (trimLines ? line.trim() : line))
@@ -51,6 +61,26 @@ function listGitPaths(cwd, args, options = {}) {
51
61
  }
52
62
  }
53
63
 
64
+ function tryListGitPaths(cwd, args, options = {}) {
65
+ const trimLines = options.trimLines ?? true;
66
+ try {
67
+ const out = execFileSync("git", args, {
68
+ cwd,
69
+ encoding: "utf8",
70
+ stdio: ["ignore", "pipe", "ignore"],
71
+ });
72
+ return {
73
+ ok: true,
74
+ paths: out
75
+ .split(/\r?\n/u)
76
+ .map((line) => (trimLines ? line.trim() : line))
77
+ .filter(Boolean),
78
+ };
79
+ } catch {
80
+ return { ok: false, paths: [] };
81
+ }
82
+ }
83
+
54
84
  function uniqueSorted(values) {
55
85
  return [...new Set(values)].toSorted((a, b) => a.localeCompare(b));
56
86
  }
@@ -71,6 +101,25 @@ function workingTreeChangedPaths(cwd, watchedPaths) {
71
101
  );
72
102
  }
73
103
 
104
+ function tryWorkingTreeChangedPaths(cwd, watchedPaths) {
105
+ const result = tryListGitPaths(
106
+ cwd,
107
+ ["status", "--porcelain", "--untracked-files=all", "--", ...watchedPaths],
108
+ { trimLines: false },
109
+ );
110
+ return {
111
+ ok: result.ok,
112
+ paths: uniqueSorted(
113
+ result.paths
114
+ .map((line) => {
115
+ const normalized = String(line ?? "");
116
+ return normalized.length > 3 ? normalized.slice(3).trim() : "";
117
+ })
118
+ .filter((filePath) => Boolean(filePath) && isRuntimeRelevantWatchedFile(filePath)),
119
+ ),
120
+ };
121
+ }
122
+
74
123
  function committedChangedPathsSince(cwd, fromGitHead, watchedPaths) {
75
124
  if (!fromGitHead) return [];
76
125
  return uniqueSorted(
@@ -84,6 +133,21 @@ function committedChangedPathsSince(cwd, fromGitHead, watchedPaths) {
84
133
  );
85
134
  }
86
135
 
136
+ function tryCommittedChangedPathsSince(cwd, fromGitHead, watchedPaths) {
137
+ if (!fromGitHead) return { ok: false, paths: [] };
138
+ const result = tryListGitPaths(cwd, [
139
+ "diff",
140
+ "--name-only",
141
+ `${fromGitHead}..HEAD`,
142
+ "--",
143
+ ...watchedPaths,
144
+ ]);
145
+ return {
146
+ ok: result.ok,
147
+ paths: uniqueSorted(result.paths.filter((filePath) => isRuntimeRelevantWatchedFile(filePath))),
148
+ };
149
+ }
150
+
87
151
  async function fileMtimeMs(p) {
88
152
  try {
89
153
  const s = await stat(p);
@@ -144,6 +208,26 @@ export async function isPackageBuildFresh(packageRoot, options = {}) {
144
208
  const currentHead = resolveGitHead(packageRoot);
145
209
  const manifestSnapshot = parseManifestSnapshot(manifest);
146
210
  if (manifestSnapshot) {
211
+ const committedQuickCheck = tryCommittedChangedPathsSince(
212
+ packageRoot,
213
+ manifest.git_head,
214
+ manifestSnapshot.watchedPaths,
215
+ );
216
+ const workingTreeQuickCheck = tryWorkingTreeChangedPaths(
217
+ packageRoot,
218
+ manifestSnapshot.watchedPaths,
219
+ );
220
+ const changedPaths = uniqueSorted([
221
+ ...committedQuickCheck.paths,
222
+ ...workingTreeQuickCheck.paths,
223
+ ]);
224
+ if (committedQuickCheck.ok && workingTreeQuickCheck.ok && changedPaths.length === 0) {
225
+ if (manifest.git_head && currentHead && manifest.git_head !== currentHead) {
226
+ return { ok: true, reason: "fresh_after_git_quick_check", changedPaths: [] };
227
+ }
228
+ return { ok: true, reason: "fresh", changedPaths: [] };
229
+ }
230
+
147
231
  const currentSnapshot = await collectWatchedRuntimeSnapshot(
148
232
  packageRoot,
149
233
  manifestSnapshot.watchedPaths,
@@ -2,7 +2,7 @@
2
2
  "schema_version": 1,
3
3
  "manifest_kind": "package",
4
4
  "package_name": "agentplane",
5
- "package_version": "0.6.9",
6
- "git_head": "c64a147ee51ff07019a834b314face264cabb948",
7
- "watched_runtime_snapshot_hash": "615cd705f0e53934ac27d05278232358ece4cef3ec436e27ed514c314755d66b"
5
+ "package_version": "0.6.10",
6
+ "git_head": "e50e620a0716c40cfa3710a3af33161a760cf7a9",
7
+ "watched_runtime_snapshot_hash": "1ad5c76d8b356c40184cb982a599adcdaedbf66e7fb1209a0dbbf294c0d2dc9e"
8
8
  }