Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d9cb408
refactor(advisor): remove disconnected analyzer
cv Aug 31, 2026
e3e3841
fix(advisor): remove retired schema terms
cv Aug 31, 2026
84eff6f
fix(ci): remove retired advisor timing hint
cv Aug 31, 2026
29e315f
fix(advisor): close specialist lifecycle findings
cv Aug 31, 2026
35b9240
fix(advisor): complete specialist migration coverage
cv Aug 31, 2026
2426b50
fix(advisor): expose diff within review boundary
cv Aug 31, 2026
e42081f
docs(advisor): clarify local snapshot dependencies
cv Aug 31, 2026
c54ec74
fix(advisor): gate lifecycle on prepared inputs
cv Aug 31, 2026
f7d6e2a
Merge remote-tracking branch 'origin/main' into refactor/remove-dead-…
cv Aug 31, 2026
53522d5
fix(advisor): clean only owned sandboxes
cv Aug 31, 2026
1ea65db
fix(advisor): isolate sandbox ownership by run
cv Aug 31, 2026
bc3bcb6
test(advisor): prove analysis skips preparation
cv Aug 31, 2026
cb08f4d
fix(advisor): isolate reruns and test artifact timing
cv Aug 31, 2026
16f1de6
fix(advisor): confirm sandbox ownership before cleanup
cv Aug 31, 2026
f430b0e
fix(advisor): stop artifact work after cancellation
cv Aug 31, 2026
e6156bf
fix(advisor): suppress cancelled summary publication
cv Aug 31, 2026
746b53e
Merge remote-tracking branch 'origin/main' into refactor/remove-dead-…
cv Aug 31, 2026
5280970
fix(advisor): clean partial sandbox creation
cv Aug 31, 2026
86f99b3
fix(advisor): verify sandbox ownership before create
cv Aug 31, 2026
c24a991
test(advisor): model sandbox ownership locally
cv Aug 31, 2026
81f8e04
refactor(advisor): rely on invocation sandbox identity
cv Aug 31, 2026
b508512
fix(advisor): generate lifecycle sandbox identity
cv Aug 31, 2026
925cd4d
refactor(advisor): remove retired sandbox identity path
cv Aug 31, 2026
6dbd071
fix(advisor): confirm sandbox ownership before cleanup
cv Aug 31, 2026
a0626eb
test(advisor): prove failed create stays unowned
cv Aug 31, 2026
c3d335e
fix(advisor): reconcile partial sandbox creation
cv Aug 31, 2026
f77573e
refactor(advisor): share local review preparation
cv Aug 31, 2026
232ed14
test(advisor): remove retired token assertion
cv Aug 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1255,9 +1255,10 @@ const PR_METADATA_EDIT_JOB_NAMES = new Set([
const PR_REVIEW_ADVISOR_WORKFLOW_NAME = "Automation / PR Review Advisor";
const PR_REVIEW_ADVISOR_WORKFLOW_PATH = ".github/workflows/pr-review-advisor.yaml";
const ADVISORY_PR_REVIEW_ADVISOR_JOB_NAMES = new Set([
"PR review advisor (GPT-5.6 Terra)",
"PR review advisor (Nemotron 3 Ultra)",
"Discover review specialists and collect GitHub context",
"Publish advisor link",
]);
const ADVISORY_PR_REVIEW_ADVISOR_SPECIALIST_JOB = /^Specialist \/ [^/]+$/u;

interface ActionRunMetadata {
attempt: number;
Expand Down Expand Up @@ -1893,7 +1894,8 @@ function currentCheckRollup(
if (
check.__typename !== "CheckRun" ||
check.workflowName !== PR_REVIEW_ADVISOR_WORKFLOW_NAME ||
!ADVISORY_PR_REVIEW_ADVISOR_JOB_NAMES.has(checkName)
!ADVISORY_PR_REVIEW_ADVISOR_JOB_NAMES.has(checkName) &&
!ADVISORY_PR_REVIEW_ADVISOR_SPECIALIST_JOB.test(checkName)
) {
return false;
}
Expand Down
15 changes: 1 addition & 14 deletions .github/workflows/pr-review-advisor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ on:
required: false
type: string
default: main
run_analysis:
description: Run PR review advisor analysis
required: false
type: boolean
default: true

# Each job declares its own privilege domain. In particular, no model-bearing
# job can write to a pull request, and the publisher never receives the model
# credential or the untrusted PR worktree.
Expand Down Expand Up @@ -105,15 +99,13 @@ jobs:
# Pin runtime packages to reviewed versions. Updates go through normal
# dependency review rather than floating in a secret-bearing job.
PI_SDK_VERSION: "0.80.6"
# The review ledger imports TypeBox directly. Pi 0.80.6 shrinkwraps its
# The advisor tools import TypeBox directly. Pi 0.80.6 shrinkwraps its
# own copy, so the advisor runtime must install this direct dependency.
TYPEBOX_VERSION: "1.1.38"
# Workflow-boundary modules parse YAML before the advisor session starts.
YAML_VERSION: "2.8.3"
# Embedded Pi SDK sessions use Pi's proxy-aware Undici transport.
UNDICI_VERSION: "8.10.0"
# Credential-free inventory discovery executes the trusted Vitest entrypoint.
VITEST_VERSION: "4.1.9"
FD_FIND_VERSION: "9.0.0-1"
RIPGREP_VERSION: "14.1.0-1"
OPENSHELL_GATEWAY_ENDPOINT: http://127.0.0.1:8080
Expand All @@ -123,12 +115,10 @@ jobs:
PR_REVIEW_ADVISOR_MODEL: ${{ matrix.advisor.model }}
PR_REVIEW_ADVISOR_INTEREST: ${{ matrix.advisor.interest }}
PR_REVIEW_ADVISOR_ARTIFACT_DIR: ${{ matrix.advisor.artifact_dir }}
PR_REVIEW_ADVISOR_RUN_ANALYSIS: ${{ github.event_name == 'workflow_dispatch' && inputs.run_analysis == false && '0' || '1' }}
PR_REVIEW_ADVISOR_COMMENT_MARKER: "<!-- nemoclaw-pr-review-advisor -->"
PR_REVIEW_ADVISOR_COMMENT_TITLE: PR Review Advisor
PR_REVIEW_ADVISOR_COMMENT_LABEL: PR review advisor
PR_REVIEW_ADVISOR_WORKFLOW_NAME: "Automation / PR Review Advisor"
SANDBOX_NAME: ${{ matrix.advisor.sandbox_name }}
# Only executable code from this checkout may run in the analysis job.
ADVISOR_DIR: ${{ github.workspace }}/advisor
TARGET_REPO: ${{ github.event_name == 'pull_request_target' && github.repository || inputs.target_repo || github.repository }}
Expand Down Expand Up @@ -264,18 +254,15 @@ jobs:

# Shared lifecycle phases preserve the configure-only credential boundary.
- name: Install OpenShell
if: ${{ env.PR_REVIEW_ADVISOR_RUN_ANALYSIS == '1' }}
run: |
env -u GITHUB_TOKEN -u GH_TOKEN -u PR_REVIEW_ADVISOR_API_KEY \
NEMOCLAW_NON_INTERACTIVE=1 \
bash "$ADVISOR_DIR/scripts/install-openshell.sh"

- name: Run advisor specialist lifecycle
id: specialist-analysis
if: always()
env:
OPENAI_API_KEY: ${{ secrets.PR_REVIEW_ADVISOR_API_KEY }}
PR_REVIEW_ADVISOR_UNAVAILABLE_REASON: ${{ env.PR_REVIEW_ADVISOR_RUN_ANALYSIS == '0' && 'PR_REVIEW_ADVISOR_RUN_ANALYSIS=0' || 'OpenShell inference configuration failed or the advisor credential is unavailable' }}
run: node --experimental-strip-types --no-warnings "$ADVISOR_DIR/tools/pr-review-advisor/specialist-lifecycle.mts" analysis

- name: Upload specialist review
Expand Down
1 change: 0 additions & 1 deletion ci/cli-test-timing-hints.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@
"test/agents/openclaw/runtime/nemoclaw-start.test.ts": 28600,
"test/automation/e2e/e2e-recommendations.test.ts": 45421,
"test/automation/pull-requests/pr-review-advisor-security-boundaries.test.ts": 24108,
"test/automation/pull-requests/pr-review-advisor-submission-tools.test.ts": 5422,
"test/automation/pull-requests/pr-review-advisor-writing-guide.test.ts": 8835,
"test/automation/releases/release-latest-tag.test.ts": 20264,
"test/automation/releases/retire-release-label.test.ts": 5642,
Expand Down
36 changes: 0 additions & 36 deletions test/automation/pull-requests/code-change-considerations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ import { tmpdir } from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";

import { preparePromptArtifacts } from "../../../tools/pr-review-advisor/analyze.mts";
import { artifactPaths } from "../../../tools/pr-review-advisor/artifacts.mts";
import {
buildSystemPrompt,
readTrustedCodeChangeConsiderations,
} from "../../../tools/pr-review-advisor/trusted-guidance.mts";
import { metadata } from "../../helpers/pr-review-advisor-test-fixtures";

const ROOT = path.resolve(import.meta.dirname, "../../..");
const RESOURCE_PATH = path.join(
Expand Down Expand Up @@ -105,37 +102,4 @@ describe("shared code change considerations", () => {
);
});

it("writes visible failure artifacts for malformed Advisor input", () => {
const outDir = fs.mkdtempSync(path.join(tmpdir(), "advisor-considerations-failure-"));
const reviewMetadata = metadata();
mockTrustedConsiderationsRead(
() => "# Code Change Considerations\n\nThis lost its contract structure.",
);

try {
expect(() =>
preparePromptArtifacts({
artifacts: artifactPaths(outDir),
metadata: reviewMetadata,
diff: "",
}),
).toThrow("Code change considerations malformed");
expect(
JSON.parse(fs.readFileSync(path.join(outDir, "pr-review-advisor-result.json"), "utf8")),
).toMatchObject({
failed: true,
reason: expect.stringContaining("Code change considerations malformed"),
});
expect(
JSON.parse(
fs.readFileSync(path.join(outDir, "pr-review-advisor-final-result.json"), "utf8"),
),
).toMatchObject({
headSha: reviewMetadata.headSha,
reviewCompleteness: { requiresHumanReview: true },
});
} finally {
fs.rmSync(outDir, { recursive: true, force: true });
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
type OpenPrOverlap,
} from "../../../tools/pr-review-advisor/github-context.mts";
import { buildSystemPrompt } from "../../../tools/pr-review-advisor/trusted-guidance.mts";
import { ROOT } from "../../helpers/pr-review-advisor-test-fixtures.ts";
const ROOT = path.resolve(import.meta.dirname, "../../..");

describe("PR review advisor", () => {
afterEach(() => {
Expand Down
34 changes: 0 additions & 34 deletions test/automation/pull-requests/pr-review-advisor-diff.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,40 +127,6 @@ describe("PR review advisor diff", () => {
}
});

it("writes failure artifacts when trusted Git inputs are unavailable", () => {
const tmp = fs.mkdtempSync(path.join(tmpdir(), "nemoclaw-pr-advisor-diff-"));
const result = spawnSync(
process.execPath,
[
"--experimental-strip-types",
path.join(ROOT, "tools/pr-review-advisor/analyze.mts"),
"--base",
"missing-ref",
"--head",
"HEAD",
"--schema",
path.join(ROOT, "tools/pr-review-advisor/schema.json"),
"--out-dir",
tmp,
],
{ cwd: ROOT, encoding: "utf8" },
);

try {
expect(result.status).toBe(1);
expect(
JSON.parse(fs.readFileSync(path.join(tmp, "pr-review-advisor-result.json"), "utf8")),
).toMatchObject({ failed: true });
expect(
JSON.parse(fs.readFileSync(path.join(tmp, "pr-review-advisor-final-result.json"), "utf8")),
).toMatchObject({
headSha: expect.stringMatching(/^[0-9a-f]{40}$/u),
reviewCompleteness: { requiresHumanReview: true },
});
} finally {
fs.rmSync(tmp, { recursive: true, force: true });
}
});
});

function commit(cwd: string, message: string): void {
Expand Down
Loading
Loading