Skip to content

DocAgentService

Defined in: src/doc-agent.ts:148

PR-gated AI doc agent (issue #882, epic #875 Phase 3).

Manual-trigger, flag-gated (config.docAgentEnabled). On consider(repoPath) it spawns a scoped, dontAsk Claude Code agent in a disposable worktree (see docAgentArgv); the agent EDITS stale prose docs and writes a SENTINEL summary, but runs NO git. On the next tick() the trusted server stages ONLY the in-scope file list, commits --no-verify, pushes, and opens a PR via forge.openPr() — never an auto-merge. Mirrors the worktree+git tail of import(”./promote”).Promoter and the spawn/membrane posture of ReviewService.

Restart-safety: the unique-per-run herdr name (__docagent__<8hex>) makes name-squat impossible; sweepOrphans() (boot) additionally clears husk tabs + orphan shepherd/docs-update-* worktrees, working even when the herdr daemon also restarted (it parses git worktree list).

new DocAgentService(deps): DocAgentService

Defined in: src/doc-agent.ts:160

DocAgentDeps

DocAgentService

consider(repoPath): Promise<DocAgentResult>

Defined in: src/doc-agent.ts:196

Start a doc-agent run for repoPath (manual trigger). At most one per repo at a time.

string

Promise<DocAgentResult>


forget(repoPath): void

Defined in: src/doc-agent.ts:505

Drop a repo’s in-flight tracking (e.g. on shutdown); does not touch the worktree.

string

void


onMergedPr(repoPath, prNumber, prTitle, baseBranch): Promise<DocAgentResult>

Defined in: src/doc-agent.ts:223

Merge-triggered consideration (issue #904). Called when a managed session’s PR merges. Only a merge INTO the repo’s default branch is considered — baseBranch (the session’s PR target) must equal forge.defaultBranch(); a feat/config PR merging into a non-default (epic/stacked) base would spawn a near-no-op run grounded on the default tip, and those changes reach the default branch at epic-landing time (caught by the nightly sweep) anyway.

Gated on a PER-PR persisted merged-seen key (NOT the sha-gate): the merged session:git event fires ONCE (the open→merged transition; gitStateChanged re-emits only on state/checks/headSha/mergeable/review/handoff moves) and this method does NO fetch, so the local origin/<base> is still the pre-merge sha at that instant — a sha-gate would wrongly skip with no re-emit to retry. The per-PR key is freshness-independent: it fires immediately (consider() → begin() fetches via ensureBaseRef so the agent grounds on the merged commits) and is restart-idempotent (the 3s boot warm-tick replays the merged event, but the key is already set).

string

number | undefined

string | undefined

string

Promise<DocAgentResult>


sweepNightly(): Promise<void>

Defined in: src/doc-agent.ts:256

Nightly cadence sweep (issue #904). Called on the 15s tick (flag-gated in index.ts). For each doc-tree repo, at most once per local day (the nightly-day marker), freshens origin/<base> and spawns a run ONLY when the default branch advanced since the last run (the last-sha gate) — so quiet days cost a fetch but no agent spawn.

Promise<void>


sweepOrphans(): Promise<void>

Defined in: src/doc-agent.ts:519

Boot reconcile. Two independent passes so it works even when the herdr daemon ALSO restarted:

  1. Close any live herdr tab whose name starts with the doc-agent prefix (herdr survived).
  2. herdr-independent: parse git worktree list per known repo and remove every shepherd/docs-update-* worktree + force-delete its branch (the authoritative orphan signal when there’s no tab to read a cwd from, and no persisted run rows). Scoped strictly to the doc-agent namespace, so it never collides with the reviewer’s review * reaper or the tmpfs sweeper.

Promise<void>


tick(): Promise<void>

Defined in: src/doc-agent.ts:444

Finalize any run whose sentinel is ready or that timed out.

Promise<void>