feat(search): guide a 0-result search and fill the single-match number
The next-step suggestion on `search issues`/`search prs` is now conditioned on the in-repo match count. On a miss it pointed the agent at `view <number>`, which is nonsensical when nothing matched; it now suggests the non-indexed `issue list --state all` / `pr list --state all` fallback, which recovers from both an over-narrow query and issue-indexer lag without naming the cause. On exactly one match it fills the real number (`issue view 2`), applying AXI Principle 9's single-id fill. Two or more matches keep the parameterized placeholder. Search stays a locator — it never auto-loads the detail even on a single match; ADR 0017 records that decision (a deliberate narrowing of Principle 4) and the CONTEXT.md search term is updated to match.
This commit is contained in:
@@ -107,6 +107,10 @@ interface SearchKind {
|
||||
noun: string;
|
||||
/** The command a matched number feeds into. */
|
||||
viewCommand: string;
|
||||
/** The list command suggested as the fallback when a search finds nothing. */
|
||||
listCommand: string;
|
||||
/** Human plural for the fallback note, e.g. "issues" or "pull requests". */
|
||||
things: string;
|
||||
/** The `--help` text for this variant. */
|
||||
help: string;
|
||||
}
|
||||
@@ -116,6 +120,8 @@ const SEARCH_ISSUES: SearchKind = {
|
||||
type: "issues",
|
||||
noun: "issues",
|
||||
viewCommand: "issue view",
|
||||
listCommand: "issue list",
|
||||
things: "issues",
|
||||
help: SEARCH_ISSUES_HELP,
|
||||
};
|
||||
|
||||
@@ -124,6 +130,8 @@ const SEARCH_PRS: SearchKind = {
|
||||
type: "pulls",
|
||||
noun: "pull_requests",
|
||||
viewCommand: "pr view",
|
||||
listCommand: "pr list",
|
||||
things: "pull requests",
|
||||
help: SEARCH_PRS_HELP,
|
||||
};
|
||||
|
||||
@@ -217,11 +225,24 @@ async function runSearch(deps: CliDeps, args: string[], kind: SearchKind): Promi
|
||||
extractRow(issue, [...SEARCH_FIELDS, ...extraFields], { now, host: context.host, full }),
|
||||
);
|
||||
|
||||
// The next-step suggestion is conditioned on the match count. On a miss the
|
||||
// `view` hint is nonsensical, so point at the non-indexed list as a fallback
|
||||
// (it recovers from both an over-narrow query and index lag); on a single match
|
||||
// fill the real number (Principle 9's single-id fill); otherwise leave the
|
||||
// number parameterized. Search stays a locator either way — it never auto-loads
|
||||
// the detail (see ADR 0017).
|
||||
const suggestion =
|
||||
total === 0
|
||||
? suggestCommand(context, `${kind.listCommand} --state all`, `to list all ${kind.things} instead`)
|
||||
: total === 1
|
||||
? suggestCommand(context, `${kind.viewCommand} ${matches[0]!.number}`, "to see it in full")
|
||||
: suggestCommand(context, `${kind.viewCommand} <number>`, "to see a match in full");
|
||||
|
||||
return renderList({
|
||||
noun: kind.noun,
|
||||
rows,
|
||||
countLine: formatCountLine(rows.length, total, false),
|
||||
help: [suggestCommand(context, `${kind.viewCommand} <number>`, "to see a match in full")],
|
||||
help: [suggestion],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user