add-element and add-group-with-fields built their baseline form with an
InputField whose DataPath pointed to "Поле1", but "Поле1" was never
declared as a form attribute. runner.mjs snapshot diffing accepted the
output, but verify-snapshots caught the real XDTO error at load time:
"Неверный путь к данным: Поле1".
Add the missing attribute to both preRun form-compile inputs and
regenerate snapshots (the new attribute takes id=5, so form-edit's added
"Поле2" now lands at id=6).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KNOWN_INVALID_TYPES (FormDataStructure, FormDataCollection, FormDataTree,
etc.) was checked but only produced a Write-Warning/print warning — the
script still emitted the bad <v8:Type> into Form.xml, which XDTO later
rejected with a cryptic load-time error. Turn the warning into a hard
throw so misuse is caught at compile time with the correct hint.
Reveals two broken test cases that shipped invalid forms:
- form-compile/catalog-form: main attribute was FormDataStructure, fixed
to CatalogObject.Товары (what ERP's reference catalog forms actually
use with the cfg: prefix).
- form-info/overview: preRun form-compile used the same wrong type, fixed
the same way; snapshot regenerated.
Bumps form-compile to v1.4 on both runtimes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two harness gaps that masked real issues and leaked stray files:
1. Case-level `setup: "fixture:<name>"` was ignored — runner.mjs handled
it, verify-snapshots did not. skd-edit/add-drilldown silently failed
with "File not found: Template.xml" because the fixture never reached
workDir. Added Step 0 fixture copy mirroring runner.mjs behavior.
2. `skillConfig.cwd === "workDir"` was ignored — main skill always ran
with cwd=REPO_ROOT. mxl-compile cases pass relative -OutputPath
"Template.xml", which landed in the repo root on every run. Plumb cwd
through execSkill and set mainCwd from skillConfig.cwd.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cf-edit add-childObject was a low-level XML-manipulation operation
with no file-existence validation — callers could register a reference
to any Type.Name in Configuration.xml's ChildObjects without the
underlying file existing on disk. Platform then refused to load:
"Файл объекта не существует".
The 4 failing tests (add-objects, remove-object, add-default-role,
set-default-roles) all used this operation with fake references in
either main input or preRun, and had no way to pass verify-snapshots
because the cf-init-ed config had no actual object files.
User observation: this is the tests being wrong, not the skill.
meta-compile/role-compile/subsystem-compile already auto-register
every new object in Configuration.xml as part of their normal flow
(meta-compile.ps1:2949-3068, role-compile.ps1:667-747,
subsystem-compile.ps1:430-506). Nobody should be calling cf-edit
add-childObject to create a new object — they should be calling the
profile skill. cf-edit add-childObject is only for rare recovery
scenarios: rolled-back Configuration.xml with intact object files,
re-import from DB dump that clobbered the root but left srcfiles.
Changes:
1. cf-edit.ps1/py: Do-AddChildObject now checks that the target file
exists at {ConfigDir}/{PluralDir}/{Name}.xml before registering.
On miss, exits 1 with a message that names the expected path and
points the user at the right skill (/meta-compile, /role-compile,
or /subsystem-compile depending on type). TYPE_TO_DIR mapping for
all 44 metadata types covers irregular plurals (FilterCriteria,
BusinessProcesses, ChartsOfAccounts, ChartsOfCharacteristicTypes,
ChartsOfCalculationTypes).
2. Tests: 4 existing cases rewritten to build realistic fixtures via
meta-compile/role-compile preRun (both skills auto-register, so
the resulting Configuration.xml already references the preRun
objects). add-objects now exercises the round-trip recovery
scenario: meta-compile creates Catalog.Товары and Document.ПриходТоваров
(auto-registered) → cf-edit remove-childObject un-registers both
(files remain) → main run re-registers via add-childObject. This
tests exactly the rollback-recovery use case the operation exists for.
3. New add-missing-errors case: negative test with expectError:
"Object file not found". Verifies the new hard-error path.
4. verify-snapshots.mjs: added symmetric expectError handling (runner.mjs
already had it at line 514). If caseData.expectError is set,
expect skill to fail; check stderr substring match; skip db-load
and mark passed. Without this, negative tests would go red in
verify-snapshots even though runner.mjs accepts them.
5. SKILL.md / reference.md: documented the new constraint and the
redirection to profile skills. Kept mention of legitimate use case
(rollback recovery).
Bumped cf-edit.ps1/py v1.0→v1.1.
Verification:
- runner --filter cf-edit (PS1): 2/6 → 7/7 (6 positive + 1 negative)
- runner --filter cf-edit --runtime python: 7/7 (dual-port clean)
- verify-snapshots --skill cf-edit: 2/6 → 7/7
With this landed P3 from debug/snapshot-verify/NEXT-STEPS.md is closed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The bottom-up flow (compile child with -Parent pointing at parent's
XML — skill creates the real child file AND registers it in parent's
ChildObjects) has been the documented canonical way to build nested
subsystems since forever. It's in SKILL.md Примеры:58 and implemented
in subsystem-compile.ps1:430-506. But zero test cases exercised it —
all 7 pre-existing cases used the top-down `children: [...]` shortcut
that aa93031 made honest with stubs.
Two problems with the status quo:
1. A model reading SKILL.md saw `"children": ["ДочерняяА", "ДочерняяБ"]`
right in the main JSON-definition example and took it as the
canonical way to create nested structure. It's a trap — the
shortcut creates placeholder stubs with empty Synonym/Content that
the model almost never actually wants. The natural flow (one
subsystem-compile call per real subsystem) wasn't visible where
the model looks first.
2. The canonical flow had no test safety net — nothing caught regressions
in the register-in-parent code path (lines 430-506).
Fix, minimal surface:
- SKILL.md: remove `"children": [...]` from the JSON-definition example.
Leave the `-Parent` example in the Примеры section (already there).
The children field stays fully supported in the scripts (aa93031 stub
behavior unchanged) for legacy JSON — just not advertised.
- New test case `nested-parent.json`: preRun compiles "Продажи" parent,
main run compiles "Настройки" child with `-Parent Subsystems/Продажи.xml`.
Verifies the real bottom-up flow: snapshot shows full child file with
real Synonym/Explanation AND parent's `<ChildObjects>` updated to
reference the child. verify-snapshots confirms platform accepts it.
- Runner plumbing: `_skill.json` gains `{ "flag": "-Parent", "from":
"workPath", "field": "parent", "optional": true }`. Required extending
both `tests/skills/runner.mjs` and `tests/skills/verify-snapshots.mjs`
(they each have their own copy of buildArgs) to support `optional: true`
on workPath mappings — otherwise existing cases without params.parent
would get the flag pushed with an empty value.
Verification:
- runner --filter subsystem-compile (PS1): 8/8 (was 7/7 +1)
- runner --filter subsystem-compile --runtime python: 8/8 (dual-port clean)
- verify-snapshots --skill subsystem-compile: 8/8
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Do-AddChild / do_add_child added `<Subsystem>Name</Subsystem>` to the
parent's `<ChildObjects>`, but never wrote the corresponding
`Subsystems/{Parent}/Subsystems/{Name}.xml` file. Same silent-drop
pattern that bit subsystem-compile (aa93031): platform used to swallow
the missing-file reference, `-StrictLog` now surfaces it as "Файл
объекта не существует" and fails add-child on load.
Both ports now mirror the subsystem-compile fix:
- Write-ChildSubsystemStub / write_child_subsystem_stub helpers
duplicated from subsystem-compile (per memory rule "skills are
autonomous, duplication acceptable")
- format_version read from loaded XmlDoc root (no need to walk up
to Configuration.xml — we already have the parent XML in memory)
- Stub creation guarded by Test-Path / os.path.exists so a pre-existing
real child file is never clobbered
Bumped subsystem-edit.ps1 v1.1→v1.2 and subsystem-edit.py v1.1→v1.2.
Verification:
- verify-snapshots --skill subsystem-edit: 3/4 → 4/4
- runner --filter subsystem-edit (PS1): 4/4
- runner --filter subsystem-edit --runtime python: 4/4 (dual-port drift clean)
With this landed P1 from debug/snapshot-verify/NEXT-STEPS.md is fully
closed: subsystem-compile 7/7, subsystem-edit 4/4, interface-edit 4/4,
role-compile 8/8, meta-compile 30/30.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a subsystem definition includes `children: [...]`, the parent XML
was emitted with `<ChildObjects><Subsystem>Name</Subsystem></ChildObjects>`
refs, but the referenced `Subsystems/{Parent}/Subsystems/{Child}.xml`
files were never created. Before 96d1dea (-StrictLog) the platform
silently dropped the refs on load (exit 0), so verify-snapshots showed
these cases green. With the new strict log parsing, `full` and
`with-children` started failing on "Файл объекта не существует".
Both PS1 and PY ports now emit a minimal valid child subsystem stub
(full MetaDataObject, empty Synonym/Content/ChildObjects) via new
Write-ChildSubsystemStub / write_child_subsystem_stub helpers. Stub
creation is guarded by Test-Path / os.path.exists, so a subsequent
compile of the same child via -Parent does not get clobbered, and
re-running the parent compile is idempotent. Дубли в children[]
дедуплицируются через seen-set.
Also removed the "Что генерируется" section from SKILL.md — filesystem
layout is covered by the OutputDir param + [OK] stdout lines; the
section was noise for model consumers.
Bumped subsystem-compile.ps1 v1.4→v1.5 and subsystem-compile.py
v1.3→v1.5 (PY caught up with PS1 version pin).
Verification:
- verify-snapshots --skill subsystem-compile: 5/7 → 7/7
- runner --filter subsystem-compile (PS1): 7/7
- runner --filter subsystem-compile --runtime python: 7/7 (dual-port drift clean)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Journal column references require the referenced document attribute to
actually exist at load time. Previously the test DSL relied on the
verify-snapshots stub mechanism, which creates minimal Document stubs
without the specific attributes the column refs point to → load failed
with "Неизвестный объект метаданных - Document.ПриходнаяНакладная.Attribute.Склад".
This was listed as D5 in the 2026-04-05 FINDINGS log ("low priority,
complex to implement").
Now the test case declares preRun steps that create both documents
with the exact attributes its journal columns reference (Склад on one,
Контрагент on both). Column "Контрагент" gained explicit references
(was a shorthand string before) because the platform rejects journal
columns without at least one reference at load time.
Regenerated the snapshot (gained Documents/ subtree from preRun output).
verify-snapshots --skill meta-compile is now 30/30 green with -StrictLog.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Custom attributes on AccumulationRegister, AccountingRegister and
CalculationRegister do NOT support FillFromFillingValue, FillValue or
DataHistory — platform logs "Неверное свойство объекта метаданных" and
silently drops them. InformationRegister DOES support these properties
(verified against erp_8.3.24 dump for both variants).
Split the single "register" Emit-Attribute context into:
- register-info → emits the three properties (InformationRegister)
- register-other → skips them (Accum/Acc/Calc)
Chart* context already handled by 3ba6072 remains as-is. Extended the
exclusion list in Emit-Attribute to cover register-other symmetrically
for FillFromFillingValue, FillValue and DataHistory.
Updated snapshots:
- accounting-register: removed the 3 bad lines on Содержание attribute
- accumulation-register/calculation-register: added test attributes
to exercise the register-other path and regenerate snapshots cleanly
Closes the silent-rejection class #4 from upload/form-baseline/gotchas.md,
now caught by verify-snapshots -StrictLog on the E2E platform load.
Bumped meta-compile.ps1 + .py to v1.8.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Platform writes load-time property/type/enum rejections ("Неверное
свойство объекта метаданных", "Неизвестное имя типа" и т.п.) into the
/Out log but still exits with code 0, silently dropping the offending
metadata. db-load-xml now parses the log for these patterns and prints
a yellow "[warning] N rejection(s)" block to stdout so users (and the
model) can see them immediately.
Exit code still mirrors the platform by default — we don't second-guess
its verdict. With the new -StrictLog switch, rejection patterns are
elevated to exit code 1, which is the mode verify-snapshots.mjs uses
for honest E2E verdicts. All three db-load-xml call sites in the
verifier (main config, CFE base, CFE extension) now pass -StrictLog.
Found while investigating upload/form-baseline/gotchas.md #4 where AR
attribute emission was wrong but verify-snapshots showed green because
the old exit-code-only check missed the silent drops.
Bumped db-load-xml.ps1 + .py to v1.3.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix-pack from skills-improvements-v4 feedback addressing 6 issues found
during real-world ФСД report development.
skd-compile (v1.10 → v1.11):
- @autoDates: emit canonical БСП pattern for ДатаНачала/ДатаОкончания —
with title, useRestriction=true, value 0001-01-01T00:00:00, expression.
Removed availableAsField=false so БСП creates two separate Start/End
fields in the quick settings panel (was rendering as a single picker).
- StandardPeriod value: always emit v8:startDate/v8:endDate to match how
1C Designer saves the schema (avoids spurious diff on first re-save).
- parameter shorthand: support [Title] syntax mirroring add-field.
skd-edit (v1.9 → v1.10):
- modify-filter / modify-dataParameter: preserve <use> when @off/@on not
explicitly set (was silently stripping <use>false</use>). Tristate
parser: None=don't touch, False=@off, True=@on.
- modify-parameter: support [Title] for setting/replacing <title>.
- rename-parameter: new operation "OldName => NewName" — atomically
renames parameter, updates &Name references in expressions of other
parameters (full identifier match only), and dcscor:parameter entries
in dataParameters of all variants. Query text is not touched.
- reorder-parameters: new operation "Name1, Name2, ..." — partial list,
named params go first in given order, rest preserve original order.
- StandardPeriod value: same v8:startDate/v8:endDate fix as compile.
Tests: 4 new test cases (rename-parameter, reorder-parameters,
modify-parameter-title, modify-dataParameter-preserves-use).
48/48 passing on both PowerShell and Python runtimes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Default structure item type to 'group' when omitted; accept groupFields as alias for groupBy
- Parse string shorthand items inside OrGroup/AndGroup/NotGroup filter recursion
- Accept useRestriction key (object form { field: true }) alongside restrict array
- Deduplicate SelectedItemAuto in skd-edit add-selection
- Update SKILL.md with object structure and useRestriction docs
- Add test cases for all 4 fixes
skd-compile v1.9→v1.10, skd-edit v1.8→v1.9
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds DetailsAreaTemplateParameter + Расшифровка appearance binding
to all named templates for each specified resource. Comma-separated
value list, idempotent, nesting-aware template scan.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously #noFilter/#noOrder/#noGroup flags were included verbatim in
<expression> instead of generating <useRestriction>. Now parsed and
handled identically to add-field.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The vertical merge flag (ОбъединятьПоВертикали) was incorrectly placed on
both the source cell (with content) and continuation cells ("|"). 1C only
expects it on continuation cells. Removed startsVMerge logic from both
PS1 and PY scripts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix 3 bugs in modify-parameter: (1) first availableValue rendered as raw
text when combined with other kv pairs in same batch entry, (2) presentation
values with spaces truncated by \S+ regex, (3) denyIncompleteValues/use
inserted without line breaks. Root cause: if/else on rest.startsWith
missed availableValue when preceded by other keys. Also fix namespace-aware
element lookup using LocalName/local_name instead of SelectSingleNode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add ">" cell syntax for horizontal merge (ОбъединятьПоГоризонтали),
analogous to "|" for vertical merge. Enables two-level headers with
colspan in DCS templates. Also fix PY decimal formatting (30.0 → 30).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes
attributes don't support FillFromFillingValue, FillValue, DataHistory
properties — platform rejects them with "Неверное свойство объекта
метаданных". Add "chart" context to Emit-Attribute to skip these.
Found via platform snapshot verification (Finding A1).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix test DSLs that used ExternalDataProcessorObject (EPF type) for
DataProcessors inside configurations. Also fix: chart-of-accounts
(remove maxExtDimensionCount without ПВХТ), calculation-register
(remove actionPeriod without infrastructure), document-multiple-tabparts
(remove registerRecords referencing non-existent register),
role-compile/explicit-rights (add dimensions to empty InformationRegister).
Regenerated all affected snapshots.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Detect config vs EPF context by walking up from FormPath looking for
Configuration.xml. ExternalDataProcessorObject/ExternalReportObject are
valid in EPF/ERF but cause XDTO exception in configuration context.
- EPF forms: no warning (ExternalDataProcessorObject is correct)
- Config forms: ERROR with hint to use DataProcessorObject/ReportObject
- Fix test DSLs: compiled-form, table-form used wrong External* type
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Runs each test case through the full pipeline: cf-init → stubs → preRun →
skill script → cf-edit → db-create → LoadConfigFromFiles → UpdateDBCfg.
Handles typed-input, args-only, standalone (SKD/MXL), and EPF skills.
Results: 118/145 pass, findings documented in debug/snapshot-verify/.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
form-compile now warns when model uses runtime types like
FormDataStructure that don't exist in XML schema. Expanded cfg:
regex to cover all 25 known prefixes.
form-validate adds Check 12 — validates all <v8:Type> values:
ERROR for known-invalid types, WARN for unrecognized bare types,
pass-through for unknown namespaced types (future-proof).
Updated SKILL.md with full type reference and invalid type warning.
Updated docs/1c-form-spec.md with missing type groups.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Snapshots for subsystem-info and interface-validate still had
Catalogs.Товары from before normalization was added.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All operations (hide, show, place, order) now auto-normalize
the first segment of command names — e.g. Catalogs.X → Catalog.X,
Справочник.X → Catalog.X.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
subsystem-compile and subsystem-edit now auto-normalize content type
prefixes (Catalogs→Catalog, Справочник→Catalog, Справочники→Catalog).
subsystem-validate detects plural forms as errors in check #6.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Addresses user feedback: set-query is all-or-nothing, and editing XML
directly is fragile due to escaping. patch-query allows targeted string
replacement via "old => new" shorthand, with batch mode support.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Now that ExtendedPresentation and InterfaceCompatibilityMode bugs are fixed,
platform integration tests can include full form generation:
- platform-config: form-add + form-compile for Catalog and Document forms
- platform-epf: epf-add-form + form-compile with elements/attributes/commands
- platform-cfe: form-add + form-compile for borrowed Catalog form
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- form-add v1.2: ExtendedPresentation only for DataProcessor/Report/External* forms
(Catalogs, Documents, Registers etc. don't have this property — platform rejects it)
- cf-init v1.1: InterfaceCompatibilityMode Taxi → TaxiEnableVersion8_2
(matches all real configs: acc 8.3.20/24/27, erp 8.3.24)
- cfe-init v1.1: read InterfaceCompatibilityMode from -ConfigPath base config
(analogous to existing CompatibilityMode auto-detection)
- Remove workaround in platform-cfe integration test (cf-edit modify-property)
- Update 162 snapshot Configuration.xml + 7 form metadata snapshots
Tests: 301/301 passed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- runner.mjs v0.4: --with-validation flag runs validators on real output
- postValidate config in 20 _skill.json files (maps skill → validator)
- validatePath in ~100 positive test cases
- skipValidation for 5 cross-reference cases (isolated workspace limitation)
- Integration tests: build-config (19 steps), build-epf (6), build-cfe (4)
- base-config cache from build-config for downstream tests
- Fix chart-of-calculation-types test data (DependenceOnCalculationTypes)
- 285/285 unit + 3/3 integration, all green with validation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- OutputDir now accepts config root dir — creates Roles/ subdirectory
- Back-compat: if OutputDir ends with "Roles", uses it as-is
- Configuration.xml lookup adjusted accordingly
- Updated SKILL.md, PS1, PY scripts (v1.3)
- Updated test cases and snapshots for new Roles/ path
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Script logic fixes (PY mirroring PS1):
- skd-compile: fix (?i) regex flag placement for Python 3.11+
- mxl-compile: handle list-of-lists row format (PS1 silently ignores)
- subsystem-compile: add "objects" → "content" synonym alias
- role-compile: add "rights" → "objects" synonym alias
- meta-compile: sort HTTP/Web service method/operation iteration
- form-edit: insert ChildItems after Events/AutoCommandBar (not at end)
- mxl-compile: sort colWidthMap iteration in both PS1 and PY for
deterministic format indices
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Skill fixes (all ps1+py, version bumped to v1.1):
- role-compile: accept "rights" as synonym for "objects"
- subsystem-compile: accept "objects" as synonym for "content"
- form-add: resolve directory path to .xml (like meta-validate)
- form-info: resolve directory path to Ext/Form.xml (like form-validate)
- mxl-compile: support absolute OutputPath (IsPathRooted check)
- meta-remove: exit 1 when object not found; v1.1
- cfe-patch-method: accept plural type names (Catalogs → Catalog)
Test fixes:
- basic-role.json: use canonical "objects" key
- basic.json (subsystem): use canonical "content" key
- catalog-form.json: fix outdated DSL format
- New synonym test cases for role-compile and subsystem-compile
- error-not-found.json: expect error (exit 1)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add parallel test execution with worker pool (default: CPU count).
New --concurrency N option (--concurrency 1 for sequential).
Pre-warm shared fixtures before parallel run.
Skip snapshot update/compare for external (read-only) workspaces —
prevents accidental copying of large config dumps.
Fix normalizeUuids for cf-info/cf-validate (false→true).
Result: 283 tests, 329s→84s (4x speedup).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 195 new test cases covering examples from SKILL.md, edge cases,
and parameter combinations. Create _skill.json for form-edit, skd-edit,
subsystem-edit. Add fixtures for negative validate cases. Fix
normalizeUuids in meta-validate/meta-info configs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- mxl-compile, mxl-validate, mxl-info, mxl-decompile: 4 cases
- runner: cwd option in _skill.json and preRun steps for skills
that resolve OutputPath relative to current directory
- Finding: mxl-compile only accepts relative OutputPath
21 tests across 9 skills, all passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fixture: paths now resolve relative to skill's cases/ dir, not global.
Each validate skill keeps its broken fixtures locally.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Compact mode shows "cases/meta-compile/catalog-basic" next to failed
test name — model can open the file, rerun, or update snapshot.
Verbose mode shows id for all cases.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Default shows one line per skill: "✓ meta-compile 6/6 (3.3s)"
Failed tests expanded with details automatically.
--verbose/-v shows full tree with every case.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>