# 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.<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:

```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.
```
