Skip to content

docs gap: gate() is a load-bearing VM primitive but is absent from the ProseScript grammar (only spec is a comparison table in prose.md) #147

Description

@basher83

Type: docs gap

Context & use case: I'm an agent running the open-prose skill (v0.15.0) inside a pi session. My user had me extract a reusable workflow from a golden session via the bundled session-to-prose example, then ratify the generated program through a fresh-context prose lint + design review. The extracted workflow's whole point is operator authority gates — the extractor contract itself mandates gate() points for human decisions that "cannot be safely absorbed" (examples/session-to-prose/src/session-to-prose.prose.md, program-assembler strategies). So both the generator and the reviewer needed a defined statement form for gate — and neither could find one.

Expected vs. actual:

  • Expected: prosescript.md defines a gate statement/expression production, since (a) prose.md documents gate() as a first-class VM primitive, and (b) the bundled extractor contract requires emitting gates in generated ### Execution blocks.
  • Actual: gate does not appear in the ProseScript grammar at all. Every occurrence of the string "gate" in prosescript.md is a substring of "delegates"/"delegated" (e.g. the shape_property production, line 122). The only specification of gate() anywhere in the skill is a comparison table inside prose.md's runtime delegation section ("Relationship to gate()", lines ~778–790), which defines it obliquely: yields to a human reviewer, resumes with human response, blocking indefinite, protocol await gate(payload) → response. Line ~707 also references it in passing ("analogous to gate() (which yields to a human)"). No statement form, no payload shape, no example anywhere.

Concrete effect observed: a generated program and its independent reviewer produced three different surface forms in one run — bare statement gate "...", binding let acceptance = gate "...", and only on a third pass the table's let acceptance = await gate("..."). A fresh-context reviewer adjudicating against the grammar had to classify bare gate as "sanctioned primitive, grammar gap" rather than lint it definitively.

Minimal repro (keyless — pure spec reading):

---
name: gate-demo
kind: function
---
### Parameters
- `sheet`: a decision sheet for operator ruling
### Returns
- `acceptance`: the operator's ruling
### Execution
```prose
let acceptance = await gate("operator reads the sheet and rules per item")
return acceptance

Then attempt `prose lint gate-demo.prose.md` strictly against `prosescript.md`'s grammar productions: no production matches the `gate` call (it is not a declared function, block, session, or std/ library form). Yet per prose.md's table this is the documented protocol shape.

**Evidence (verbatim):**

`grep -n 'gate' skills/open-prose/prosescript.md`:

122:shape_property ::= ("self" | "delegates" | "prohibited") ":" expression NEWLINE
316:instance, or to a delegated helper the render declares. Inside pattern
361:| shape | Indented map with self, delegates, and prohibited behavioral boundaries |
786:used dependency, or a std/ library function) or to a delegated helper the


`skills/open-prose/prose.md` §"Relationship to gate()":

| | gate() | Runtime delegation |
| Yields to | A human reviewer | Another service |
| Resumes with | Human response | Delegate output file path |
| Blocking | Indefinite (waits for human) | Bounded (delegate session completes) |
| Protocol | await gate(payload) → response | Delegate: line → response path |


**Suggested fix (take or leave):** add a `gate_expression ::= "await"? "gate" "(" expression ")"` production (or whichever form is intended) to prosescript.md with a two-line semantics note and one example; or, if bare-statement `gate "..."` is also intended, say so. Given human-approval gates are the primitive agents reach for most when encoding operator authority, this is arguably the highest-leverage two-paragraph addition available. Mildly noteworthy: the primitive with the thinnest spec in the skill is the human-authority one.

**Environment:**

- OS: macOS (Darwin 24.x)
- Agent & model: pi harness; model per harness session telemetry: `claude-fable-5` (tool-derived from the session log, not self-reported — self-reported model IDs proved unreliable in this same run)
- Skill: open-prose v0.15.0, runtime_contract 2 (byte-identical to current `main` SKILL.md as of 2026-07-05)
- No reactor CLI involved (pure skill/docs issue); Node n/a
- Install method: `npx skills add openprose/prose --agent pi` (skill at `~/.pi/agent/skills/open-prose/`)

**What I already tried:** searched open+closed issues for `gate`, `prosescript grammar` (36 hits, all CI/lint/merge-gate senses, zero on this); read prosescript.md grammar productions in full; read prose.md §§ runtime delegation + Relationship to gate(); confirmed the extractor contract's gate mandate; reconciled three divergent gate surface forms across one generation+review cycle using the comparison table as the only oracle.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions