Skip to content

fix: escape labels, scope the layer annotation, guard foreign catalogs, announce the root (#2, #4, #5) - #10

Merged
RichardHightower merged 2 commits into
mainfrom
fix/catalog-and-root
Aug 10, 2026
Merged

fix: escape labels, scope the layer annotation, guard foreign catalogs, announce the root (#2, #4, #5)#10
RichardHightower merged 2 commits into
mainfrom
fix/catalog-and-root

Conversation

@RichardHightower

Copy link
Copy Markdown
Contributor

Three fixes in the bundle/catalog layer. The middle one is the interesting one.

#4 — scope the · <layer> annotation to catalogs only this plugin owns

This is the actual shared-bundle fix. The suffix fired for any concept
carrying a layer key, in any of the 32 catalogs — including the 8 that
system-architecture-capture also declares
(agents, diagrams, domains,
glossary, packs, products, storage, workflows). Its renderer emits a
bare - [label](path), so a shared catalog flipped back and forth on every
alternation between the two plugins.

Measured after the change — rendering the same glossary concept through all
three plugins:

SAC   md5=eecb841a   - [Alpha](/glossary/a.md)
PKC   md5=eecb841a   - [Alpha](/glossary/a.md)
DEKC  md5=eecb841a   - [Alpha](/glossary/a.md)

Byte-identical. The annotation is kept on catalogs only this plugin owns, such
as layers, and the test pins both halves.

I also added the catalog not in CATALOGS guard, but I want to be clear it is
not what fixes this: for a catalog two plugins both declare, that guard
passes in both. It is defensive hardening against an outside caller iterating
directories. The annotation scoping is the load-bearing change.

#2 — escape brackets in catalog link labels

Fact [Sales] rendered as [Fact [Sales]](/tables/a.md), which the graph
reader's link regex cannot match — producing a missing edge rather than a
broken one, which validate does not report.

Limit worth stating: backslash-escaping does not rescue a reader whose
label class is [^\]]+; that class has no notion of an escape and still stops at
the literal ]. Escaping is correct CommonMark and is what a bracket-aware
reader needs, but this half is inert until the reader change ships
(okf-plugin #48/#50). The test asserts that negative explicitly.

#5 — announce a fallback root

resolve_knowledge_root probes sample-knowledge/ and .okf/ when the
configured root is not an initialized bundle. There are 16 call sites and only
dekc_doctor announced
the bundle it used, so with any other command you could
not tell which root you got — and this repo ships a sample-knowledge/, so a
capture run inside a clone before initializing a bundle wrote there silently.

The configured root still wins whenever it is usable; that is unchanged and now
pinned by a test.

Verification

python3 tests/test_dekc.py                                    # 3 failures before, 22/22 after
python3 -m py_compile scripts/dekc_*.py                       # ok
python3 scripts/dekc_validate.py --bundle sample-knowledge    # ok
python3 scripts/dekc_doctor.py  --bundle sample-knowledge     # ok
python3 scripts/dekc_index.py ... build && dekc_search ...    # count=11

Closes #2
Closes #4
Closes #5

…s, announce the root (#2, #4, #5)

#2 -- escape brackets in catalog link labels.
A title like "Fact [Sales]" rendered as [Fact [Sales]](/tables/a.md), which the
OKF graph reader's link regex cannot match. The result is a MISSING edge, not
a broken one -- validate reports broken links only for edges that exist, and
its orphan check needs a concept to have NEITHER inbound NOR outbound links.
So any concept carrying one outbound link lost its catalog backlink silently.

Note the limit, because it surprised me: backslash-escaping does NOT rescue a
reader whose label class is [^]]+, since that class has no notion of an escape
and still stops at the literal ]. Escaping is the correct CommonMark output
and what a bracket-aware reader needs, but it only takes effect once the
matching reader change ships. The test asserts that negative explicitly.

#4 -- scope the layer annotation to catalogs only this plugin owns.
This is the actual shared-bundle fix. The " · <layer>" suffix fired for any
concept carrying a `layer` key, in any of the 32 catalogs -- including the 8
that system-architecture-capture also declares. Its renderer emits a bare
- [label](path), so the file flipped on every alternation between plugins.

Measured after the change: rendering a `glossary` concept through all three
plugins now produces byte-identical output (md5 eecb841a from each). The
annotation is retained on catalogs only this plugin owns, e.g. `layers`.

Also added the `catalog not in CATALOGS` guard. On its own that does NOT fix
the churn -- for a catalog two plugins both declare it passes in both -- which
is exactly why the annotation scoping is the load-bearing half.

#5 -- announce a fallback root.
resolve_knowledge_root probes sample-knowledge/ and .okf/ when the configured
root is not an initialized bundle. There are 16 call sites and only dekc_doctor
announced the bundle it used, so with any other command you could not tell
which root you got. This repo ships a sample-knowledge/, so a capture run
inside a clone before initializing a bundle wrote there silently.

3 failures before, 22/22 after. py_compile, validate, doctor, index build and
the search assertion all pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011XXDjM9WnCtsdRTU441WUu
Union-merge the test file (both branches purely added imports/classes)
and collapse the dekc_common import block to a single statement.
@RichardHightower
RichardHightower merged commit f088821 into main Aug 10, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant