Commit 1f97f6f
fix(ids): scope purpose inference + sync self-entry on regen (#748)
* fix(ids): scope purpose inference + sync self-entry on regen
Closes the cosmetic follow-up noted after PR #747 — CodeRabbit's
"Outside diff range" comments about entity-registry self-entry drift
and the `component-creation-guide` purpose field reading "Analyzes
provided dataset to identify patterns and insights" (clearly
unrelated to a component creation guide).
## Bug 1: purpose inference matched body text it shouldn't have
`extractPurpose()` in `populate-entity-registry.js` had a fallback
regex:
```js
const descMatch = content.match(/(?:description|purpose|summary)[:]\s*(.+)/i);
```
This is case-insensitive and unanchored — it matched ANY occurrence
in the file body, including example output inside installer
transcripts and fenced code blocks. For
`component-creation-guide.md`, it picked up line 132:
```
? Task description: Analyzes provided dataset to identify patterns and insights
```
…which is example output showing what a user might type, not a
description of the guide itself.
Fix: restructured `extractPurpose()` to a stricter priority chain:
1. **YAML frontmatter** — `description:` (or aliases) inside the
`---` block at the top of the file. Anchored to the frontmatter
region so body matches can't leak in.
2. **`## Purpose` section** — first non-empty line.
3. **`## Overview` section** — same shape as Purpose. Many guides
use Overview instead (e.g. component-creation-guide.md itself).
4. **First `# Title` heading** — the document's name.
5. **Generic fallback** — `Entity at <path>`.
The previous body-level `(?:description|purpose|summary)[:]` regex
was REMOVED deliberately. Its false-positive rate (matching example
output, installer transcripts, code block content) outweighed the
narrow legitimate case it covered, which is now handled by the
frontmatter branch.
## Bug 2: self-entry drift in `entities.data.entity-registry`
The registry contains a record for itself because the data layer
scan picks up every `.yaml`. That record's `lastVerified` was stuck
at whatever value the previous scan happened to write, and the
`checksum` was likewise stale relative to the regenerated file.
Fix: added `syncSelfRegistryEntry()` which runs after the registry
object is assembled but before yaml.dump. It:
- Sets `lastVerified` to the same `lastUpdated` timestamp written
into `metadata.lastUpdated` (single source of truth for this
regen event).
- Sets `checksum` to a sentinel value `sha256:<self-reference>`
because hashing the registry from inside the registry is circular —
any computed hash invalidates itself the moment it's written.
The sentinel signals "skip this comparison" to downstream
validators; trying to compute a "real" hash here would just
produce a number that doesn't match its own input.
The sync is guarded: it only fires when the self-entry's `path`
field is `.aiox-core/data/entity-registry.yaml`. The companion
`entity-registry.js` module under `entities.modules.*` is NOT
self-referential and is left alone.
## Validation
Regenerated the registry on this branch. After the fix:
- `grep -c "Analyzes provided dataset" .aiox-core/data/entity-registry.yaml` → `0`
- `grep -c "Add MCP Server Task" .aiox-core/data/entity-registry.yaml` → `0` (was the wrong purpose on the yaml self-entry)
- The yaml self-entry's `lastVerified` now matches `metadata.lastUpdated` exactly
- The yaml self-entry's `checksum` is the sentinel as expected
The `component-creation-guide` entity is no longer in the registry
at all — the file lives under `.aiox-core/core/docs/` which is not
in `SCAN_CONFIG` (the `modules` scan covers `.aiox-core/core` but
only for `*.js`/`*.mjs`, not `*.md`). Its previous presence was an
artifact of a prior scan run with broader config; this regen cleans
it up. If we want to start tracking framework docs as entities,
that's a separate concern handled in a follow-up to SCAN_CONFIG.
## Out of scope for this commit
A second-order cleanup that this PR does NOT do: there are still
some purposes in the registry that look like leaked template
placeholders (`'{Brief description of what this task does...}'`,
`'{{TASK_TITLE}}'`, `'*${taskName.replace(...)}'`). Those come from
files whose own bodies contain unfilled handlebars or JS literals —
the inference is technically working, the source is the problem.
Separate from this fix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(ids): align extractPurpose tests with refactored priority chain
The previous suite had a test "extracts from description field" that
fed a bare `description: ...` string and expected it to be matched.
That was exactly the body-level fallback regex that produced the
"Analyzes provided dataset" false purpose on component-creation-guide.md
(reported by CodeRabbit on PR #747). The refactor in this PR
intentionally removed that match, so the test must be updated to
reflect the new contract.
Changes to the test file:
* Replaced "extracts from description field" with two replacement tests:
- "extracts from YAML frontmatter `description:` field" — feeds a
`---\ndescription: X\n---` block and expects extraction from it.
- "handles quoted YAML frontmatter description" — feeds
`description: "X"` inside frontmatter and expects the quotes to
be stripped.
* Added "falls back to ## Overview when no Purpose section" — covers
the new strategy 3 in the priority chain (many guides like
component-creation-guide.md use Overview instead of Purpose).
* Added TWO regression tests for the bug that motivated the refactor:
- "does NOT match body-level `description:` outside frontmatter" —
reproduces the exact component-creation-guide pattern (Overview
section + a fenced code block with `Task description:` inside)
and asserts the Overview wins.
- "does NOT extract from `description:` lines without YAML
frontmatter delimiters" — bare `description: X` without `---`
delimiters falls through to the `# Title` header, NOT to the
body line.
Test result: 79/79 pass. Existing 5 tests in the suite still pass.
Two new tests cover the YAML frontmatter branch (priority 1) and the
new `## Overview` branch (priority 3). Two regression tests lock in
the removal of the body-level matcher so it can't silently come back.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent e5cd355 commit 1f97f6f
4 files changed
Lines changed: 1498 additions & 1285 deletions
File tree
- .aiox-core
- data
- development/scripts
- tests/core/ids
0 commit comments