Skip to content

fix(cli): headings name a project by its label; four small CLI fixes - #415

Merged
kevintseng merged 2 commits into
mainfrom
fix/dogfood-small-fixes
Sep 22, 2026
Merged

kevintseng merged 2 commits into
mainfrom
fix/dogfood-small-fixes

Conversation

@kevintseng

@kevintseng kevintseng commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Refs #409, #410 and #412. Each of them also has parts this PR does not touch, so none is closed here.

Five small user-visible fixes found by an independent dogfood pass on release 4.10.2, in one commit (fix(cli): headings name a project by its label; four small CLI fixes).

What changes for a user

  • Headings name a project by its label, not its 32-character hash (The injected briefing prints the 32-hex project id repeatedly and the standard index repeats memories already shown #409). Decisions and direction for "memesh~2c0fe491888c8efb9a4894828bbc2733": now reads Decisions and direction for "memesh":. The same goes for the other headings of the briefing, the task-state lines, the durable-memory index heading and its empty-state line, the first-run banner and the lines memesh task prints. One rule owns it, projectLabel in src/core/work-topology.ts: it removes one trailing ~ plus exactly 32 lowercase hex characters and leaves anything else alone. The full id stays wherever it identifies data: project: tags, entity names, the project field of JSON and MCP results, --project, and the unread-message line, which tells an agent which project to poll. Still there: the titles the session-summary and pre-compact hooks stored (2026-09-22 memesh~…: edited 12 file(s)) contain the whole id and are printed as stored under Recent activity (see "Not in this PR").
  • briefing --json no longer reports hasTaskState: true when the only state line is the unread-message reminder. It is now true exactly when a task-state line leads the block: the fresh state, the one-line stale flag, or the unreadable-record line. The CLI's "set the task state" hint reads it, so that hint now also appears beside the reminder on a project with a message waiting and no task state.
  • memesh config get <key> exists (CLI inconsistencies: config get is missing, status says up to date on a newer version, briefing --index prints the framing #410). It printed unknown command 'get'. It prints the stored value as config list shows it (for briefing: what is stored, not the level in effect), or <key> is not set in config.json (exit 0; it says nothing about which value applies, because an environment variable can still override the default). An unknown key is refused in the same two lines as set and unset (exit 1); the three share one requireAllowedKey.
  • memesh status no longer calls a newer install "up to date" (CLI inconsistencies: config get is missing, status says up to date on a newer version, briefing --index prints the framing #410). On 4.10.2 (a trial build on the next tag) while npm latest was 4.9.4 it printed Update check: up to date (fresh; latest 4.9.4) and an Update path: for @latest, a downgrade. It now says running pre-release version (4.10.2), npm latest is 4.9.4, as memesh doctor already did, and prints no update path. A newer install that is also deprecated, whose check only partly succeeded, or whose check could not run keeps its update path: only the "running pre-release version" line withholds it, through one shared predicate (showsPreReleaseNotice) that the status line and the trailer both use.
  • memesh config list always shows the briefing level in effect and where it comes from (The effective briefing level is not shown anywhere, and no live journey runs at the default level #412): briefing: minimal (default), briefing: standard (config.json), briefing: full (env MEMESH_BRIEFING), or, for a stored or environment value that is not a level, briefing: minimal (default; the value in config.json is invalid: "banana"). It uses the same resolver the hook uses. With nothing stored it prints (nothing stored — all defaults) first.

Evidence

  • npm run verify GREEN on the tree of the commit (tree 27d19998019b; 262 test files, 4529 tests passed, 9 skipped; the isolated suite, the packaged-artifact smoke and the dashboard e2e included).
  • An independent verifier ran every fix on the built output of the base commit and of the first version of this commit, on throwaway homes: all five reproduce on the base and are gone on the commit, neighbouring states are unchanged, the fields that identify data keep the full id, and a sweep of the output of eight commands finds no ~<32 hex> outside the project field. The MCP briefing tool was checked through a real JSON-RPC call.
  • Break-tests on the review fixes (string write-back, sha256 restored each time): making the status trailer ignore the deprecated and partial states turns the two new CLI tests red; taking the deprecated exception out of showsPreReleaseNotice turns exactly its truth-table row red; putting the old config get text back turns the two config get tests red.
  • Reviews of the whole diff by three independent reviewers (fresh-eyes, code review, silent-failure), plus the verifier above and a read-only simplification pass. The first version drew PASS_WITH_CONCERNS, PASS_WITH_CONCERNS and FAIL. The FAIL had three blocking findings, all real, all fixed in this commit: config get said "the default applies" while an environment variable could override it; the update path was wrongly hidden for a deprecated or partly checked install (a regression this change had introduced); a docs sentence said "every stored key" although one stored key is not settable. Two of them (silent-failure and code review) then re-reviewed the fix: no blocking finding, every earlier finding closed, and the status predicate checked against the status chain over 384 state combinations (0 mismatches). The remaining findings of those two were wording, fixed in the final commit; the third reviewer's non-blocking findings are either fixed or tracked above.

Simplification pass

A read-only pass over the whole diff found two candidates, both applied: the API reference repeated the allowed-key list in prose (cut: it goes stale unchecked, and memesh config set --help names the keys), and config set / config unset carried a pure alias, const canonical = key (removed). Kept on purpose, each checked for a consumer: the sort in config list (a test asserts the key order), the label === '' guard in projectLabel (a test pins it), describeEffectiveBriefing (one caller, but no other copy of it exists), and the overlapping test assertions (each goes through a different entry point).

Not in this PR (tracked)

Found by dogfooding release 4.10.2. Refs #409, #410 and #412; each of them
also has parts this commit does not touch.

- Headings and empty-state lines of the briefing, the task-state lines, the
  first-run banner and the lines `memesh task` prints name a project by its
  label ("memesh"), not its whole id ("memesh~<32 hex>"). One rule,
  `projectLabel` in work-topology.ts, removes one trailing `~` plus exactly 32
  lowercase hex characters and leaves anything else alone. The full id stays
  wherever it identifies data: `project:` tags, entity names, the `project`
  field of results, `--project`, and the unread-message line.
- `briefing --json` reports `hasTaskState: true` only when a task-state line
  leads the block; the unread-message reminder no longer counts.
- `memesh config get <key>` exists: the stored value, or "<key> is not set in
  config.json" (it says nothing about which value applies: an environment
  variable can still override the default); an unknown key is refused in the
  same words as `set` and `unset`.
- `memesh status` on an install newer than npm `latest` says "running
  pre-release version (X), npm latest is Y", as `memesh doctor` already did,
  instead of "up to date", and prints no update path. A newer install that is
  also deprecated, whose check only partly succeeded, or whose check could not
  run keeps its update path: only the "running pre-release version" line
  withholds it.
- `memesh config list` always shows the briefing level in effect and where it
  comes from (default, config.json or the environment).

Not changed on purpose: the stored fallback title of a task state, the titles
the pre-compact and session-summary hooks write (so the whole id can still
appear in the lines under "Recent activity"), lesson names and the dashboard
still carry the full id.
@kevintseng
kevintseng merged commit 3cce192 into main Sep 22, 2026
14 checks 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

Development

Successfully merging this pull request may close these issues.

1 participant