## [2026-05-15T12:24:33.944Z]
R0.3: cascade from cli/io metadata update (repo-scanner.ts added to mapping)
## [2026-05-15T12:36:42.733Z]
R0.4b: cascade from cli/io metadata update (atomic-write.ts added to mapping)
## [2026-05-15T12:41:10.419Z]
R0.5: graph-loader.ts now routes all fs calls through io/graph-fs.ts (readSortedDir, readTextFile)
## [2026-05-15T19:19:07.244Z]
Fix diagnostic-logging: add debugWrite() to both catch blocks in find.ts to satisfy the aspect requirement that all swallowed errors are logged via debugWrite before returning or exiting
## [2026-05-16T06:34:16.133Z]
Phase 5.2 (posix-paths-output): normalize doc.path before writing to stdout
## [2026-05-16T17:37:13.679Z]
Replaced inline 'No .yggdrasil/ directory found' error block with the shared loadGraphOrAbort helper from formatters/cli-preamble.ts. Reason: the same string and exit-1 logic was duplicated across 12 CLI command handlers; centralization eliminates a copy-paste class and routes the missing-graph message through buildIssueMessage uniformly. Other errors continue to flow through the surrounding catch and will be migrated to buildIssueMessage in the next task.
## [2026-05-16T18:22:20.435Z]
Migrated remaining ad-hoc stderr errors to buildIssueMessage (constant-text errors wrapped inline) and routed generic catch-blocks through the new abortOnUnexpectedError helper from formatters/cli-preamble.ts. Reason: even after the loadGraphOrAbort centralization, command-specific errors and option-validation messages bypassed the what/why/next structure; this commit aligns them so the AST aspect added in the next commit can enforce the rule mechanically.
## [2026-05-28T14:01:34.499Z]
Surface aspect-default status in yg find aspect-kind results. When a result's Kind is aspect, the rendered block now includes a status: <enum> line (draft / advisory / enforced) so adopters discovering entry points see the enforcement posture before opening the aspect content. Status is read from the indexed document and falls back to enforced when unset.
## [2026-05-31T14:10:02.987Z]
The relevance score shown next to each search result was the raw score from the underlying full-text index, which is an unbounded, query-dependent quantity (often around two to three) that a reader cannot interpret on its own and that contradicted the documented zero-to-one scale. Each result's score is now divided by the best result's score, so the output is normalized to a zero-to-one range relative to the strongest match: the top result reads as one and the others as their fraction of it. This makes the ranking legible — a large gap between the first and second result signals a confident winner, while tightly clustered values signal an ambiguous query — without changing the ranking order itself.
## [2026-05-31T15:19:20.033Z]
The search results "Matched:" line printed every term the query matched. For fuzzy and prefix queries the matcher expands a single word into many near-duplicate stems (order, orders, ordering, …), so the line became a long, noisy dump that buried the signal. The terms are now deduplicated case-insensitively and the rendered list is capped, with a "(+N more)" suffix when the full set is longer, so a reader can still see which query terms drove the match without scanning dozens of near-identical stems.
## [2026-05-31T15:26:48.857Z]
Routed unexpected errors in the find command through the single canonical error funnel. The command function previously wrapped its whole body in a try/catch that absorbed any error with an inline message and returned a non-zero code, which meant a genuinely unexpected failure never reached the shared abort-on-unexpected-error path that every other command uses, and the surfaced message did not follow the uniform what/why/next shape. The inner catch was removed so unexpected errors propagate to the action handler, which already routes them through the canonical funnel; the explicit empty-query validation (a known, constant-text error) stays inline as before. Behavior for the user is unchanged except that an unexpected crash now reports through the same uniform channel as the rest of the CLI.
## [2026-05-31T16:03:31.393Z]
Replaced the hand-inlined path-separator normalization with calls to a single shared helper. The same small idiom — convert backslash separators to forward slashes, and in most places also strip a trailing slash — had been copied across many modules, so the normalization rule lived in dozens of places at once and any change to it risked drifting them out of step. Consolidating it behind one well-named helper means the rule lives in exactly one spot and each call site reads by intent instead of by a repeated regex. Behavior is unchanged: the helper bodies are byte-for-byte equivalent to the expressions they replace, and the full test suite passes identically.
## [2026-05-31T17:27:16.732Z]
Moved the shared command-layer support helpers — the graph-load-or-abort wrapper and the unexpected-error funnel — out of the formatters layer and into the command layer. These helpers must reach both the engine (to load the graph) and the formatters (to build the uniform what/why/next message), and only the command layer may legally depend on both; keeping them in the formatters layer was an upward dependency on the engine that the layering rules forbid. The helpers register no command of their own, so they live under a dedicated command-support classification rather than as a command handler. Command handlers now import them from their new command-layer location.
## [2026-06-13T11:05:16.219Z]
The search command ended with a ranked list but no next action, leaving the agent to recall from the rules how to handle a node result versus an aspect result. It now ends with a concrete next step derived from the top result: for a component, the command to read its context; for a rule, a note to read the rule file directly rather than treat it as a component. The no-results case now points at browsing the full tree or re-querying.
