mirror of
https://github.com/openai/codex.git
synced 2026-10-29 19:08:43 +00:00
Refresh model-visible context docs
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
co-authored by
Codex
parent
56f5f6346a
commit
24bc139c89
@@ -39,17 +39,18 @@ In the codex-rs folder where the rust code lives:
|
||||
### Model-visible context fragments
|
||||
|
||||
- Model-visible prompt context should go through the shared fragment abstractions described in `docs/model-visible-context.md`.
|
||||
- Every new model-visible fragment should implement `ModelVisibleContextFragment` and set `type Role`.
|
||||
- Every named fragment type should implement `ModelVisibleContextFragment` and set `type Role`.
|
||||
- Turn-state model-visible context assembly should produce exactly two envelopes (one developer message + one contextual-user message) via the shared envelope builders.
|
||||
- Define and register current model-visible fragment types in `codex-rs/core/src/model_visible_fragments.rs`. That registry is the single source of truth for contextual-user detection and both turn-state envelopes.
|
||||
- Contextual-user fragments should use the shared detection path on `ModelVisibleContextFragment`: prefer defining `contextual_user_markers()` when marker-based detection/wrapping is sufficient, and override `matches_contextual_user_text()` only for genuinely custom matching (for example AGENTS.md).
|
||||
- Define and register current fragment types in `codex-rs/core/src/model_visible_fragments.rs`. `REGISTERED_MODEL_VISIBLE_FRAGMENTS` is the integration point for contextual-user detection and registry-driven turn-state assembly.
|
||||
- If a fragment represents durable turn/session state that should be rebuilt correctly across resume/fork/compaction/backtracking, implement `ModelVisibleContextFragment::build(...)`.
|
||||
- If a fragment is contextual-user, it must provide stable detection: prefer `contextual_user_markers()` when fixed markers are sufficient, and override `matches_contextual_user_text()` only for genuinely custom matching (for example AGENTS.md).
|
||||
- Use the developer envelope for developer guidance. Custom override text (for example config/app-server `developer_instructions`) should use `CustomDeveloperInstructions`; system-generated developer context should use typed fragments plus the neutral `developer_*_text` helpers rather than reusing the custom override type.
|
||||
- Use the contextual-user envelope for user-role contextual state or runtime markers such as AGENTS instructions, plugin instructions, environment context, skills, and shell-command markers. Contextual-user fragments must provide stable markers so history parsing treats them as contextual state rather than user intent.
|
||||
- Use contextual-user fragments for contextual user-role state. Turn-state contextual-user fragments such as AGENTS instructions and environment context belong in the contextual-user envelope. Initial-only or runtime contextual-user fragments should still use typed fragments so history parsing treats them as contextual state rather than user intent; some are appended to the initial contextual-user envelope (for example plugin session instructions) and others are emitted as standalone messages (for example skills, shell-command records, and turn-aborted notices).
|
||||
- Use `<environment_context>` specifically for environment facts derived from `TurnContext` that may need turn-to-turn diffs (`cwd`, `shell`, optional `current_date`, optional `timezone`, optional network allow/deny domain summaries). Do not put policy text, plugin/skill listings, or other guidance into `<environment_context>`; those should use dedicated fragments.
|
||||
- Fragments derived from durable/current turn state that should update/reinject via diff across resume/fork/compaction/backtracking should implement `ModelVisibleContextFragment::build(...)` so current-state extraction, diffing, and rendering live together.
|
||||
- Runtime/session-prefix one-off fragments should leave `ModelVisibleContextFragment::build(...)` as `None` when they are not turn-state diffs.
|
||||
- Register every current fragment exactly once in `REGISTERED_MODEL_VISIBLE_FRAGMENTS` in `codex-rs/core/src/model_visible_fragments.rs`, in the rough order it should appear in model-visible context.
|
||||
- Do not hand-construct model-visible `ResponseItem::Message` payloads in new code; use fragment conversion and shared envelope builders.
|
||||
- Runtime/session-prefix fragments that are not turn-state diffs should usually leave `ModelVisibleContextFragment::build(...)` as `None`.
|
||||
- Register every current fragment exactly once in `REGISTERED_MODEL_VISIBLE_FRAGMENTS`, in the rough order it should appear in model-visible context.
|
||||
- Prefer dedicated typed fragments over plain strings. Developer-only one-off text is acceptable only when it is truly isolated, does not need contextual-user detection, and does not participate in turn-state diff reconstruction.
|
||||
- Do not hand-construct model-visible `ResponseItem::Message` payloads in new turn-state code; use fragment conversion and the shared envelope builders.
|
||||
- Do not inject raw strings directly into the initial-context or settings-update builders, and do not call fragment wrapping helpers ad hoc from new code.
|
||||
|
||||
Run `just fmt` (in `codex-rs` directory) automatically after you have finished making Rust code changes; do not ask for approval to run it. Additionally, run the tests:
|
||||
|
||||
+328
-88
@@ -1,124 +1,364 @@
|
||||
# Model-visible context fragments
|
||||
# Model-visible context
|
||||
|
||||
Codex injects model-visible context through two turn-state envelopes:
|
||||
This document describes how model-visible prompt context is represented in the
|
||||
current `codex-rs` codebase, and how to add new context without breaking
|
||||
resume, compaction, backtracking, or history parsing.
|
||||
|
||||
- the developer envelope, rendered as a single `developer` message
|
||||
- the contextual-user envelope, rendered as a single `user` message whose contents are contextual state rather than real user intent
|
||||
The key modules are:
|
||||
|
||||
Both envelopes are assembled from the single ordered fragment registry in
|
||||
[`codex-rs/core/src/model_visible_fragments.rs`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/model_visible_fragments.rs).
|
||||
Envelope builders normalize text fragment boundaries by inserting `\n\n`
|
||||
between adjacent text content items, so fragments do not run together in the
|
||||
model-visible token stream.
|
||||
- [`codex-rs/core/src/model_visible_context.rs`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/model_visible_context.rs):
|
||||
shared fragment abstractions, roles, marker helpers, and diff params
|
||||
- [`codex-rs/core/src/model_visible_fragments.rs`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/model_visible_fragments.rs):
|
||||
concrete fragment definitions, the central registry, shared contextual-user
|
||||
detection, and turn-state fragment assembly
|
||||
- [`codex-rs/core/src/context_manager/updates.rs`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/context_manager/updates.rs):
|
||||
the shared developer/contextual-user envelope builders and steady-state
|
||||
per-turn diff assembly
|
||||
- [`codex-rs/core/src/codex.rs`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/codex.rs):
|
||||
initial-context assembly and the normal runtime path that decides whether to
|
||||
inject full context or only diffs
|
||||
|
||||
## Canonical rules
|
||||
## Core model
|
||||
|
||||
1. All model-visible injected context must be represented as a typed `ModelVisibleContextFragment`.
|
||||
2. Turn-state context assembly always produces exactly two envelopes: one developer message and one contextual-user message.
|
||||
3. There is one blessed place to define and register current fragment types: [`model_visible_fragments.rs`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/model_visible_fragments.rs).
|
||||
4. Contextual-user fragments must provide stable detection so history parsing can distinguish contextual state from true user intent.
|
||||
5. Fragments derived from durable/current turn state that should survive history-mutating flows (resume/fork/compaction/backtracking) via re-diffing should implement `ModelVisibleContextFragment::build(...)`.
|
||||
6. Do not hand-construct model-visible `ResponseItem::Message` payloads in new code. Use fragment conversion (`into_message` / `into_response_input_item`) and the shared envelope builders.
|
||||
Model-visible prompt context falls into three buckets:
|
||||
|
||||
Rule 2 applies to turn-state context assembly (`build_initial_context` /
|
||||
`build_settings_update_items`). Runtime or session-prefix events may still
|
||||
inject standalone fragment messages, but those fragment types still belong in
|
||||
the central registry so rendering and contextual-user detection remain
|
||||
standardized.
|
||||
1. Turn-state fragments.
|
||||
These are derived from current durable turn/session state and are the ones
|
||||
that must survive history-mutating flows such as resume, compaction,
|
||||
backtracking, and fork by being rebuilt from current state plus an optional
|
||||
persisted baseline.
|
||||
2. Registered runtime fragments.
|
||||
These are not derived from `TurnContext` diffs, but they are still modeled
|
||||
as typed fragments because they are emitted into model-visible history and,
|
||||
for contextual-user fragments, must still be recognized during later history
|
||||
parsing.
|
||||
3. Developer-only one-off text injections.
|
||||
These are not currently represented as dedicated registered fragments. They
|
||||
are developer-role text added in a few call sites where no contextual-user
|
||||
detection or turn-state diffing is needed.
|
||||
|
||||
## Blessed path
|
||||
The single most important distinction is whether the model-visible state is:
|
||||
|
||||
When adding new model-visible context:
|
||||
- durable turn/session state that should be rebuilt from `TurnContext`
|
||||
- or a one-off event/message that is only relevant because it just happened
|
||||
|
||||
1. Define a typed fragment type in [`model_visible_fragments.rs`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/model_visible_fragments.rs).
|
||||
2. Implement `ModelVisibleContextFragment` for it.
|
||||
3. Set the fragment `type Role` to the correct developer or contextual-user role.
|
||||
4. If it is a contextual-user fragment:
|
||||
- define `contextual_user_markers()` when marker-based detection/wrapping is sufficient
|
||||
- override `matches_contextual_user_text()` only when matching is genuinely custom (for example AGENTS.md)
|
||||
5. If it is derived from current/persisted turn state and should participate in initial-context assembly and turn-to-turn diffing, implement `build(...)`.
|
||||
6. Register the fragment exactly once in `REGISTERED_MODEL_VISIBLE_FRAGMENTS`, in the rough order it should appear in model-visible context.
|
||||
That determines whether the fragment needs `build(...)`.
|
||||
|
||||
That single registration powers:
|
||||
## Two-envelope rule
|
||||
|
||||
- contextual-user history detection
|
||||
- developer-envelope turn-state assembly
|
||||
- contextual-user-envelope turn-state assembly
|
||||
Turn-state context assembly always produces exactly two envelopes:
|
||||
|
||||
This is intentionally stricter than “implement the trait somewhere.” A fragment
|
||||
definition is not integrated until it is registered.
|
||||
- one `developer` message
|
||||
- one contextual `user` message
|
||||
|
||||
## Choosing an envelope
|
||||
Those envelopes are assembled by the shared builders in
|
||||
[`updates.rs`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/context_manager/updates.rs).
|
||||
Adjacent text content items are explicitly separated with `\n\n` because, from
|
||||
the model's perspective, adjacent text `ContentItem`s inside one message are
|
||||
effectively concatenated.
|
||||
|
||||
Use the developer envelope for developer-role guidance:
|
||||
This two-envelope rule applies to turn-state context assembly:
|
||||
|
||||
- permissions / approval policy instructions
|
||||
- collaboration-mode developer guidance
|
||||
- model switch and realtime notices
|
||||
- personality guidance
|
||||
- subagent roster and subagent notifications
|
||||
- other developer-only instructions
|
||||
- [`Codex::build_initial_context(...)`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/codex.rs#L3342)
|
||||
- [`build_settings_update_items(...)`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/context_manager/updates.rs#L105)
|
||||
|
||||
Use `CustomDeveloperInstructions` only for custom developer override text (for
|
||||
example config/app-server `developer_instructions` values).
|
||||
It does not mean every model-visible message in the system is forced into those
|
||||
two envelopes. Runtime/session-prefix messages may still be emitted as separate
|
||||
messages when the event itself is what needs to be recorded, and some
|
||||
initial-only contextual/developer additions are appended to the envelopes
|
||||
outside registry-driven `build(...)` assembly.
|
||||
|
||||
For system-generated developer guidance (permissions, collaboration-mode
|
||||
wrappers, realtime notices, personality wrappers, model-switch notices), use
|
||||
typed developer fragments whose text comes from the neutral
|
||||
`developer_*_text` helpers in `codex_protocol::models`.
|
||||
## Current architecture
|
||||
|
||||
Use the contextual-user envelope for contextual state that should not count as
|
||||
real user turns:
|
||||
### 1. Shared fragment trait
|
||||
|
||||
- AGENTS / user instructions
|
||||
- environment context
|
||||
Every named fragment type implements
|
||||
[`ModelVisibleContextFragment`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/model_visible_context.rs#L180).
|
||||
|
||||
Use standalone contextual-user fragment messages for runtime contextual state or
|
||||
markers that also should not count as real user turns:
|
||||
That trait owns:
|
||||
|
||||
- plugin instructions
|
||||
- skill instructions
|
||||
- user shell command records
|
||||
- turn-aborted markers
|
||||
- `type Role`
|
||||
- `render_text()`
|
||||
- optional `build(...)` for turn-state fragments
|
||||
- optional contextual-user detection via `contextual_user_markers()` or
|
||||
`matches_contextual_user_text()`
|
||||
- standard conversions such as `into_message()` and `into_response_input_item()`
|
||||
|
||||
Contextual-user fragments must have stable detection because history parsing
|
||||
uses it to distinguish contextual state from real user intent.
|
||||
Roles are:
|
||||
|
||||
Use `<environment_context>` only for environment facts derived from turn/session
|
||||
state (`TurnContext`) that may need turn-to-turn diffing. Today that includes
|
||||
`cwd`, `shell`, optional `current_date`, optional `timezone`, and optional
|
||||
network allow/deny domain summaries. Do not put developer policy/instructions
|
||||
or plugin/skill metadata into `<environment_context>`; those belong in their
|
||||
own typed fragments.
|
||||
- `DeveloperContextRole`
|
||||
- `ContextualUserContextRole`
|
||||
|
||||
## Build semantics
|
||||
### 2. Central registry
|
||||
|
||||
`ModelVisibleContextFragment::build(...)` is the canonical hook for turn-state
|
||||
fragments.
|
||||
Current fragment types are registered exactly once in
|
||||
[`REGISTERED_MODEL_VISIBLE_FRAGMENTS`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/model_visible_fragments.rs#L123).
|
||||
|
||||
That registry is used for:
|
||||
|
||||
- contextual-user fragment detection during history parsing
|
||||
- turn-state fragment assembly for both envelopes by calling `build(...)`
|
||||
|
||||
Registration is therefore an integration step, not just bookkeeping. Defining
|
||||
the type is not enough; the fragment is not part of the system until it is
|
||||
registered.
|
||||
|
||||
### 3. Build semantics
|
||||
|
||||
[`ModelVisibleContextFragment::build(...)`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/model_visible_context.rs#L187)
|
||||
is the canonical hook for turn-state fragments.
|
||||
|
||||
It receives:
|
||||
|
||||
- the current `TurnContext`
|
||||
- an optional `reference_context_item`, which is the last persisted turn-state snapshot already represented in model-visible history
|
||||
- `TurnContextDiffParams` for shared runtime inputs such as shell rendering, previous-turn bridge state, exec-policy rendering context, and feature gating flags
|
||||
- `reference_context_item: Option<&TurnContextItem>`
|
||||
- `TurnContextDiffParams`
|
||||
|
||||
Turn-state fragments should return:
|
||||
`reference_context_item` is the persisted durable baseline already represented
|
||||
in model-visible history. A turn-state fragment should compare against that
|
||||
baseline to avoid emitting duplicate prompt state. When there is no baseline
|
||||
(`None`), the fragment should decide whether to emit full current context or
|
||||
fall back to `TurnContextDiffParams` for other relevant previous-turn/session
|
||||
state such as `previous_turn_settings`.
|
||||
|
||||
- `Some(fragment)` when current model-visible state should be injected
|
||||
- `None` when no model-visible update is needed
|
||||
Turn-state fragments return:
|
||||
|
||||
Runtime/session-prefix fragments that are not built from turn state should leave
|
||||
the default `build(...) -> None`.
|
||||
- `Some(fragment)` when model-visible state should be injected
|
||||
- `None` when the current state is already represented and no update is needed
|
||||
|
||||
## History behavior
|
||||
Fragments that are not turn-state-derived leave `build(...)` as the default
|
||||
`None`.
|
||||
|
||||
Developer fragments do not need contextual-user detection because they are
|
||||
already separable by message role.
|
||||
## Initial context vs steady-state diffs
|
||||
|
||||
Contextual-user fragments do need contextual-user detection because they share
|
||||
the `user` role with real user turns, and history parsing / truncation must
|
||||
avoid treating injected context as actual user input.
|
||||
The code intentionally treats these differently.
|
||||
|
||||
Current fragment types live in the registry. Historical wrappers that are no
|
||||
longer current fragments should stay in a tiny separate compatibility shim near
|
||||
the detection path rather than being added as fake current fragments.
|
||||
### Full initial context
|
||||
|
||||
[`Codex::build_initial_context(...)`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/codex.rs#L3342)
|
||||
always builds turn-state fragments with `reference_context_item = None`. In
|
||||
other words, it asks every turn-state fragment for the full current prompt
|
||||
state, not a diff.
|
||||
|
||||
That is the right behavior for:
|
||||
|
||||
- first real user turn in a thread
|
||||
- any path that must re-establish canonical prompt context from scratch
|
||||
|
||||
There is also
|
||||
[`build_initial_context_without_reference_context_item(...)`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/codex.rs#L3445),
|
||||
which currently delegates to the same full-context behavior and exists to make
|
||||
the “ignore any existing baseline” intent explicit in compaction rebuild paths.
|
||||
|
||||
### Steady-state turn updates
|
||||
|
||||
[`build_settings_update_items(...)`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/context_manager/updates.rs#L105)
|
||||
passes the current `reference_context_item` into the registry-driven turn-state
|
||||
builder loop, so registered turn-state fragments can emit only the minimal
|
||||
developer/contextual-user diffs for the next turn.
|
||||
|
||||
### Normal runtime path
|
||||
|
||||
[`record_context_updates_and_set_reference_context_item(...)`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/codex.rs#L3479)
|
||||
uses this rule:
|
||||
|
||||
- if there is no baseline, inject full initial context
|
||||
- otherwise inject only turn-state diffs
|
||||
|
||||
After each real user turn it persists the latest `TurnContextItem` and advances
|
||||
the in-memory baseline even if no model-visible diff message was emitted. That
|
||||
is what keeps later diffing aligned with current state.
|
||||
|
||||
## Contextual-user detection
|
||||
|
||||
Contextual-user fragments share the `user` role with real user messages, so
|
||||
history parsing must be able to distinguish:
|
||||
|
||||
- contextual state
|
||||
- true user intent
|
||||
|
||||
That is why contextual-user fragments need stable detection.
|
||||
|
||||
Preferred path:
|
||||
|
||||
- implement `contextual_user_markers()` when the fragment has stable fixed
|
||||
wrappers
|
||||
|
||||
Fallback path:
|
||||
|
||||
- override `matches_contextual_user_text()` when detection is genuinely custom
|
||||
(for example the current AGENTS.md wrapper)
|
||||
|
||||
The shared detection entrypoint is
|
||||
[`is_contextual_user_fragment(...)`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/model_visible_fragments.rs#L843).
|
||||
It first checks the current registry, then applies a very small legacy shim for
|
||||
historical user-role wrappers that were shipped previously but are no longer
|
||||
current fragment types.
|
||||
|
||||
Current legacy shim:
|
||||
|
||||
- old user-role `<subagent_notification>...</subagent_notification>` messages
|
||||
|
||||
Those legacy checks should stay bounded and local to detection. Do not create
|
||||
fake current fragment types just to recognize old persisted history.
|
||||
|
||||
## Current fragment inventory
|
||||
|
||||
### Registered turn-state developer fragments
|
||||
|
||||
These implement `build(...)` and participate in both full initial context and
|
||||
steady-state diffs:
|
||||
|
||||
- `ModelInstructionsUpdateFragment`
|
||||
- `PermissionsUpdateFragment`
|
||||
- `CustomDeveloperInstructionsUpdateFragment`
|
||||
- `CollaborationModeUpdateFragment`
|
||||
- `RealtimeUpdateFragment`
|
||||
- `PersonalityUpdateFragment`
|
||||
|
||||
### Registered runtime developer fragments
|
||||
|
||||
These are typed and registered, but not built from `TurnContext` diffs:
|
||||
|
||||
- `SubagentRosterContext`
|
||||
- `SubagentNotification`
|
||||
|
||||
### Registered turn-state contextual-user fragments
|
||||
|
||||
These implement `build(...)` and participate in both full initial context and
|
||||
steady-state diffs:
|
||||
|
||||
- `AgentsMdInstructions`
|
||||
- `EnvironmentContext`
|
||||
|
||||
### Registered runtime contextual-user fragments
|
||||
|
||||
These are typed and registered for rendering/detection, but not built from
|
||||
`TurnContext` diffs:
|
||||
|
||||
- `SkillInstructions`
|
||||
- `PluginInstructions`
|
||||
- `UserShellCommandFragment`
|
||||
- `TurnAbortedMarker`
|
||||
|
||||
`PluginInstructions` is currently appended to the initial contextual-user
|
||||
envelope during full initial-context assembly. `SkillInstructions`,
|
||||
`UserShellCommandFragment`, and `TurnAbortedMarker` are currently emitted as
|
||||
standalone contextual-user messages.
|
||||
|
||||
## Current non-registry developer text injections
|
||||
|
||||
The current codebase still has a few developer-role prompt injections that are
|
||||
not dedicated registered fragments. These are accurate descriptions of current
|
||||
behavior, not the preferred path for new work.
|
||||
|
||||
Current examples include:
|
||||
|
||||
- memory-tool initial developer instructions
|
||||
- apps guidance in the initial developer envelope
|
||||
- commit-attribution guidance in the initial developer envelope
|
||||
- explicit plugin-mention developer hints
|
||||
- a few one-off runtime developer messages such as stop-hook and hook-provided
|
||||
additional context
|
||||
|
||||
These are acceptable because they are developer-role only and do not need
|
||||
contextual-user detection or turn-state diff reconstruction. But for new
|
||||
model-visible context, prefer a dedicated typed fragment unless the message is
|
||||
truly an isolated one-off developer event.
|
||||
|
||||
## Choosing the right representation
|
||||
|
||||
### Use a registered turn-state fragment when:
|
||||
|
||||
- the context is derived from `TurnContext` / durable session state
|
||||
- resume, fork, compaction, or backtracking should be able to rebuild it
|
||||
- it belongs in one of the two turn-state envelopes
|
||||
|
||||
Examples:
|
||||
|
||||
- permissions policy
|
||||
- collaboration mode
|
||||
- realtime start/end state
|
||||
- AGENTS.md instructions
|
||||
- environment context
|
||||
|
||||
### Use a registered runtime fragment when:
|
||||
|
||||
- the context is model-visible
|
||||
- it is not derived from `TurnContext` diffs
|
||||
- it still benefits from standardized rendering and, for contextual-user
|
||||
fragments, shared detection
|
||||
|
||||
These fragments may either:
|
||||
|
||||
- be appended to an envelope in a non-diff initial-context path
|
||||
- or be emitted as standalone runtime/session-prefix messages
|
||||
|
||||
Examples:
|
||||
|
||||
- turn-aborted marker
|
||||
- user shell command record
|
||||
- skill injection
|
||||
- plugin session instructions
|
||||
- subagent roster / subagent notification
|
||||
|
||||
### Use a plain developer text wrapper only when:
|
||||
|
||||
- the message is developer-role only
|
||||
- it is a narrow one-off or initial-only addition
|
||||
- it does not need contextual-user detection
|
||||
- it does not need to participate in turn-state diff reconstruction
|
||||
|
||||
If you are tempted to use a plain `String` or `DeveloperTextFragment`, stop and
|
||||
verify that this is really just an isolated developer-only event and not new
|
||||
shared prompt state.
|
||||
|
||||
## Environment context rule
|
||||
|
||||
Use `<environment_context>` only for environment facts derived from
|
||||
`TurnContext` that may need turn-to-turn refresh semantics.
|
||||
|
||||
Current fields are:
|
||||
|
||||
- `cwd`
|
||||
- `shell`
|
||||
- optional `current_date`
|
||||
- optional `timezone`
|
||||
- optional network allow/deny summaries
|
||||
|
||||
Do not put other guidance in `<environment_context>`, especially:
|
||||
|
||||
- permissions/policy instructions
|
||||
- skills or plugins
|
||||
- AGENTS instructions
|
||||
- subagent notices
|
||||
|
||||
Those should stay in their own fragment types.
|
||||
|
||||
## Blessed path for new work
|
||||
|
||||
When adding new model-visible context:
|
||||
|
||||
1. Decide whether the model should see it at all.
|
||||
2. Decide whether it is durable turn/session state or a one-off runtime event.
|
||||
3. If it should be represented as a named fragment, define a typed fragment in
|
||||
[`model_visible_fragments.rs`](/Users/ccunningham/code/codex-worktree-tria/codex-rs/core/src/model_visible_fragments.rs).
|
||||
4. Implement `ModelVisibleContextFragment`.
|
||||
5. Set `type Role` correctly.
|
||||
6. If it is turn-state context, implement `build(...)`.
|
||||
7. If it is contextual-user, provide stable detection with
|
||||
`contextual_user_markers()` or custom `matches_contextual_user_text()`.
|
||||
8. Register it exactly once in `REGISTERED_MODEL_VISIBLE_FRAGMENTS`, in prompt
|
||||
order.
|
||||
9. Use the shared envelope builders or fragment conversions rather than
|
||||
hand-constructing model-visible `ResponseItem::Message` payloads in new
|
||||
turn-state paths.
|
||||
|
||||
Rule of thumb:
|
||||
|
||||
- “This is durable prompt state” => registered typed fragment, usually with
|
||||
`build(...)`
|
||||
- “This is a one-off contextual/runtime marker” => registered typed fragment,
|
||||
usually without `build(...)`
|
||||
- “This is an isolated developer-only text event” => plain developer text is
|
||||
sometimes acceptable, but it is the exception, not the default
|
||||
|
||||
Reference in New Issue
Block a user