The approval gate
Every post carries an approval state:draft, approved, or rejected.
- Fail-closed. A post with no approval will not publish. The default is to not act.
- Drafts only on create.
plan_create_postalways creates a draft. Creating a post never approves it. - Approval is explicit. Only
approve_postandreject_postflip the approval state. - Approval is separate from authorship. Nothing publishes until it’s approved, and by default that approver is you.
The Meta 368 breaker
Meta error 368 is an action block. When pendpost sees a 368 it trips a breaker that halts the Meta lane.- Never auto-resumes. Error 368 carries no machine-readable clear time, so pendpost cannot know when Meta has lifted the block. The owner must clear the breaker explicitly once Meta lifts it (see From an agent (MCP) for the clear call).
- Zero Graph traffic while blocked. Health probes send no Graph traffic while the lane is blocked, so pendpost will not poke an already-angry endpoint.
The cadence cap
The Meta lane has a cadence cap configured indata/plans/meta-lane.json:
maxPer24h: the maximum number of publishes in a rolling 24 hours.minGapMinutes: the minimum gap between publishes.
On a multi-client instance,
data/plans/meta-lane.json is resolved per active client (in the active client’s subtree, under data/plans/), so each project can tune its own cadence cap independently.meta_lane_set({ actor: "owner", cadence: { maxPer24h, minGapMinutes } }) (see From an agent (MCP)).
The lane pause kill switch
You can stop the Meta lane on demand with the lane pause kill switch:- Set
pausedindata/plans/meta-lane.json, or - Set the environment variable
META_PUBLISHING_PAUSEDtotrue.
META_PUBLISHING_PAUSED overrides a file or tool pause: while that env var is set, a paused write has no effect.
From an agent, pause or resume over MCP instead of hand-editing the file: meta_lane_set({ actor: "owner", paused: true }) or meta_lane_set({ actor: "owner", paused: false }) (see From an agent (MCP)). Resuming the lane never clears a 368 block.
From an agent (MCP)
A headless agent does not edit JSON by hand. The same breakers are readable and operable over the MCP face (see MCP), with the owner still in control of the dangerous half.- Read the state.
pendpost_healthis the one-call readiness check. It returns{ ready, blockers[], schedulerRunning, nextDue[] }, whereblockers[]surfaces the 368 block and lane readiness andnextDue[]lists the next due posts (a post deferred only by the cadence cap still appears there: throttled, not failed). It is read-only. - Record a block.
pendpost_record_blockrecords a 368 (the engines call it on a Meta 368, and an agent can record one too), client-scoped with an optionalclientId. - Clear a block. Clearing is the owner’s call:
pendpost_record_block({ blockedUntil: null, actor: "owner" }), on the owner’s explicit instruction once Meta has confirmed the lift out of band. - A manual sweep respects the block.
publish_due_run(confirm: true)filters the Meta lane out exactly as a scheduler tick does, so an on-demand run cannot punch through an active 368. - Tune the cadence cap or pause the lane.
meta_lane_set({ actor: "owner", cadence: { maxPer24h, minGapMinutes } })sets the cap;meta_lane_set({ actor: "owner", paused: true })ormeta_lane_set({ actor: "owner", paused: false })stops or resumes the lane. Passactor(e.g."owner","agent:claude") — it is logged to the activity feed.META_PUBLISHING_PAUSEDoverrides a file or tool pause, andmeta_lane_setnever clears a 368 block (clear that withpendpost_record_block).
The gate, the 368 breaker, the cadence cap, and the lane pause stack. A post must be approved, the lane must not be paused, the 368 breaker must be clear, and the post must fit the cadence cap before it publishes.