Files
olp/docs/openai-spec-pin.md
T
taodengandClaude Opus 4.7 5119b427fd docs: D30 — README env vars correctness (F7) + openai-spec-pin.md v0.1 baseline (F20)
cold-audit catch from 2026-05-24 (round 3)

Round-3 P3 docs batch. Two unrelated docs items grouped per IDR cleanup
convention (D19/D20/D25 precedent).

**F7** — README Environment Variables table drift.

Pre-D30 table documented `OLP_HOME` and `OLP_LOG_LEVEL` — neither is
read by any code in the repo. The table missed `OLP_CLAUDE_BIN`,
`OLP_CODEX_BIN`, `OLP_VIBE_BIN` which the 3 provider plugins DO read
to override the path to each provider's CLI binary.

`grep -rn "process\.env\.OLP_" server.mjs lib/` returns exactly 4 reads:
- `OLP_PORT` (server.mjs:49)
- `OLP_CLAUDE_BIN` (anthropic.mjs:69)
- `OLP_CODEX_BIN` (codex.mjs:143)
- `OLP_VIBE_BIN` (mistral.mjs:240)

Fix: README env-vars table now lists exactly these 4 active vars with
their actual defaults. `OLP_HOME` + `OLP_LOG_LEVEL` moved to a
"📋 Planned (Phase 2)" callout block beneath the table, with honest
explanations linking to the actual code state (`loadFallbackConfigSync`
hardcodes the config path; `logEvent` writes unconditionally).

**F20** — Author docs/openai-spec-pin.md v0.1 baseline.

ALIGNMENT.md Authority 2 + Annual Alignment Audit § Scope both
referenced `docs/openai-spec-pin.md` as the artifact the annual audit
diffs against. Pre-D30 the file didn't exist (D20 marked it 📋 Planned).
This left the entry-surface audit without a diff baseline — v0.1 ships
with no provable "the OpenAI spec was THIS on the day OLP implemented
its entry surface" anchor.

Fix: author a 175-line minimal v0.1 baseline. Every field claim is
verified against source (openai-to-ir.mjs + ir-to-openai.mjs + server.mjs).
Structure:
- POST /v1/chat/completions: 14 supported request fields (model,
  messages + 6 message-level subfields, stream, temperature, max_tokens,
  top_p, stop, tools, tool_choice, response_format) + 11 NOT-yet-supported
  fields (n, seed, frequency_penalty, presence_penalty, logit_bias,
  logprobs, top_logprobs, user, service_tier, parallel_tool_calls,
  stream_options)
- Response shapes: chat.completion (non-stream), chat.completion.chunk
  (streaming) — verified against irResponseToOpenAINonStream and
  irChunkToOpenAISSE
- `finish_reason` enum: verified against OPENAI_FINISH_REASON_ENUM
  constant in ir-to-openai.mjs (post-D19 + D26)
- Error response shape: HTTP 4xx/5xx + `{error: {message, type}}` —
  verified against `sendError` in server.mjs
- GET /v1/models: verified against handleModels (post-D18 + D27 F15)
- Streaming SSE semantics: framing, terminator, post-D26 F19
  truncation marker

The pin also documents the v0.1 → v1.0 forward-looking expansion plan:
the "NOT yet supported" fields are explicit candidates for v1.0+
implementation via openai-to-ir.mjs amendments + ADR 0003 updates.

ALIGNMENT.md + README Implementation status table both flip the marker
from 📋 Planned to  Shipped (D30) with the 2026-05-24 timestamp.

Changes (3 files, +180 / -8):
- ALIGNMENT.md +2/-2 (2 markers updated: Authority 2 + Annual Audit)
- README.md +11/-6 (env-vars table delta + status table marker flip +
  Planned callout for OLP_HOME/OLP_LOG_LEVEL)
- docs/openai-spec-pin.md (new, 175 lines)

Tests: 400/400 unchanged — pure docs change.

Authority:
- F7 → process.env reads verified by direct grep
- F20 → OpenAI Chat Completions spec
  https://platform.openai.com/docs/api-reference/chat/create
  https://platform.openai.com/docs/api-reference/chat/streaming
  https://platform.openai.com/docs/api-reference/chat/object
  https://platform.openai.com/docs/api-reference/models/list
- F20 internal source-of-truth: openai-to-ir.mjs + ir-to-openai.mjs +
  server.mjs (all field claims traced)
- ALIGNMENT.md § Authority 2 + § Annual Alignment Audit
- CC 开发铁律 v1.6 § 10.x — Round-3 Cold Audit caught both items

Reviewer (Iron Rule v1.6 § 10.x Mode A, fresh-context opus, independent
of drafter): APPROVE. Independent verification:
- Grep confirmed exactly 4 process.env.OLP_* reads — matches new env
  vars table
- Each new var's default value verified against the plugin code
  (anthropic.mjs:69 → 'claude'; codex.mjs:143 → 'codex'; mistral.mjs:240
  → 'vibe')
- All 14 spec-pin supported request fields traced to openAIToIR line
  references (model L129, messages L45-89, stream L141, temperature
  L160, max_tokens L152, top_p L168, stop L176, tools L183, tool_choice
  L187, response_format L191)
- All 11 NOT-supported fields confirmed absent via grep
- Response shape claims (chat.completion + chat.completion.chunk +
  /v1/models) all match source code line-by-line
- ALIGNMENT.md markers — pure markup flip, no rule changes
- 400/400 tests pass

3 non-blocking suggestions noted (function_call finish_reason caveat;
README slug rendering; ADR 0003 cross-link in spec-pin) — all cosmetic,
not folded.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 16:56:01 +10:00

6.7 KiB

OpenAI Spec Pin (v0.1 baseline)

  • Date pinned: 2026-05-24 (D30)
  • Status: v0.1 baseline — annual audit per ALIGNMENT.md § Annual Alignment Audit
  • Authority: OpenAI Chat Completions API + Models API

This document is the spec-diff baseline against which OLP's annual audit will compare future OpenAI spec changes. It enumerates the specific spec sections OLP currently implements as the entry surface, verified against lib/ir/openai-to-ir.mjs and lib/ir/ir-to-openai.mjs at the time of pinning.


Endpoints implemented

POST /v1/chat/completions

Request body fields supported (translated into IR by openAIToIR in lib/ir/openai-to-ir.mjs):

Field Type Required Notes
model string required Passed through to IR; validated non-empty
messages array required Non-empty; each element translated via translateMessage
messages[i].role string required system / user / assistant / tool; deprecated function normalized to tool
messages[i].content string|null required null normalized to ''
messages[i].name string optional Passed through to IR
messages[i].tool_call_id string optional Passed through to IR
messages[i].tool_calls array optional {id, type:'function', function:{name, arguments}}
messages[i].function_call object optional Deprecated field; mapped to a single tool_calls entry
stream boolean optional Default false; true triggers SSE path
temperature number optional Range [0, 2]; passed to IR
max_tokens integer optional Must be a positive integer; passed to IR
top_p number optional Range [0, 1]; passed to IR
stop string | array optional Passed to IR as-is
tools array optional Only type:'function' tools supported; translated via translateTools
tools[i].function.name string required (in tool) Passed through
tools[i].function.description string optional Passed through if present
tools[i].function.parameters object optional Passed through if present
tool_choice 'auto'|'none'|'required'|{type:'function',function:{name}} optional Passed to IR verbatim
response_format object optional Passed to IR verbatim

Request body fields NOT yet supported (silently dropped by entry surface — not read in openAIToIR):

  • n — multiple completions; OLP is single-completion only
  • seed — deterministic sampling
  • frequency_penalty, presence_penalty
  • logit_bias
  • logprobs, top_logprobs
  • user
  • service_tier
  • parallel_tool_calls
  • stream_options

Response shape (non-streaming)object: 'chat.completion' (assembled by irResponseToOpenAINonStream in lib/ir/ir-to-openai.mjs):

{
  "id": "chatcmpl-<base64url>",
  "object": "chat.completion",
  "created": <unix-epoch-seconds>,
  "model": "<model-string-from-request>",
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "<string-or-null>",
      "tool_calls": [ ... ]
    },
    "finish_reason": "<stop|length|tool_calls|content_filter|function_call|null>"
  }],
  "usage": { ... }
}
  • usage is included only when the provider surfaces token counts on the final chunk.
  • message.tool_calls is included only when tool calls are present.
  • message.content is null when there is no text content and tool calls are present.

Response shape (streaming)object: 'chat.completion.chunk' (emitted by irChunkToOpenAISSE in lib/ir/ir-to-openai.mjs):

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":<ts>,"model":"<m>","choices":[{"index":0,"delta":{"role":"assistant","content":"..."},"finish_reason":null}]}

data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":<ts>,"model":"<m>","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: [DONE]
  • delta carries role (first chunk only), content (text chunks), or tool_calls (tool call chunks).
  • Final stop chunk has finish_reason set and empty delta.
  • usage is included in the stop chunk only when the provider surfaces token counts.
  • Stream terminator: data: [DONE]\n\n.

finish_reason enum honored (normalized by normalizeFinishReason; non-spec values normalized to 'stop'):

  • stop — natural completion
  • length — truncated at max_tokens or synthesized on truncation (D19/D16)
  • tool_calls — model stopped to emit a tool call
  • content_filter — provider-side content filter
  • function_call — deprecated; preserved for backwards compatibility
  • null — in-progress (streaming delta chunks)

Error response shape:

HTTP 4xx/5xx with body:

{ "error": { "message": "<string>", "type": "<string>" } }

No invented top-level error field on chat.completion objects (per ALIGNMENT.md Rule 2 — D12 finding). Errors surface exclusively via HTTP status codes with the above body shape.


GET /v1/models

Response shape (handleModels in server.mjs):

{ "object": "list", "data": [ ... ] }

Each entry: { "id": "<model-id>", "object": "model", "created": <ts>, "owned_by": "<provider-key>" } — no invented fields (per D27 F15). Alias entries are also surfaced as separate list members (per D27 F15 alias surfacing).


GET /health

OLP-specific endpoint (not in OpenAI spec). Returns:

{ "ok": true, "version": "<semver>", "providers": { "enabled": <n>, "available": <n> } }

Streaming SSE semantics

  • MIME: text/event-stream
  • Per-chunk framing: data: <json>\n\n
  • Terminator: data: [DONE]\n\n
  • Truncation marker: finish_reason: 'length' synthesized when the provider generator exhausts without a natural stop chunk (D26 F19 — mirrors D16 buffered-path semantics)
  • Response headers on stream: Content-Type: text/event-stream, Cache-Control: no-cache, Connection: keep-alive, X-Accel-Buffering: no plus OLP diagnostic headers

Audit method

Annual audit (target 2027-05-14): re-fetch each cited URL above, diff against the field lists above, file an ADR amendment for any newly-shipped OpenAI field or changed semantic that OLP should implement. Consult lib/ir/openai-to-ir.mjs and lib/ir/ir-to-openai.mjs as the implementation source of truth.


Scope note: v0.1 baseline

This is a minimal baseline. v1.0+ should expand coverage to include the "NOT yet supported" fields above where OLP intends to support them (via openAIToIR amendments + ADR 0003 updates).