ChatGPTClaudeGrok / X / CursorGemini

DSH GitHub review policy: run() hooks, repo mapping and 202

Configuration & UsagePublished 2026-10-21Author: DeepSeek Plugin Market
DeepSeek HarnessGitHub reviewwebhookpolicyworkspace
DSH GitHub review rules are trusted JavaScript: run() can query policy, map a repo to a local path, or return null. A 202 only means the call was scheduled.

The default GitHub review rule accepts one repository, one event, and one action; run() is what connects it to an internal workflow. It is ordinary trusted JavaScript: before returning a session request it can query a policy service, map a repository name to a local checkout, or return null to skip. That explains both “the webhook returned 202 but no session appeared” and “the same PR produced two sessions”.

DeepSeek Harness: What run() can do

run() executes after signature validation and before session creation; it is the only place to insert policy. Three actions:(source)

  1. Query internal policy — call a policy service and decide whether to review. Expected: return null when not allowed, so no session is created.
  2. Map repository paths — turn repository.full_name into an absolute local path. Expected: different repositories land in different checkouts.
  3. Return a session request — title, workspacePath, prompt. Expected: WorkspaceRegistry normalizes and starts a read-only review.

The return value is not an HTTP response; it is “whether to create a session and where”. The 202 is produced after that decision.

DeepSeek Harness: Policy and repository mapping

Two common extensions: choose a path by repository, and decide whether to run by policy. Official examples:(source)

js
const response = await fetch('https://policy.internal/pr-review', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ repository: payload.repository.full_name }),
  signal,
})
if (!response.ok || (await response.json()).automaticReview !== true) return null
js
const workspacePath = {
  'deepseek-ai/deepseek-harness': '/path/to/deepseek-harness',
  'deepseek-harness/dsh-sdk': '/path/to/dsh-sdk',
}[payload.repository.full_name]
if (workspacePath === undefined) return null
  1. Check the repository first — an unmapped repository returns null. Expected: no accidental session in the default directory.
  2. Then check policy — an unavailable or disallowing service returns null. Expected: fail closed, not auto-review.
  3. Finally supply the path — return an absolute path to WorkspaceRegistry. Expected: created on first use, reused later.

Pass signal to policy-service calls so cancellation follows the webhook; do not block here for a long time.

DeepSeek Harness: 202 and delivery semantics

202 is “accepted and scheduled”, not “matched and created”. Three boundaries:(source)

  • 202 does not mean the rule matched — the rule may return null for a repository, event, or action mismatch.
  • 202 does not mean a session exists — the invocation only entered in-memory scheduling.
  • Duplicate deliveries run again — the runtime stores no delivery state, so a duplicate webhook may create a second session.

To know whether a session really exists, check the DSH session list and logs, not only the GitHub delivery page.

DeepSeek Harness: Security boundaries

The webhook secret proves “this came from GitHub”; it does not grant “the agent may write to GitHub”. Four points:(source)

  1. Payload is untrusted metadata — the rule marks JSON untrusted; do not treat it as trusted instructions.
  2. Review sessions are read-only — the default uses the standard agent preset and read-only permission preset, forbidding changes to files, branches, PRs, or GitHub status.
  3. The secret only validates inbound — it does not grant outbound GitHub access to the rule or agent.
  4. Workspace paths must be trusted — the repository map belongs to the deployment, not to the payload.

If the policy service needs authentication, keep credentials in a controlled environment, not in the webhook payload or rule source.

DeepSeek Harness: A runnable rule skeleton

The core is “check source, choose path, return a session request or null”. Skeleton:(source)

js
export async function run(payload, { signal }) {
  if (payload.action !== 'ready_for_review') return null
  if (payload.repository.full_name !== 'your-org/your-repo') return null

  const workspacePath = '/srv/checkouts/your-repo'
  return {
    title: `Review PR #${payload.pull_request.number}`,
    workspacePath,
    prompt: `Review the changes in PR #${payload.pull_request.number}.`,
  }
}

A real rule should also query policy, pass the head SHA, and bound prompt length. The skeleton is enough to prove the webhook, signature, and Workspace path work.

DeepSeek Harness: Three policy strategies

Hard-coded allowlist, internal policy service, and map-plus-default-deny increase in flexibility and control. Three:(source)

  1. Hard-coded allowlist — fixed repositories and actions. Expected: simplest, good for one repository.
  2. Internal policy service — query per review by team, branch, or author. Expected: flexible, but a policy outage blocks reviews.
  3. Map + default deny — explicit repository-to-path mapping; an unmapped repo is skipped. Expected: controlled paths, good for multiple repositories.

The strategies combine. The most common setup is “map decides the path, policy service decides whether to run”.

DeepSeek Harness FAQ

Webhook configured, PR ready, but no session—why? Confirm the event is pull_request and the action is ready_for_review, then check whether the rule returned null for the repository or action. A 202 does not prove a match.

Will repeated ready events review the same PR twice? Possibly. The runtime stores no delivery state; make the rule idempotent, for example by checking an internal review record.

Can the review session be made writable? You can change the preset, but that breaks the default read-only boundary. If writes are required, design permissions and audit separately.

The short version: GitHub review policy lives in run(), not in YAML; a 202 only means the request was accepted, not that a review happened.

ChatGPTClaudeGrok / X / CursorGemini

FAQ

When does the DeepSeek Harness GitHub review rule run?

DeepSeek Harness: after the webhook receives a payload that passes signature validation, the overlay invokes run(). It is ordinary trusted JavaScript and can query an internal policy service, map a repository path, or return null before a session request is produced.

How do I map different GitHub repositories to different local checkouts?

DeepSeek Harness: use payload.repository.full_name as a key in run() and map it to an absolute local path; return null when there is no mapping. The workspacePath is normalized by WorkspaceRegistry.create(), which creates it on first use and reuses it later.

Does a 202 response mean the review session was created?

DeepSeek Harness: no. A 202 only means the signature and JSON were accepted and the rule invocation was scheduled in memory. It does not mean the rule matched or that a session was created. Check the DSH session list.

Can duplicate GitHub deliveries create multiple review sessions?

DeepSeek Harness: yes. The webhook runtime stores no delivery or execution state, so a duplicate delivery runs the rule again and may create another session. Make the rule idempotent if that matters.

Does the webhook secret grant the agent GitHub write access?

DeepSeek Harness: no. The secret only validates inbound GitHub data. It does not grant the rule or the created agent outbound GitHub access; configure that permission separately.

Related Terms

github-review overlay
The github-review overlay is an optional DeepSeek Harness configuration layer that adds a signed GitHub endpoint to dsh web and creates a read-only review session when a pull request becomes ready for review.— DeepSeek Harness docs - GitHub review sessions
run()
run() is the trusted JavaScript entry point of a github-review rule. It executes before the session request and can query policy, map repositories, or return null to skip.— DeepSeek Harness docs - GitHub review sessions
WorkspaceRegistry.create()
WorkspaceRegistry.create() normalizes a workspacePath. On the first matching delivery it creates the workspace if absent; later deliveries reuse it.— DeepSeek Harness docs - GitHub review sessions
202
202 is the github-review webhook HTTP response meaning the signature and JSON were accepted and the rule invocation was scheduled in memory. It does not mean the rule matched or a session exists.— DeepSeek Harness docs - GitHub review sessions

Sources