# 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: ```text .[.
....] ``` Examples: ```text Справочник.Контрагенты Справочник.Контрагенты.Наименование Документ.РеализацияТоваровУслуг.Товары.Номенклатура РегистрСведений.ЦеныНоменклатуры.Измерения.Номенклатура РегистрСведений.ЦеныНоменклатуры.Ресурсы.Цена Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента.Товары ОбщийМодуль.ИнтеграцияС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: ```text 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 `Форма.` and `ОбщийМодуль..`. - `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.