Skip to content

fix(ingest): drop machine-identifier entity names and wire the guard - #894

Merged
green-dalii merged 2 commits into
mainfrom
fix/755a-machine-name-guard
Oct 27, 2026
Merged

green-dalii merged 2 commits into
mainfrom
fix/755a-machine-name-guard

Conversation

@green-dalii

Copy link
Copy Markdown
Member

Split out of #755, which bundled this production fix with the extraction-focus settings. The code is @weqoocu's; the split is mine, and the commit carries their author line.

When the ingested note's own filename is a machine identifier — a dinox UUID (01988c6e_86e9_7b79_83b5_c8c4b354fdc9.md), an ob timestamp (202511042307.md), an IM message id (1921147873752416344) — the model sometimes extracts the source DOCUMENT itself as an entity and lifts the filename as its name. The result is entities/<uuid>.md: a page whose body merely re-narrates the summary it came from.

isSourceSelfReference rejects those names at normalization time, before a page exists:

  • machine shapes are rejected regardless of what the source file is called;
  • a verbatim copy of the basename is rejected only when it carries a plugin-style _ + hex hash tail, so TNF-α extracted from TNF-α.md survives, and a drama name from 庆余年_8a53fa.md survives.

Why the split needed a construct, not a cherry-pick

The original commit added the function and left the two .filter(...) calls to its successor. Cherry-picked alone it would have shipped an exported predicate that nothing calls, with tests that pass by calling the function directly — a guard that is not on the path. The wiring is in this PR, and the diff shows it:

.filter(e => e?.name?.trim())
.filter(e => !isSourceSelfReference(e.name, sourcePath))

Same for the tests: they arrived without the mentions_in_source fixture field their types require, which the successor commit had added. Both came across with the guard.

What is not in this PR

The prompt-level layer — "do not extract the source document, do not use the source filename as a name" — stays in the sibling PR with the settings it belongs to. This PR is the structural filter only, so it can be reviewed and reverted on its own.

Gate 4: Performance

Dim Status Notes
CPU ✅ Three anchored regex tests and one string comparison per extracted item, on the normalization path. Items number in the tens per source; the regexes are ^-anchored so they fail fast
Memory ✅ Nothing retained; a rejected item never reaches a page
IO ✅ Strictly less: a rejected name no longer becomes a file
Network ✅ No change
Token ✅ No prompt change in this PR

Credit, stated rather than assumed

If this merges by squash, the commit author becomes the PR author — me — and @weqoocu's contribution would read as mine. The options are a rebase merge (keeps their commit author), or a squash whose message names them. I am not deciding that here; it needs the maintainer's call at merge time.

Gate 1: lint 0, tsc 0, build clean, 367 test files / 5,038 tests, css-lint 0.

…git message IDs

Split out of #755, which bundled this guard with the extraction-focus settings.
The code is @weqoocu's; the split is mine.

When the ingested note's own filename is a machine identifier — a dinox UUID, an
ob timestamp, an IM message id — the model sometimes extracts the source DOCUMENT
itself as an entity and lifts the filename as its name. The result is
`entities/<uuid>.md`: a page whose body re-narrates the summary it came from.

`isSourceSelfReference` rejects those names at normalization time, before a page
exists. Machine shapes are rejected regardless of the source filename; a verbatim
copy of the basename is rejected only when it carries a plugin-style `_` + hex
hash tail, so `TNF-α` from `TNF-α.md` survives.

The wiring is part of this commit, not of the PR this was split from. That is
worth stating because the original commit added the function and left the two
`.filter(...)` calls to its successor: cherry-picking it alone would have
produced an exported predicate that nothing calls, with tests that pass against
the function directly. A guard that is not on the path is not a guard.

The prompt-level layer ("do not extract the source document") stays in the split
sibling, because it is a prompt change and this is a structural filter.

Gate 1: lint 0, tsc 0, build clean, tests pass, css-lint 0.
@green-dalii green-dalii added this to the v1.28.x PATCH milestone Oct 25, 2026
The guard moved out of #755 into #894, so the reference moves with it.

@green-dalii green-dalii left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge audit, recorded before the squash. Administrative bypass on explicit instruction; ruleset added, used, restored, re-read field by field.

Why bypass. Own PR, no approval possible on own PRs, ruleset requires a review.

Pre-merge scans. No closing keyword. No trailer. Two commits, both authored weqoocu <musicleaf@qq.com> — the contributor's identity, kept as the author of the work.

Credit. The commit author is the contributor's. A squash merge would make the merge commit's author the PR author — me — and the contribution would read as mine. The merge message below names the contributor instead.

What was verified beyond Gate 1. The guard is on the path, not beside it: the two .filter(...) calls that use isSourceSelfReference are in this PR, because the original commit added the function and left the wiring to its successor. Cherry-picking that commit alone would have shipped an exported predicate nothing calls, with tests that pass by calling the function directly. grep confirms two call sites in normalizeBatchResponse, and the semantic names survive: TNF-α from TNF-α.md passes.

Sequencing. #895 and this PR both touch src/wiki/source-analyzer.ts. They were merged together in a test branch before either was merged here — 369 files and 5,053 tests, both guards present — so the pair is known to compose.

@green-dalii
green-dalii merged commit bbcab12 into main Oct 27, 2026
2 checks passed
@green-dalii
green-dalii deleted the fix/755a-machine-name-guard branch October 27, 2026 01:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants