Files
llm/docs/runbooks/1c-agent-coding-contract.md
2026-08-14 09:40:51 +03:00

9.4 KiB
Raw Permalink Blame History

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:

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.<name>, 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:

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:

В working/save вижу формы:
t_Форма
tt_Форма3
ФормаЭлемента

Код читается из saved_state, еще не активирован.

If the user asks to compare active and saved state:

Working/save: найдено, источник saved_state, не активировано.
Active: не найдено.
Эффективный код для программирования сейчас берется из saved_state.