fix: gc must traverse oneOf and preserve template content #94
Reference in New Issue
Block a user
Delete Branch "fix/93-gc-collectrefs-oneof"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Fix
ocas gcfalsely deleting CAS nodes that are reachable throughoneOfschema combinators (e.g. uwf step chains usingoneOf: [{type:"null"}, {type:"string", format:"ocas_ref"}]for nullableprev/detail/start). Also aligngcwithclosure.tsPhase 3 so template content nodes (@ocas/template/text/<schema>) survive when their schema is reachable.Why
collectRefs()in@ocas/coretraverses every JSON-Schema combinator that the meta-schema accepts (anyOf,allOf,if/then/else,not,contains,propertyNames, etc.) exceptoneOf. uwf uses the standard JSON-Schema idiom for nullable references —oneOf: [{type:"null"}, {type:"string", format:"ocas_ref"}]— sowalk()never reachesprev/detail/start, andgc()marks only the head step + its schema. Every intermediate step, detail node, and workflow node was swept as a false orphan.Secondary defect:
gc()did not include@ocas/template/text/<schema-hash>content the wayclosure.tsdoes in Phase 3, so rendered template content for a reachable schema was incorrectly collected.Changes
packages/core/src/schema.ts—collectRefs()now traversesoneOfexactly the wayanyOfis traversed (every variant may contribute refs).packages/core/src/gc.ts— after walking from variable roots, walk every@ocas/template/text/<hash>variable whose schema-hash is in the reachable set, mirroringclosure.tsPhase 3.collectRefsoneOf), Suite B (5 tests forgcwithoneOfchains), Suite C (2 tests for template var preservation/collection), Suite D (1 CLI integration test). 695/695 tests passing..changeset/93-gc-collectrefs-oneof.md(@ocas/core: patch).No public type, function signature, or output schema changes. CLI behavior unchanged on the surface.
Ref
Fixes #93
collectRefs silently skipped oneOf even though it is in the meta-schema's allowed keys. uwf step nodes use the standard JSON-Schema idiom oneOf: [{type:"null"}, {type:"string", format:"ocas_ref"}] for nullable prev/detail/start refs, so walk() never reached the chain and gc swept the intermediate steps as false orphans. Mirror the anyOf branch in collectRefs so every oneOf variant contributes refs. Also align gc with closure.ts Phase 3: walk @ocas/template/text/<schema> content for every reachable schema so rendered template nodes survive when their schema is reachable, and are still collected when the schema itself is unreachable. Fixes #93LGTM ✅ 根因分析精准,修复干净。
oneOf 修复 — 与 anyOf handler 完全对称,递归设计天然处理嵌套场景。over-collect 安全(false reachable = 不丢数据),under-collect 致命 — 这个设计选择正确。
template 保留 — 与 closure.ts Phase 3 结构一一对应,snapshot-before-walk 防止级联。
12 个测试 — 三层覆盖:
全流程一次通过,reviewer 零 reject,小橘 solve-issue 管线真的成熟了 👏