# 1C Agent Coding Contract This contract is the default rule set for coding agents that work through the 1C adapter. The agent calls it only through the `onec_request` MCP tool; the REST SQL adapter is MCP's private downstream transport. ## Default View - Read current code and metadata from the working saved-state layer by default. - For REST calls, use `state=working`. - For MCP calls, use `source_state=working`. - Treat saved-state objects as current programming state even when they are not activated yet. - Objects can exist only in saved-state and can later be activated or canceled. Do not hide them from the agent view. ### Empty saved-state layer An empty saved-state layer is normal before the first edit. In that case an agent still uses only public selectors and reports the adapter result; it must not obtain an active `ConfigCAS`/`Config` module reference and retry by hand. Known adapter limitation (2026-08-02): for an extension-owned object module with no prepared saved-state row, public `code.read` can return `source_missing` even though the active module is proven to exist. Treat this as an adapter defect, not as evidence that the 1C object or BSL is absent. Use a developer-owned diagnostic check to investigate it; do not expose its storage coordinates to a coding agent. ## Required adapter acceptance fixture `upo_test` must contain one isolated extension-owned `Report` with a decoded `object_module`, a unique BSL anchor, and no shared business role. This fixture is created and maintained by a human in Configurator; the SQL-only adapter must not fabricate it. It is the required target for the public acceptance sequence: ```text code.read(ref, extension, module_ordinal=1) → code.write(old, new, apply_and_rollback) → code.search verifies new text → rollback and saved-state cleanup ``` The request must contain no `layer`, table, file name, module ref, payload hash, or stream index. Until the fixture exists, unit tests prove routing only; they do not prove a live extension Report write. ### Verified base-module smoke On 2026-08-02 the public sequence was verified on `upo_test` against base `Report.АвтоматическиеСкидки`, `module_ordinal=1`: a unique comment replacement completed in about 25 seconds with `verified_and_rolled_back`. The adapter auto-prepared `ConfigSave`, read back the write, rolled back the BSL change, then removed the exact rows it had prepared. The public result contains the opaque `prepare_receipt_id` and `prepare_cleanup`; the final saved-state status was `empty`. This validates the base route only, not the extension Report route. Live check on 2026-08-02 found 19 extensions but zero extension-owned Reports in `upo_test`; therefore the required extension acceptance fixture is currently missing and the extension write branch remains unaccepted. Live check on 2026-08-13 found an extension BSL stream for `Report.УОП_ИнвентаризационнаяОпись`, but its `role_status=unconfirmed`. That is read-only evidence, not an acceptance fixture: do not write through an ordinal, storage reference, or guessed Configurator role. A human must add or identify one extension Report with a decoded `object_module` before the live extension `apply_and_rollback` test can run. ## Compare Views - Use `state=both` or `source_state=all` only when the task needs a comparison with activated runtime state. - Show the effective working text first. - Mark comparison details explicitly: - `saved_state`: saved and not activated; - `active`: activated runtime state; - `text_source`: which layer produced the returned text; - `comparison.differs`: whether both layers exist and differ. ## Read Workflow Use public names and selectors: 1. `extension.objects.find` with `state=working` to find extension objects. 2. `code.search` with `state=working` to find routines or fragments. 3. `code.read` with `state=working` to read the module or routine. 4. `code.read` with `state=both` only for an explicit saved-vs-active check. For a report form, keep the descriptions separate: 1. `metadata.object.forms(ref=Report., source_state=working)` lists the report's form references. 2. `metadata.object.form.details` with that same public report ref and the returned form name reads the form description (attributes, parameters, commands, items, and the form module). 3. `metadata.form.decode(view=structure)` is an optional compact static projection. It must retain `unresolved` parent/child links where no SQL codec has proved them. A form command does not have its own module. Its handler is a named routine in the form module only when the decoder returns an evidenced command link. Use the `read_selector.selector_token` returned by discovery with the method declared in that selector. Do not copy GUIDs, module refs, table names, or file names into a follow-up request. A module ordinal, display name, or storage-derived role is not a Configurator-tree path. If a result has `role_status=unconfirmed` or `configurator_path_status=unconfirmed`, the agent must not name, write, or infer its tree owner; report the missing decoder evidence instead. When checking object commands, call `metadata.object.commands` with the same public `ref`/`kind`+`name` and `extension` selector. The adapter resolves the extension name and reads its active metadata itself. A prior `not_found` from a route that did not carry the extension context is not evidence that the report has no commands. Conversely, a BSL stream suffix alone is never evidence of a command or of its module path. Agents should ask for and report object names, routine names, and code text. They should not ask users for SQL tables, storage file names, stream indexes, or saved-state write flags during normal coding work. ## Write Workflow All normal BSL writes go through `code.write`. Supported public edit shapes: - replace a whole module with `module_text`, `full_text`, or `code`; - replace one procedure or function with `routine_name` and `routine_text`; - replace one unique fragment with `old` and `new`; when `routine_name` is supplied, the adapter scopes the replacement to that routine. `code.write` saves into saved-state automatically. A coding agent should simply say "save this code" and send the desired code text. It must not ask whether SQL saved-state apply flags are allowed. For extension object modules, preparation maps the active payload route to its canonical saved-state filename internally. A public `code.write` therefore continues with `extension`, `ref`, module role, and the proven replacement only; it must never ask the caller to supply the canonical filename or stream. Every successful `code.write` response must show: - `write_mode.target=saved_state`; - `write_mode.activation_state=not_activated`; - `write_mode.production_apply=false`. ### Repository-controlled extension writes For a repository-controlled extension, use the public sequence below and stop when it asks for a human Configurator action: ```text code.search(extension, ref, old fragment) → repository.lock.plan(extension, ref) → repository.lock.request → human captures the exact object in Configurator → repository.lock.confirm → code.write(extension, ref, module_ordinal, old, new, repository_lock) → code.search readback ``` The lock plan for `upo / фс_Отчеты1 / Report.фс_ПродовольственнаяКорзина` resolves exactly one object: `Отчет.фс_ПродовольственнаяКорзина`, in extension layer `extension:8e02accd-8a34-11f1-8294-005056b0d483`. SQL cannot prove a native Configurator capture; only a human confirmation can continue this route. `metadata.write.preflight` currently plans canonical high-level `metadata.write` targets and may return `needs_route` for this compatibility `code.write` shape before saved-state preparation. This is not permission to use its low-level payload hint. Use `code.write(mode=plan)` instead: a first extension edit may return public `needs_prepare`, which means to confirm the repository lock and reissue the same public request in an apply mode. Keep using the public `code.write` route; report any different route failure to adapter developers. If it returns `extension_saved_state_prepare_protocol_unproven`, do not retry or supply technical coordinates. The adapter has not yet proven the exact saved-state preparation codec for this extension layout; report it for adapter development. Do not infer that the extension was not saved in Configurator. ## Hidden Storage Details The form module container marker `///----` is adapter-owned storage syntax. Public `code.read` and `code.search` responses must not expose it as BSL. Full-module writes must preserve the marker internally when the saved form payload requires it. Low-level methods such as `metadata.module.write_apply`, `metadata.write`, SQL tables, stream refs, and saved-state apply flags are diagnostic tools. They are not the default programming interface for agents. ## Agent Response Shape When reporting a working saved-state result to a user, prefer concise wording: ```text В working/save вижу формы: t_Форма tt_Форма3 ФормаЭлемента Код читается из saved_state, еще не активирован. ``` If the user asks to compare active and saved state: ```text Working/save: найдено, источник saved_state, не активировано. Active: не найдено. Эффективный код для программирования сейчас берется из saved_state. ```