Files
deepseek-harness/.agents/notes/implemented/architecture/2026-08-25-sparse-first-party-prompt-section-orders.md
T
Tianyi Cui 3ca9c7d489 rename code-mode to ptc (PTC mode), except session-persistent vocabulary
Rename the tool-presentation transport from code-mode to ptc everywhere
that is not written into session logs: the mode config value becomes 'ptc',
the preset directory/id becomes ptc, the demo becomes demo:ptc, the
dispatch waterfall becomes tools/ptc-dispatch-log (types PtcDispatch*), the
prompt rule becomes tools:ptc-only, source/test files become ptc.ts etc.,
and prose says PTC mode / PTC 模式. The session-persistent vocabulary
(durable events tool/code-dispatch*, logged plugin name tools-code-mode,
sub-call id segment :code:) intentionally stays and moves in the stacked
persistence PR, which is blocked until the SESSION_FORMAT_VERSION v0→v1
migration lands with it. run_code, its code parameter, CodeSdkLanguage,
CodeRunFailedError, the dsh-code-runtime family, third-party codex names,
and frozen archived notes keep their names.
2026-08-27 23:14:31 +08:00

5.6 KiB
Raw Blame History

Agent Note: Centralize sparse first-party prompt-section orders

Status: implemented

English | 中文

Problem

Repository-owned system-prompt sections declared unrelated numeric literals across more than twenty packages. The main tool sequence occupied consecutive values from 100 through 117 and then used half-step values for insertions. A later change could therefore collide with an existing section without seeing the complete allocation.

Equal orders used stable JavaScript sort behavior, which made plugin activation order the effective tie-breaker. The Cordis/workflow prompt-order fix showed that clean compositions can activate the same plugins in different orders and produce different request headers and snapshot results. Fixing one collision locally did not prevent another package from reusing that value.

The shell guidance also followed filesystem guidance even though shell commands have the broadest execution and failure semantics. A model should read the shell result obligation before the narrower instructions that route file work to dedicated tools.

Decision

@deepseek-ai/dsh-system-prompt exports FIRST_PARTY_SECTION_ORDER as the single allocation for repository-owned sections. Every first-party contributor imports its named placement instead of declaring a numeric literal. Values are unique integers, and adjacent allocated values differ by at least ten.

The allocation preserves the established first-party sequence except for two deliberate changes: Bash, or PowerShell in the Windows composition, leads per-tool guidance; and sections that shared an order receive an explicit sequence. The groups are:

Group Entries
Product opening harness:identity 1000, harness:source 900, app:web-surface 800, deployment:persona 0
Work modes plan:policy 500, team:policy 600
Invocation prelude tools:ptc-only 800, context:file-reference 900
Local tools tool:bash 1000, tool:pwsh 1010, tool:read 1100, tool:write 1200, tool:edit 1300, tool:glob 1400, tool:grep 1500, tool:jobs 1600, tool:pty 1700
Higher-level tools tool:web_search 2000, tool:web_fetch 2100, tool:lsp 2200, tool:session-query 2300, tool:goal 2400, tool:cordis 2500, tool:workflow 2600, tool:ralph 2700, continuable-subagent guidance 2800, tool:report 2900
Generated protocol tools:sdk 5000
Final-output obligations deliverable file references 9000, tool:structured_output 9900

SystemPrompt.assemble() sorts equal-order sections by code-unit section name after comparing order. This makes third-party collisions deterministic without locale-sensitive comparison. First-party contributors still receive distinct ranks so their intended sequence remains explicit rather than depending on the fallback.

Dynamic PromptContext order and tool-schema toolOrder are separate sequences and remain unchanged. A scoped deployment:persona continues to shadow the global section by name before section sorting, so it shares PERSONA_ORDER rather than consuming another placement.

Verification

The system-prompt unit suite verifies that every exported first-party value is an integer, every value is unique, adjacent values differ by at least ten, and opposite registration permutations produce the same code-unit name order for a tie. Real-composition snapshots pin the model-visible ordering change, including Bash before filesystem guidance and the explicit Cordis, workflow, Ralph, subagent, and report sequence.

Alternatives considered

Keep package-local numeric literals and review collisions manually. Rejected because a contributor cannot see the complete allocation locally, and the collision that motivated the earlier fix recurred after that fix merged.

Continue inserting fractional values. Rejected because fractions provide no durable spacing rule, obscure the semantic groups, and still permit unrelated packages to choose the same value.

Normalize only snapshot comparisons. Rejected because the runtime request header and model prompt would remain activation-order dependent while the test hid the difference.

Preserve activation order for equal ranks. Rejected because activation order is not a prompt-order decision and varies across valid compositions. Name order is deterministic for external collisions; explicit named placements carry first-party intent.

Renumber dynamic contexts and tool schemas in the same allocation. Rejected because they are independently assembled sequences. Combining them would imply cross-sequence ordering that the runtime does not perform.

Consequences

Numeric ranks are not rendered, so the renumbering alone does not change model text. Bash or PowerShell moves before other per-tool guidance, and previously tied sections acquire deterministic order; those model-visible changes update request-header snapshots and may invalidate provider prefix reuse from the first moved paragraph.

An external plugin that chose a raw number specifically to sit between old first-party values may move relative to repository sections. This repository is pre-release and provides no compatibility shim for the old allocation; extensions can select positions from the exported current allocation. Equal external ranks remain supported and deterministic by name.

The system-prompt package now knows the names and relative placement of repository features. That centralized coupling is deliberate: the registry already owns the ordering semantics, while distributed numeric literals made the same relationship implicit and uncheckable.