Bulletin and Controlled Prose routing#
Gate provides two disabled policies for the fleet’s prose boundary. One validates a complete caller-owned bulletin section. The other carries a null routing request to Corpus. Neither policy reads a file, rewrites shared prose, starts a daemon, or registers a native hook.
from gate.admission import AdmissionKernel
from gate.policies import BulletinSectionPolicy, ControlledProseRoutePolicy
kernel = AdmissionKernel([BulletinSectionPolicy(), ControlledProseRoutePolicy()])
Constructing this kernel activates nothing. A native adapter still has to prove the lifecycle, complete candidate, target identity, and supported effects described in Action admission.
Bulletin section contract#
The adapter may identify the real fleet bulletin as the logical target fleet.bulletin only
after it has proved the canonical file target and isolated the complete section owned by the
caller. The candidate field is bulletin_section. Any other target or field makes the policy
abstain, so an uncertain adapter cannot inspect or block another agent’s section.
One optional blank line may follow the H2 header. One final newline is also optional. All other lines are mandatory, single-line, ASCII values in this exact order:
## <task> - <agent> - ACTIVE
doing: <one line>
where: <one line>
changes: yes <paths> | no
Duplicate, missing, unknown, reordered, empty, continued, or orphaned fields deny with that ASCII
skeleton. changes: no is the complete no-change form; otherwise yes must be followed by one or
more affected paths. Bare yes, none, and maybe deny. Non-ASCII typography, emoji, combining
characters, and CJK-family characters also deny. The policy never repairs or moves text. Its
feedback contains only stable issue classes and coordinates; receipts retain digests rather than
the section or recovery text.
Measured byte budget#
The 768-byte limit is calibrated, not a prose-quality claim. On 2026-09-02, the 12 active sections
then present in ~/ai/bulletin.md measured 235 bytes minimum, 431 median, 703 maximum, and 458.583
mean when each section was counted from its ## header through its separating newline. The limit
is the first 256-byte boundary above the observed maximum, leaving 65 bytes of headroom while
making the three-value shape the primary brevity constraint.
The replay was:
LC_ALL=C awk '
/^## / { if (active) print bytes; active=1; bytes=length($0)+1; next }
active { bytes+=length($0)+1 }
END { if (active) print bytes }
' ~/ai/bulletin.md |
sort -n |
awk '
{ value[NR]=$1; sum+=$1 }
END {
median = NR % 2 ? value[(NR+1)/2] : (value[NR/2]+value[NR/2+1])/2
printf "count=%d min=%d median=%.1f max=%d mean=%.3f\n", NR, value[1], median, value[NR], sum/NR
}
'
This baseline measures real active entries before promotion. It does not show that those entries already conformed to the new field shape, and it does not authorize activation. Re-measure after a representative shaped trial before promoting the threshold fleet-wide.
The optional policy’s admission budget is the largest materializable Python candidate rather than a second, lower semantic limit. Its evaluator checks target and field identity first, then counts at most 769 UTF-8 bytes before returning the oversize denial. Consequently, adding bytes cannot turn the 768-byte rule into an optional kernel abstention, while an uncertain target or caller-owned field still abstains without scanning the candidate.
Content-free Controlled Prose route#
ControlledProseRoutePolicy accepts only event prose.route, field route_request, value None,
and the exact logical target corpus.controlled_prose. An adapter may mint that target only when
it has evidence for target identity; native paths, suffixes, newlines, and document content in
either candidate or target abstain. The policy emits an observation naming the same Corpus route
and authority boundary. Gate therefore receives no prose bytes through this seam.
The route is not an eligibility decision. Corpus retains every privacy ring, exclusion, parser, protected-span check, semantic review, compare-and-swap, undo, reins, and inbox rule. Public, private, and sealed labels all receive the same content-free route observation; Corpus decides what may proceed.
Runtime survey and activation frontier#
The 2026-09-02 runtime survey found no Controlled Prose user unit or timer:
systemctl --user list-unit-files 'corpus-*prose*' # no rows
systemctl --user list-timers 'corpus-*prose*' # no rows
Corpus exposes the prose and prose-hygiene console commands, but no prose daemon or timer was
running. This change creates no second queue and does not activate either command. Native bulletin
enforcement and any Controlled Prose service remain later, explicit rollout decisions with fresh
adapter evidence and representative false-positive measurement.
Deterministic bulletin-shape checks and content-free prose routing.
The bulletin policy accepts one complete caller-owned section under a logical target identity. It never reads or rewrites the shared bulletin. The Controlled Prose policy routes only a null request plus target identity; document bytes remain outside Gate and under Corpus authority.
- class gate.policies.bulletin.BulletinIssue(kind: BulletinIssueKind, line: int, column: int = 1)#
One validation failure located without retaining source content.
- class gate.policies.bulletin.BulletinIssueKind(*values)#
Stable, content-free bulletin validation classes.
- class gate.policies.bulletin.BulletinSectionPolicy#
Validate one complete, caller-owned fleet bulletin section.
- class gate.policies.bulletin.ControlledProseRoutePolicy#
Route a null Markdown request to Corpus without receiving document bytes.
- gate.policies.bulletin.inspect_bulletin_section(value: str) tuple[BulletinIssue, ...]#
Return deterministic shape and character findings for one complete section.