aiur-cli 0.0.3 → 0.0.5-nightly.24dcc4d

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.
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ readonly deletion_threshold=50
5
+ base_branch="${1:-${AIUR_BASE_BRANCH:-}}"
6
+
7
+ if [[ -z "$base_branch" ]]; then
8
+ echo "guard-pr-deletions: base branch is required (argument or AIUR_BASE_BRANCH)" >&2
9
+ exit 2
10
+ fi
11
+
12
+ if ! git diff --quiet || ! git diff --cached --quiet; then
13
+ echo "guard-pr-deletions: tracked changes must be committed before checking PR deletions" >&2
14
+ exit 2
15
+ fi
16
+
17
+ if ! git fetch --quiet --no-tags origin "refs/heads/$base_branch"; then
18
+ echo "guard-pr-deletions: could not fetch origin/$base_branch; refusing to use a stale base" >&2
19
+ exit 2
20
+ fi
21
+
22
+ if ! base_sha="$(git rev-parse --verify 'FETCH_HEAD^{commit}')"; then
23
+ echo "guard-pr-deletions: fetched base commit is unavailable" >&2
24
+ exit 2
25
+ fi
26
+
27
+ scratch_dir="$(mktemp -d)"
28
+ trap 'rm -rf "$scratch_dir"' EXIT
29
+
30
+ git diff --diff-filter=D --name-only "$base_sha"..HEAD | LC_ALL=C sort -u >"$scratch_dir/deleted"
31
+ deleted_count="$(wc -l <"$scratch_dir/deleted" | tr -d ' ')"
32
+
33
+ if ((deleted_count <= deletion_threshold)); then
34
+ echo "guard-pr-deletions: $deleted_count untouched file deletions (limit: $deletion_threshold)"
35
+ exit 0
36
+ fi
37
+
38
+ branch_start="${AIUR_BRANCH_START_SHA:-}"
39
+
40
+ if [[ -z "$branch_start" ]] && git rev-parse --verify --quiet 'refs/aiur/branch-start^{commit}' >/dev/null; then
41
+ branch_start="$(git rev-parse --verify 'refs/aiur/branch-start^{commit}')"
42
+ fi
43
+
44
+ if [[ -z "$branch_start" ]]; then
45
+ echo "guard-pr-deletions: refusing $deleted_count deletions because the workspace branch-start ref is unavailable" >&2
46
+ exit 1
47
+ fi
48
+
49
+ if ! git merge-base --is-ancestor "$branch_start" HEAD; then
50
+ echo "guard-pr-deletions: workspace branch-start $branch_start is not an ancestor of HEAD" >&2
51
+ exit 2
52
+ fi
53
+
54
+ git log --format= --name-only "$branch_start"..HEAD | sed '/^$/d' | LC_ALL=C sort -u >"$scratch_dir/touched"
55
+ # Both inputs are sorted with LC_ALL=C, so comm must compare with the same
56
+ # collation. Under a UTF-8 locale comm reads C-sorted input as unsorted (any
57
+ # mix of upper- and lower-case initial paths, e.g. README.md beside src/...)
58
+ # and its output on unsorted input is undefined -- it can drop rows, which
59
+ # would make this guard under-count untouched deletions and fail open.
60
+ LC_ALL=C comm -23 "$scratch_dir/deleted" "$scratch_dir/touched" >"$scratch_dir/untouched-deletions"
61
+
62
+ untouched_count="$(wc -l <"$scratch_dir/untouched-deletions" | tr -d ' ')"
63
+
64
+ if ((untouched_count > deletion_threshold)); then
65
+ echo "guard-pr-deletions: refusing PR with $untouched_count untouched file deletions (limit: $deletion_threshold)" >&2
66
+ sed -n '1,20p' "$scratch_dir/untouched-deletions" >&2
67
+ exit 1
68
+ fi
69
+
70
+ echo "guard-pr-deletions: $untouched_count untouched file deletions (limit: $deletion_threshold)"
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "aiur-cli",
3
- "version": "0.0.3",
3
+ "version": "0.0.5-nightly.24dcc4d",
4
4
  "description": "AI Unit Runtime for Executors.",
5
5
  "license": "Apache-2.0",
6
- "homepage": "https://github.com/its-everdred/aiur",
6
+ "homepage": "https://github.com/aiur-team/aiur",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/its-everdred/aiur.git"
9
+ "url": "git+https://github.com/aiur-team/aiur.git"
10
10
  },
11
11
  "bin": {
12
12
  "aiur": "bin/aiur.js"
@@ -18,17 +18,18 @@
18
18
  "files": [
19
19
  "bin/aiur.js",
20
20
  "libexec/aiur-engine.sh",
21
+ "libexec/guard-pr-deletions.sh",
21
22
  "scripts/postinstall.mjs",
22
23
  "share/aiur.tmux.conf"
23
24
  ],
24
25
  "engines": {
25
26
  "node": ">=18"
26
27
  },
27
- "opencodeVersion": "1.15.6",
28
+ "opencodeVersion": "1.17.10",
28
29
  "optionalDependencies": {
29
- "aiur-cli-linux-x64": "0.0.3",
30
- "aiur-cli-linux-arm64": "0.0.3",
31
- "aiur-cli-darwin-x64": "0.0.3",
32
- "aiur-cli-darwin-arm64": "0.0.3"
30
+ "aiur-cli-linux-x64": "0.0.5-nightly.24dcc4d",
31
+ "aiur-cli-linux-arm64": "0.0.5-nightly.24dcc4d",
32
+ "aiur-cli-darwin-x64": "0.0.5-nightly.24dcc4d",
33
+ "aiur-cli-darwin-arm64": "0.0.5-nightly.24dcc4d"
33
34
  }
34
35
  }
@@ -23,14 +23,15 @@ import path from "node:path";
23
23
 
24
24
  // Pinned opencode version, read from package.json `opencodeVersion` (single
25
25
  // source of truth — keep in sync with mise.toml). aiur's opencode pane
26
- // integration is validated against this version; 1.17.x broke custom-provider
27
- // model resolution (ProviderModelNotFoundError), blanking the chat panes.
26
+ // integration is validated end-to-end against this exact version; floating to
27
+ // `latest` would adopt an unverified opencode that could regress custom-provider
28
+ // model resolution or the chat panes, so the spec must carry a fixed version.
28
29
  const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
29
30
  export const OPENCODE_PACKAGE = `opencode-ai@${pkg.opencodeVersion}`;
30
31
 
31
32
  // True only when the *pinned* opencode version is on PATH. A wrong (e.g.
32
- // newer) version must be reinstalled — leaving 1.17.x in place keeps the
33
- // panes broken — so a mere presence check isn't enough.
33
+ // newer, unverified) version must be reinstalled to the pin — so a mere
34
+ // presence check isn't enough.
34
35
  export function opencodeMatchesPin() {
35
36
  const result = spawnSync("opencode", ["--version"], { encoding: "utf8" });
36
37
  return !result.error && result.status === 0 && result.stdout.trim() === pkg.opencodeVersion;