Files
llm/docs/1c-extension-layer-plan.md
T

14 KiB

1C Extension Layer Plan

Status: active work plan.

This plan defines how the 1C adapter and agent must handle extensions, full 1C paths, effective reads, provenance, and safe writes.

Core Principles

The adapter has two responsibilities that must not be merged:

  • return the effective picture that the 1C runtime and Configurator see after applying active extensions;
  • keep editor provenance so every change can be routed to the correct layer: base configuration, a concrete extension, or a saved-state working copy.

Agent-facing APIs use 1C names and full paths. GUIDs, SQL table names, CAS keys, and payload offsets are storage evidence, not the everyday language of the agent.

Addressing Model

The default address format is a full semantic 1C path:

<ObjectKind>.<ObjectName>[.<Section>.<Member>...]

Examples:

Справочник.Контрагенты
Справочник.Контрагенты.Наименование
Документ.РеализацияТоваровУслуг.Товары.Номенклатура
РегистрСведений.ЦеныНоменклатуры.Измерения.Номенклатура
РегистрСведений.ЦеныНоменклатуры.Ресурсы.Цена
Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента.Товары
ОбщийМодуль.ИнтеграцияСCRM.ОтправитьКонтрагента

Short names are input conveniences only. Before analysis or writing, the agent must normalize them to a single full path or return candidate paths when the name is ambiguous.

There are three allowed address levels:

  • canonical_path: full 1C path, safe for reads and write planning;
  • context_path: shortened path valid only inside a known object, form, module, tabular section, or routine;
  • local_name: local BSL symbol or local form item name, never enough for a cross-object write by itself.

The adapter must keep metadata path resolution separate from code symbol resolution. In BSL, Номенклатура.ЕдИзмерения.Код may start from a variable, form attribute, object attribute, tabular-section column, query field, or procedure parameter. It must not be silently treated as Справочник.Номенклатура.

Layer Views

Every read API that can be affected by extensions should support these views:

  • base: only the main configuration;
  • extension: only one selected extension;
  • effective: the runtime/configurator picture after applying active extensions;
  • origin: provenance of effective members and code fragments;
  • diff: semantic differences between base and one or more extensions.

The effective view is the default for agent investigation. It is incomplete for writing unless paired with origin and write-target evidence.

Extension Provenance

For every metadata object, member, form, module, routine, command, and event handler, responses should expose:

  • canonical_path;
  • presentation and synonym when known;
  • created_in;
  • modified_by;
  • effective_owner;
  • active_extensions;
  • extension_order;
  • conflicts;
  • storage_evidence for debug/expert mode.

Extension changes must be classified semantically:

  • object added by extension;
  • base object adopted/extended by extension;
  • attribute/tabular section/form/command/event added;
  • property changed;
  • module added;
  • routine added;
  • code inserted before;
  • code inserted after;
  • code replaced;
  • code replaced with control.

For replace_with_control, the adapter must expose the controlled base fragment and report whether it still matches the current base/effective source.

Write Planning

Writes must start with a plan. The agent may read effective text, but must not write effective text directly.

The write planner must answer:

  • what full path or symbol is being changed;
  • what layer owns the current effective element;
  • which layer is the correct write target;
  • whether the target is base saved state, extension saved state, generated extension source, or read-only reference evidence;
  • which operation is allowed: add, property change, insert before, insert after, replace, replace with control, append routine, upsert routine, move form item;
  • which guards are required: sha1, controlled fragment, expected old text, syntax check, extension order, conflict scan;
  • which follow-up reads and validation steps must be run.

The first production-safe write path remains extension-first:

generate extension source
  -> validate in 1C tooling
  -> package extension
  -> load into disposable base
  -> run smoke tests
  -> produce human approval diff

Direct active configuration writes remain forbidden.

Agent Workflow

For concrete 1C tasks, the agent should follow this sequence:

  1. Parse the user request and extract likely full paths, short names, and local symbols.
  2. Resolve all metadata paths through the adapter.
  3. Read effective context for the selected objects.
  4. Read origin/layer evidence before drawing conclusions about ownership.
  5. For BSL expressions, resolve local symbols inside the concrete module, routine, form, or query context.
  6. If a change is needed, build a write plan before generating or applying a patch.
  7. Apply only through allowed saved-state, patch-workspace, or extension-source routes.
  8. Re-read effective and origin views.
  9. Run semantic diff, BSL syntax checks, saved-state checks, and extension conflict checks.
  10. Report results to the user in full 1C paths, hiding storage ids unless the user asks for expert evidence.

Work Plan

  1. Finalize the full-path contract in adapter docs and schemas.
  2. Extend the resolver model to return canonical_path, context_path, ambiguity candidates, and path-kind diagnostics.
  3. Add a code symbol resolver that works inside a selected module/routine/form context and distinguishes variables from metadata paths.
  4. Extend object, form, and module reads with consistent origin fields.
  5. Add an extension layer inventory that reports active extensions, order, adopted base objects, added objects, and conflicts.
  6. Add routine-level extension action evidence: before, after, replace, and replace with control.
  7. Add a read-only write planner that chooses base saved state, extension saved state, or generated extension source without applying changes.
  8. Wire the planner into metadata.write so writes without a resolved full-path target and layer decision are rejected.
  9. Add smoke tests for ambiguous short names, extension-added attributes, extension-overridden routines, and replace-with-control drift.
  10. Add eval cases so the agent learns to answer with full paths and to refuse unsafe direct effective-text writes.

First Implementation Slice

The first executable slice should be read-only:

  • update resolve_1c_fact.py output to include canonical path metadata;
  • add path ambiguity tests for object member paths;
  • add origin fields to module/routine reads where extension overlays already exist;
  • document a proposed metadata.write.plan shape before implementing apply behavior.

Current progress:

  • resolve_1c_fact.py returns canonical_path, path_kind, and tabular section context_path for verified object/member facts.
  • metadata.write.plan validates full 1C paths and concrete saved-state/module references without applying changes.
  • metadata.write.plan infers form/module write intent from canonical path sections such as Форма.<FormName> and ОбщийМодуль.<Name>.<Routine>.
  • metadata.write.plan can call metadata.definition.find for compact origin_lookup evidence.
  • metadata.write.plan reports ambiguous_origin_matches when a full path still resolves to multiple definitions, including same-layer ambiguity such as object member versus form member.
  • metadata.write.plan recommends base_saved_state, extension_saved_state, saved_state, blocked_unknown, or blocked_conflict from origin evidence.
  • metadata.write.plan normalizes preferred_layer and reports preferred_layer_conflict when a requested base/extension target disagrees with the origin-derived write recommendation.
  • metadata.write.plan accepts preferred_extension and reports preferred_extension_conflict when the requested extension name/GUID differs from the resolved extension owner.
  • metadata.write.plan validates module-code preconditions for replace_with_control, replace, and insert_before/insert_after before allowing even saved-state plans.
  • metadata.write.plan normalizes Russian and English operation names into stable operation_class values such as insert_before, insert_after, replace, and replace_with_control.
  • metadata.write.plan returns route.apply_payload_hint for concrete saved-state module/form routes, so an agent can carry the validated guards into metadata.module.write_apply or form write planning without inventing field names.
  • metadata.write.plan also carries selector fields inferred from canonical_path into route.apply_payload_hint, including kind, name, form, element, and routine_name when known.
  • metadata.write.plan marks selector-only module/form hints as ready_for_apply_method=false and returns next_resolution pointing to the required saved-state target resolver before apply methods can be called.
  • metadata.write blocks direct writes to effective canonical_path targets without a concrete saved-state/module route.
  • Blocked metadata.write responses now surface the plan's apply_payload_hint and next_resolution for parsed form/module paths, keeping the next safe resolver visible without allowing direct writes to the effective view.
  • When a concrete saved-state form file or module stream is later provided with that same full path, metadata.write merges missing selector fields from the plan hint into the low-level apply payload, such as form, element, and routine_name.
  • Concrete references now keep their field identity in write planning and hints: module_ref, module_id, file_name, and form_guid are not collapsed into each other.
  • Write planning rejects incompatible concrete references with concrete_reference_kind_mismatch, so a form selector cannot be used as a module route or the other way around.
  • resolve_1c_bsl_symbol.py adds the first conservative code-symbol resolver: full paths such as Справочник.Номенклатура.Артикул resolve as metadata, context-proven object-module fields resolve as metadata members, but routine parameters, local variables, and short object names stay BSL symbols until proven otherwise.
  • The live adapter now exposes the same conservative resolver as code.symbol.resolve, backed by modules.read, metadata.definition.find, and metadata.object.attributes.
  • check_1c_code_symbol_contract.py verifies the public adapter method through call_method, including that canonical_path, context_path, and safe_as_metadata_path survive public-result sanitizing.
  • modules.read now returns fallback public origin evidence from the storage table for direct module references: applied configuration, saved state, or unresolved CAS reference that requires owner resolution before write planning.
  • check_1c_module_origin_contract.py verifies that public modules.read and code.read responses keep this origin evidence visible without include_storage=true.
  • code.search items now preserve origin from modules.search, so the agent can see provenance before selecting a read_selector for code.read.
  • metadata.write.plan now accepts target.origin/origin from those prior read/search results and converts it to provided_origin_evidence, preserving layer recommendation while still requiring a concrete write route before apply.
  • metadata.resolve_overrides now exposes extension_action per routine link: known evidence is normalized to insert_before, insert_after, replace, or replace_with_control; unresolved extension routine actions are reported as unknown_extension_action so the agent does not silently treat them as a plain replace.
  • metadata.write.plan now accepts that extension_action evidence directly: known actions can infer the module operation when the user did not specify one, unknown actions block planning, and explicit operation/action mismatches are rejected before any saved-state apply route can run.
  • Multi-item extension_actions from an override chain now block write planning as extension_action_ambiguous; the agent must narrow to one extension/module action before generating a patch.
  • metadata.resolve_overrides now returns write_plan_evidence, a ready metadata.write.plan fragment carrying the routine name, object selector fields, target.extension_action, and next_resolution.params for metadata.saved_state.modules.search; saved-state module search now resolves public object_type/object_name selectors to owner GUIDs when possible. This reduces agent-side field translation while still requiring a concrete saved-state module route.
  • metadata.saved_state.modules.search now returns streams[].write_plan_target, a concrete module target with module_ref, file_name, stream_index, and expected_sha1 for the next metadata.write.plan call.
  • The OpenAPI contract now exposes the same write-plan response fields: concrete reference identity, apply payload hints, next resolution, and blocked high-level write responses.
  • metadata.write now refuses to call low-level apply methods when the corresponding read-only plan is blocked, for example replace_with_control without a control fragment.
  • Direct saved-state form/module apply methods now run the same metadata.write.plan gate before SQL apply, so low-level callers cannot bypass blocked guard checks.
  • metadata.write.plan blocks replace_with_control as control_fragment_drift when optional current-source evidence is supplied and the controlled fragment no longer matches that source.