PHASE S7.5 — RUNTIME EMISSION GUARDRAILS (IMPLEMENTATION + HARD GATES)

STATUS INTENT

This phase wires runtime emission capability for expansion invitations, but ONLY behind hard gates and feature flags, with silent abort as the default outcome. The system must preserve:

  • Contract 1 truth envelope

  • S6 epistemic guarantees

  • S7.1 language constraints (canonical)

  • S7.2 generation constraints (canonical)

  • S7.3 template fixtures (canonical)

  • S7.4 CI mechanical invariants (active)

ABSOLUTE CONSTRAINTS (NON-NEGOTIABLE)

  1. Default outcome is ALWAYS “emit nothing.”

  2. Any rule failure results in silent abort (no user-visible signal, no apology, no meta).

  3. One invitation maximum per response.

  4. No new facts. Invitation text must be semantically inert.

  5. No questions (no “?”).

  6. No second-person pronouns (“you”, “your”, “yours”).

  7. No optionality phrasing (“if you want”, “you can”, “feel free”).

  8. No evaluative adjectives (“helpful”, “important”, “useful”, “better”, “essential”).

  9. No imperatives (“do”, “try”, “follow”, “use”, “apply”, “practice”).

  10. One sentence only.

  11. One plane only (C OR D OR E) and must match selected plane exactly.

  12. No emission on DEFINE/VERIFY/SCRIPTURE/UNKNOWN speech-acts (inherits S7.2).

  13. No emission unless CI invariants are green (mechanical gate).

  14. No emission unless Canary is explicitly authorized for invitations (separate flag from Contract 2 enrichment).

FEATURE FLAGS (ENV)

Add to /app/ezra_admin/.env (do not remove existing flags):

FEATURE_S7_INVITES_ENABLED=false

FEATURE_S7_INVITES_ROLLOUT_PERCENTAGE=0

FEATURE_S7_INVITES_REQUIRE_CI_GREEN=true

FEATURE_S7_INVITES_REQUIRE_CANARY_FREEZE=false

Notes:

  • REQUIRE_CI_GREEN must remain true in all environments that can reach users.

  • REQUIRE_CANARY_FREEZE is optional; set true if you want “no invites while enrichment canary is running.”

RUNTIME EMISSION DECISION PIPELINE (ORDER)

This MUST run after Contract 1 completion and after Contract 2 enrichment handling (if enabled), and ONLY as a post-processing append candidate:

  1. Contract 1 completes successfully.

  2. Contract 2 enrichment may or may not attach (independent).

  3. S7 invitation eligibility check (S7.2 canonical rules).

  4. S7 guardrail gate checks (new S7.5).

  5. If allowed, choose exactly one template (S7.3 canonical templates only).

  6. Validate final invitation string with the same CI validator used in S7.4 (shared logic).

  7. If passes, append as final line (double newline separator).

  8. If fails at any point: append nothing; no logging to user; only internal trace marker.

HARD GATES (S7.5)

Gate A: Feature enabled

  • FEATURE_S7_INVITES_ENABLED must be true

  • Rollout hash must include session_id in deterministic distribution:

    hash(session_id) % 100 < FEATURE_S7_INVITES_ROLLOUT_PERCENTAGE

Gate B: CI invariants green (mandatory)

  • If FEATURE_S7_INVITES_REQUIRE_CI_GREEN=true:

    require last CI validation status = PASS

    If unknown/unavailable: ABORT silently

Gate C: Eligibility (inherits S7.2)

  • Must meet all 6 eligibility conditions (S7.2)

  • Must not meet any of the 10 abort conditions (S7.2)

  • Must be post-content positioning only

  • Must be max 1

Gate D: Template-only selection

  • Only allow the 3 canonical templates from S7.3

  • No runtime text generation

  • No dynamic interpolation

  • No synonyms, no rewrites

Gate E: Final string validation (shared validator)

  • Must pass the S7.4 validator exactly

  • If validator errors: ABORT silently

Gate F: Observability (internal-only)

  • trace[”_s7_invite”] = {emitted: bool, reason: str, template_id: str|None, plane: str|None, rollout: int}

  • Logs may record markers but must not alter user output or introduce meta.

APPEND FORMAT (USER-VISIBLE)

If emitted, append exactly:

\n\n<INVITATION_SENTENCE>

No label, no bracket header, no “invitation:” prefix, no explanation, no “optional”.

TEMPLATES (CANONICAL, S7.3 ONLY)

Use exactly these three, unchanged:

Plane D (Clarification): This explanation can be extended to clarify related distinctions.

Plane C (Depth): This description can be expanded with additional structural detail.

Plane E (Application): This can be extended with applied usage contexts.

PLANE SELECTION SOURCE

Invitations must use the same plane selected for Contract 2 enrichment logic (or the plane selected in S5.2 logic), but invitations do NOT require enrichment to exist. Plane must be known and explicit:

  • EXPLAIN → Plane C

  • HOWTO → Plane E

  • Educational ambiguity (only if S5.2 supports it deterministically) → Plane D

    If plane is unknown: ABORT silently.

PROHIBITED INTERACTIONS

  • Do not emit invitations when Contract 1 fails or falls back.

  • Do not emit invitations when speech_act is DEFINE, VERIFY, SCRIPTURE, UNKNOWN.

  • Do not emit invitations when the response is already short-circuiting due to safety policy triggers.

  • Do not emit invitations when any other experimental feature is in an error state (fail closed).

INSTALLATION STEPS (SERVER)

  1. Create backup before changes:

    cp /app/ezra_admin/core/guest_safe_response_contract.py /app/ezra_admin/core/guest_safe_response_contract.py.bak_s7_5_$(date +%Y%m%d_%H%M%S)

  2. Add env vars to /app/ezra_admin/.env (do not overwrite unrelated lines):

    FEATURE_S7_INVITES_ENABLED=false

    FEATURE_S7_INVITES_ROLLOUT_PERCENTAGE=0

    FEATURE_S7_INVITES_REQUIRE_CI_GREEN=true

    FEATURE_S7_INVITES_REQUIRE_CANARY_FREEZE=false

  3. Implement functions (guest_safe_response_contract.py)

  • should_emit_s7_invite(trace, ctx) -> (bool, reason)

  • select_s7_template(plane) -> (template_id, sentence) or abort

  • validate_s7_invite(sentence) -> (bool, reason) using the SAME validator from S7.4

  • attach_s7_invite(response_text, sentence) -> response_text (append only)

  1. Wire into pipeline as final post-processing step:

  • After Contract 1 response is finalized (and after Contract 2 enrichment attachment decision), before returning to caller.

  • Ensure “emit nothing” is the default.

  1. Add deterministic rollout using session_id (same pattern as Contract 2 rollout).

  2. Add internal trace markers and logs:

  • [PHASE_S7.5_INVITE_CHECK]

  • [PHASE_S7.5_INVITE_EMITTED] only when emitted

VALIDATION TESTS (MUST PASS BEFORE ANY ENABLEMENT)

Run with FEATURE_S7_INVITES_ENABLED=true and ROLLOUT_PERCENTAGE=100 in a NON-PROD test session only:

Test Set A (Must NOT emit)

  • DEFINE: “What is an apple?” → no invite

  • VERIFY: “Is an apple a fruit?” → no invite

  • SCRIPTURE: any scripture query → no invite

  • UNKNOWN speech-act → no invite

  • Any response where Contract 1 not completed → no invite

Test Set B (May emit, but must remain inert)

  • EXPLAIN: “Explain photosynthesis” → optional invite appended (Plane C)

  • HOWTO: “How do I divide numbers?” → optional invite appended (Plane E)

Assertions:

  • Contract 1 text must be byte-identical between invite OFF and invite ON, except for the appended invitation line.

  • Invitation line must exactly match one canonical template.

  • No new facts introduced.

  • No “you”, no “?”, one sentence, no labels.

ROLLBACK

Immediate rollback (under 5 minutes):

  • Set FEATURE_S7_INVITES_ENABLED=false

  • Set FEATURE_S7_INVITES_ROLLOUT_PERCENTAGE=0

  • sudo systemctl restart ezra-admin.service

    This must fully restore pre-S7.5 behavior (no invitations emitted).

ROLL-OUT POLICY (DO NOT ENABLE YET)

S7.5 completes when:

  • Code is installed

  • All tests pass

  • CI invariants remain green

  • FEATURE_S7_INVITES_ENABLED remains false by default

    Enablement is a separate explicit architect directive (S7.6 rollout).

DELIVERABLES

  1. Implementation in /app/ezra_admin/core/guest_safe_response_contract.py (guardrails + wiring)

  2. Journal entries in /srv/ezra_vault/chilton/journal/daily/YYYY-MM-DD/

    • 30_actions.md (what changed)

    • 10_findings.md (validation results)

  3. Optional: /srv/ezra_vault/chilton/canon/S7_5_RUNTIME_EMISSION_GUARDRAILS.md (summary + gates + rollback)

END OF SCRIPT