feat(audit): run the audit on the hosted agent platform behind a flag - #915
feat(audit): run the audit on the hosted agent platform behind a flag#915daniloc wants to merge 5 commits into
Conversation
`wizard audit` can now run server-side on the PostHog agent platform instead of a local Claude Agent SDK subprocess. The model runs off a frozen agent bundle and reaches back for this machine's filesystem via read-only client tools (list/grep/read, plus a single write for the report); its `resolve_checks` results mirror onto the same local ledger the existing audit TUI renders, so the screens, checklist, and report are unchanged. Keeping the audit's behaviour in a re-freezable bundle is the point — the checklist and report format change without a wizard release. Gated by the boolean `wizard-cloud-audit` flag (staff-targeted; the platform's posthog auth 403s anyone outside the agent's org). Plain `wizard audit` forks here when the flag is on and silently falls back to the classic local run on any cloud failure — same bootstrap, no re-auth; `wizard audit cloud` reaches the hosted arm directly. The ledger read-modify-write helpers move to a shared `audit/ledger.ts` so both the local MCP tools and the cloud bridge share one implementation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TKGXDLPogR2b41oGaJfyk5
| import { registerCleanup } from '../../../utils/wizard-abort'; | ||
| import { runLinearProgram } from './linear'; | ||
| import { runCloudProgram } from './cloud'; | ||
| import { WizardError, wizardAbort } from '../../../utils/wizard-abort'; |
There was a problem hiding this comment.
| import { WizardError, wizardAbort } from '../../../utils/wizard-abort'; | |
| import { WizardError, wizardAbort } from ''@utils/wizard-abort'; |
ditto other similar imports. We have these aliases
gewenyu99
left a comment
There was a problem hiding this comment.
Fly by,
What I'll ask you('re agent) to consider is that flags for switching between harness (which is what this is), sequence, model, and effort are all patched through the switch board for maintainability.
The cloud runner itself looks clean, but I believe we could achieve a better shape that way.
Issue 2 is that I see tools and ledger bridgers and cloud runner specific tools in the cloud-audit program. Might I suggest that they go in the runner?
for your consideration
|
@gewenyu99 indeed; I'm untangling its confused first cut a few different ways rn, thanks so much for this context |
The hosted audit agent accumulates its checklist in the CLI-hosted ledger (.posthog-audit-checks.json) but had no way to read it back — so its final report was built from its own context, which drifts over a long run. Add a read_ledger client tool that returns the wizard's accumulated ledger, so the agent re-grounds from the authoritative on-disk state instead of memory. The agent-side instruction (agent.md) and spec live in the wizard-audit bundle and re-deploy separately. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TKGXDLPogR2b41oGaJfyk5
|
lmao the problem was that it built this on an inexplicably stale checkout without my catching it. reworking |
b75bb2c to
0619572
Compare
Merge main and rebuild the hosted audit onto the runner architecture that landed since this branch forked (switchboard -> sequence + harness). The config.executor === 'cloud' fork and the machinery under programs/cloud-audit/ were the pre-switchboard shape; this replaces them with: - a remote sequence (sequence/remote.ts): remote bundle execution, no local skill install or prompt, drives the harness, owns seed/failover/outro - an agents-platform harness (harness/agents-platform/): the platform session transport, client tools, and ledger bridge, moved out of the program - switchboard wiring: Sequence.remote + Harness.agentsPlatform, a wizard-cloud-audit flag middleware on both axes, and a cloud-audit binding; the run-task clamp now only affects orchestrator - ProgramConfig.remoteRun: how a program declares its hosted arm; run stays the local default and the remote sequence's fallback Migrated to boot.credentials, dropped the obsolete executor/fallback fields, and rewrote the failover test for the new sequence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TKGXDLPogR2b41oGaJfyk5
0619572 to
a77f887
Compare
audit/index.ts and cloud-audit/index.ts import each other's run-builders at module-init time. buildCloudAuditRun is a hoisted `function`, so it survives the cycle, but buildClassicAuditRun was a non-hoisted `const` arrow. When the bundle emits the cloud-audit region first, cloudAuditConfig's `run: buildClassicAuditRun` reads the const before the audit region initializes it, throwing `ReferenceError: Cannot access 'buildClassicAuditRun' before initialization` at the top of dist/bin.js — a module-init crash that takes down the whole CLI. Convert buildClassicAuditRun to a hoisted `function` declaration, symmetric with buildCloudAuditRun, so both survive the cycle regardless of bundler ordering. Reproduced via the postbuild smoke test (bin.js crashed on load); fixed after. Generated-By: PostHog Code Task-Id: d5a911ec-e7d6-4b49-a651-9f56cb33ace7
Classic. |
|
There we go. A glance and it looks miles and miles cleaner to read. |
|
and I think I can make the diff even smaller 😎 |
The wizard's client-tool hands (read/grep/list/write) hand-rolled ~100 lines of node:fs logic. Route them through pi's built-in tool implementations (createReadTool/createGrepTool/createLsTool/createWriteTool) instead — the same engine the platform runs — so we reuse pi's read/grep/list/write logic, arg schemas, and truncation rather than maintaining our own. We keep only the path jail (the remote model is untrusted) and the audit-specific read_ledger. Follow-ups (need the platform stack): align the wizard-audit bundle's client tool descriptions to pi's result shape, and validate end to end. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TKGXDLPogR2b41oGaJfyk5
|
This should be an ultra neat shape. If we can prove this to be a good 1:1 drop over like we did pi vs anthropic agent SDK, we can just flag this for testing with any program |
Problem (by Danilo)
We need to try agent platform with real people and real projects. The
auditprogram is a great candidate: enough volume to be real, not an emergency if it breaks. this uses the new machinery, along with a feature flag, to route half of audits to the Agent Platform.we shouldn't merge until platform-side changes land
PostHog/posthog#71696
Changes (by the robot)
wizard auditcan now run server-side on the PostHog agent platform instead of a local subprocess, behind the booleanwizard-cloud-auditflag.The inversion is the whole point. In the local arm the model runs here and reaches out for a skill; in the hosted arm the model runs off a frozen agent bundle server-side and reaches back for this machine's filesystem through read-only client tools. The agent's
resolve_checksresults stream back over SSE and mirror onto the same local ledger the existing audit TUI file-watches — so the screens, live checklist, and on-disk report are unchanged. The audit's checklist and report format now change by re-freezing the bundle, with no wizard release.Built on the switchboard architecture. This branch was rebased onto main's runner refactor (switchboard → sequence + harness) per reviewer guidance. The hosted audit is not a branch inside a program — it's a first-class
remotesequence on anagents-platformharness, routed through the switchboard:remotesequence (runner/sequence/remote.ts) — remote bundle execution: no local skill install or prompt assembly. It resolves the program's hosted run, drives it through the harness, and owns the shared pipeline around that call (seed, failover, outro), mirroring howlinear.tswrapsanthropic/pi.agents-platformharness (runner/harness/agents-platform/) — the SDK adapter for the platform: opens a session, streams the turn, fulfils client tool calls, mirrors the checklist. The transport, client tools, and ledger bridge live here (moved out of the program, mirroring what refactor(agent): split runner into agent/runner, move orchestrator machinery out of programs #688 did for the orchestrator).Sequence.remote+Harness.agentsPlatformregistered; awizard-cloud-auditflag middleware on both axes bindsauditto{remote, agents-platform}; the explicitwizard audit cloudcommand gets a defaultcloud-auditbinding. The orchestrator run-task clamp now only affects orchestrator.ProgramConfig.remoteRun— how a program declares its hosted arm.runstays the local default and the remote sequence's fallback.Other pieces:
read_ledgerclient tool + re-grounding. The client hosts the run's authoritative ledger; the agent reads it back viaread_ledgerand builds the report's per-check results from it (not from its own context) — protecting the result against context drift over a long run. If it's missing a check the agent recorded, the agent re-records and re-reads (reconciliation), with a fall-through to its recorded state when the client keeps no ledger.posthogauth 403s anyone outside the agent's org, so the flag is targeted to PostHog staff; an external user who got it flipped would only reach a 403, surfaced as a readable message.wizard-tools.tsto a sharedaudit/ledger.tsso the local MCP tools and the cloud bridge share one implementation.Depends on the platform primitives in PostHog/posthog#71696 (the
authenticated-class audience story and the agent's client-tool session protocol).Known follow-up: the
agents-platformharness is still audit-coupled (importsbuildAuditTask+ the ledger bridge directly). Fine while audit is the only remote program; a second one would inject those from the program viaremoteRun.Test plan
runner/__tests__/switchboard.test.ts) — added cases pinning the routing:cloud-auditbinds to{remote, agents-platform}, andaudit+wizard-cloud-auditflag resolves to{remote, agents-platform}while staying{linear, anthropic}off the flag.failover.test.ts, rewritten for the sequence) — hosted success stops there; hosted error degrades to the local linear pipeline with the classic run; no remote arm → linear.cloud-audit-ledger-bridge.test.ts) — catalog/resolved folding, idempotent replay, stale-ledger reset, drift-drop coercion;read_ledgerreturns the accumulated ledger and empty before the first resolution.tsdownbuilds; prettier + eslint clean. (The remaining strict-tsc errors are in main's own untouched files — pi harness, orchestrator, ci-region.)POSTHOG_WIZARD_AGENT_URLpoints the wizard at a local ingress for end-to-end runs against the seededwizard-auditagent.LLM context
Co-authored in a Claude Code session. Rebased onto main's switchboard/sequence/harness architecture and re-homed the hosted audit as a
remotesequence +agents-platformharness per reviewer (gewenyu99) guidance; thewizard-developmentskill's architecture doc was updated to match. The platform-side counterpart (auth audience + cross-agent memory) is PostHog/posthog#71696.