@unbrained/pm-cli 2026.5.18 → 2026.5.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +60 -0
- package/README.md +2 -1
- package/dist/cli/commander-usage.js +16 -2
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/annotation-command.d.ts +49 -0
- package/dist/cli/commands/annotation-command.js +135 -0
- package/dist/cli/commands/annotation-command.js.map +1 -0
- package/dist/cli/commands/append.js +3 -7
- package/dist/cli/commands/append.js.map +1 -1
- package/dist/cli/commands/calendar.js +3 -6
- package/dist/cli/commands/calendar.js.map +1 -1
- package/dist/cli/commands/claim.js +12 -22
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/close.js +61 -9
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/comments.d.ts +5 -0
- package/dist/cli/commands/comments.js +27 -117
- package/dist/cli/commands/comments.js.map +1 -1
- package/dist/cli/commands/completion.js +102 -15
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/context.js +4 -10
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/contracts.js +168 -36
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/commands/create.js +49 -44
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/dedupe-audit.js +7 -4
- package/dist/cli/commands/dedupe-audit.js.map +1 -1
- package/dist/cli/commands/delete.d.ts +3 -0
- package/dist/cli/commands/delete.js +9 -8
- package/dist/cli/commands/delete.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +1 -0
- package/dist/cli/commands/docs.js +4 -8
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/event-validation-messages.d.ts +3 -0
- package/dist/cli/commands/event-validation-messages.js +44 -0
- package/dist/cli/commands/event-validation-messages.js.map +1 -0
- package/dist/cli/commands/extension.d.ts +1 -0
- package/dist/cli/commands/extension.js +138 -21
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/files.js +6 -13
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/gc.js +17 -4
- package/dist/cli/commands/gc.js.map +1 -1
- package/dist/cli/commands/get.d.ts +3 -2
- package/dist/cli/commands/get.js +50 -8
- package/dist/cli/commands/get.js.map +1 -1
- package/dist/cli/commands/health.d.ts +10 -0
- package/dist/cli/commands/health.js +254 -75
- package/dist/cli/commands/health.js.map +1 -1
- package/dist/cli/commands/history-redact.d.ts +8 -0
- package/dist/cli/commands/history-redact.js +14 -97
- package/dist/cli/commands/history-redact.js.map +1 -1
- package/dist/cli/commands/history-repair.d.ts +33 -0
- package/dist/cli/commands/history-repair.js +166 -0
- package/dist/cli/commands/history-repair.js.map +1 -0
- package/dist/cli/commands/history.d.ts +4 -4
- package/dist/cli/commands/history.js +10 -88
- package/dist/cli/commands/history.js.map +1 -1
- package/dist/cli/commands/index.d.ts +3 -1
- package/dist/cli/commands/index.js +5 -3
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +28 -0
- package/dist/cli/commands/init.js +23 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/learnings.js +20 -119
- package/dist/cli/commands/learnings.js.map +1 -1
- package/dist/cli/commands/linked-test-entry.d.ts +3 -0
- package/dist/cli/commands/linked-test-entry.js +62 -0
- package/dist/cli/commands/linked-test-entry.js.map +1 -0
- package/dist/cli/commands/list.js +32 -22
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/notes.js +20 -119
- package/dist/cli/commands/notes.js.map +1 -1
- package/dist/cli/commands/plan.d.ts +3 -0
- package/dist/cli/commands/plan.js +184 -22
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/restore.js +7 -50
- package/dist/cli/commands/restore.js.map +1 -1
- package/dist/cli/commands/schema.d.ts +31 -0
- package/dist/cli/commands/schema.js +98 -0
- package/dist/cli/commands/schema.js.map +1 -0
- package/dist/cli/commands/search.js +151 -40
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/templates.d.ts +4 -0
- package/dist/cli/commands/templates.js +89 -17
- package/dist/cli/commands/templates.js.map +1 -1
- package/dist/cli/commands/test-all.js +4 -8
- package/dist/cli/commands/test-all.js.map +1 -1
- package/dist/cli/commands/test.d.ts +1 -0
- package/dist/cli/commands/test.js +7 -10
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update-many.js +4 -8
- package/dist/cli/commands/update-many.js.map +1 -1
- package/dist/cli/commands/update.js +109 -51
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +3 -1
- package/dist/cli/commands/validate.js +23 -71
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/error-guidance.js +96 -6
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/extension-command-help.d.ts +0 -1
- package/dist/cli/extension-command-help.js +2 -13
- package/dist/cli/extension-command-help.js.map +1 -1
- package/dist/cli/extension-command-options.d.ts +1 -0
- package/dist/cli/extension-command-options.js +106 -7
- package/dist/cli/extension-command-options.js.map +1 -1
- package/dist/cli/help-content.d.ts +0 -1
- package/dist/cli/help-content.js +13 -9
- package/dist/cli/help-content.js.map +1 -1
- package/dist/cli/help-json-payload.d.ts +1 -0
- package/dist/cli/help-json-payload.js +33 -3
- package/dist/cli/help-json-payload.js.map +1 -1
- package/dist/cli/main.js +35 -29
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-list-query.d.ts +1 -1
- package/dist/cli/register-list-query.js +40 -17
- package/dist/cli/register-list-query.js.map +1 -1
- package/dist/cli/register-mutation.d.ts +1 -1
- package/dist/cli/register-mutation.js +232 -64
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-operations.js +16 -11
- package/dist/cli/register-operations.js.map +1 -1
- package/dist/cli/register-setup.js +26 -14
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli/registration-helpers.d.ts +0 -2
- package/dist/cli/registration-helpers.js +13 -40
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli.js +23 -3
- package/dist/cli.js.map +1 -1
- package/dist/core/extensions/index.d.ts +0 -1
- package/dist/core/extensions/index.js +2 -14
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.js +3 -9
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/fs/path-utils.d.ts +1 -0
- package/dist/core/fs/path-utils.js +12 -0
- package/dist/core/fs/path-utils.js.map +1 -0
- package/dist/core/history/drift-scan.d.ts +11 -0
- package/dist/core/history/drift-scan.js +67 -0
- package/dist/core/history/drift-scan.js.map +1 -0
- package/dist/core/history/replay.d.ts +82 -0
- package/dist/core/history/replay.js +249 -0
- package/dist/core/history/replay.js.map +1 -0
- package/dist/core/item/item-format.js +11 -8
- package/dist/core/item/item-format.js.map +1 -1
- package/dist/core/item/item-type-definition.d.ts +52 -0
- package/dist/core/item/item-type-definition.js +123 -0
- package/dist/core/item/item-type-definition.js.map +1 -0
- package/dist/core/item/parse.js +3 -2
- package/dist/core/item/parse.js.map +1 -1
- package/dist/core/item/priority.d.ts +23 -0
- package/dist/core/item/priority.js +55 -0
- package/dist/core/item/priority.js.map +1 -0
- package/dist/core/item/status.d.ts +14 -1
- package/dist/core/item/status.js +22 -2
- package/dist/core/item/status.js.map +1 -1
- package/dist/core/item/toon-decode.d.ts +19 -0
- package/dist/core/item/toon-decode.js +69 -0
- package/dist/core/item/toon-decode.js.map +1 -0
- package/dist/core/item/type-registry.js +13 -84
- package/dist/core/item/type-registry.js.map +1 -1
- package/dist/core/packages/manifest.js +3 -9
- package/dist/core/packages/manifest.js.map +1 -1
- package/dist/core/schema/item-types-file.d.ts +85 -0
- package/dist/core/schema/item-types-file.js +243 -0
- package/dist/core/schema/item-types-file.js.map +1 -0
- package/dist/core/schema/runtime-schema.d.ts +2 -1
- package/dist/core/schema/runtime-schema.js +11 -9
- package/dist/core/schema/runtime-schema.js.map +1 -1
- package/dist/core/search/semantic-defaults.js +3 -3
- package/dist/core/search/semantic-defaults.js.map +1 -1
- package/dist/core/shared/author.d.ts +1 -0
- package/dist/core/shared/author.js +9 -0
- package/dist/core/shared/author.js.map +1 -0
- package/dist/core/shared/lazy-module.d.ts +1 -0
- package/dist/core/shared/lazy-module.js +11 -0
- package/dist/core/shared/lazy-module.js.map +1 -0
- package/dist/core/shared/option-alias-visibility.d.ts +44 -0
- package/dist/core/shared/option-alias-visibility.js +76 -0
- package/dist/core/shared/option-alias-visibility.js.map +1 -0
- package/dist/core/shared/text-normalization.d.ts +0 -1
- package/dist/core/shared/text-normalization.js +2 -5
- package/dist/core/shared/text-normalization.js.map +1 -1
- package/dist/core/store/item-store.d.ts +2 -0
- package/dist/core/store/item-store.js +70 -39
- package/dist/core/store/item-store.js.map +1 -1
- package/dist/core/store/settings-validator.d.ts +106 -0
- package/dist/core/store/settings-validator.js +279 -0
- package/dist/core/store/settings-validator.js.map +1 -0
- package/dist/core/store/settings.js +6 -343
- package/dist/core/store/settings.js.map +1 -1
- package/dist/core/telemetry/runtime.js +5 -3
- package/dist/core/telemetry/runtime.js.map +1 -1
- package/dist/mcp/server.js +64 -13
- package/dist/mcp/server.js.map +1 -1
- package/dist/sdk/cli-contracts.d.ts +9 -2
- package/dist/sdk/cli-contracts.js +204 -13
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/runtime.d.ts +25 -1
- package/dist/sdk/runtime.js +46 -3
- package/dist/sdk/runtime.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.js +10 -2
- package/dist/types.js.map +1 -1
- package/docs/AGENT_GUIDE.md +7 -1
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/COMMANDS.md +39 -6
- package/docs/CONFIGURATION.md +1 -1
- package/docs/RELEASING.md +11 -7
- package/docs/SDK.md +11 -2
- package/package.json +12 -11
- package/packages/pm-calendar/README.md +3 -1
- package/packages/pm-calendar/extensions/calendar/index.js +21 -2
- package/packages/pm-calendar/extensions/calendar/index.ts +21 -2
- package/packages/pm-search-advanced/README.md +8 -0
- package/packages/pm-search-advanced/extensions/search-advanced/index.js +74 -0
- package/packages/pm-search-advanced/extensions/search-advanced/index.ts +74 -0
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +67 -9
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +67 -9
- package/packages/pm-templates/extensions/templates/runtime.js +11 -202
- package/packages/pm-templates/extensions/templates/runtime.ts +38 -230
- package/dist/core/output/command-aware.d.ts +0 -1
- package/dist/core/output/command-aware.js +0 -397
- package/dist/core/output/command-aware.js.map +0 -1
|
@@ -23,7 +23,7 @@ const calendarFlags = [
|
|
|
23
23
|
{ long: "--assignee-filter", value_name: "value", value_type: "string", description: "Filter assignee presence." },
|
|
24
24
|
{ long: "--sprint", value_name: "value", value_type: "string", description: "Filter by sprint." },
|
|
25
25
|
{ long: "--release", value_name: "value", value_type: "string", description: "Filter by release." },
|
|
26
|
-
{ long: "--include", value_name: "value", value_type: "string", description: "Include sources: deadlines|reminders|events|all." },
|
|
26
|
+
{ long: "--include", value_name: "value", value_type: "string", description: "Include sources: deadlines|reminders|events|scheduled|all." },
|
|
27
27
|
{ long: "--recurrence-lookahead-days", value_name: "n", value_type: "string", description: "Bound open-ended recurrence lookahead days." },
|
|
28
28
|
{ long: "--recurrence-lookback-days", value_name: "n", value_type: "string", description: "Bound open-ended recurrence lookback days." },
|
|
29
29
|
{ long: "--occurrence-limit", value_name: "n", value_type: "string", description: "Cap generated occurrences per recurring event." },
|
|
@@ -36,8 +36,27 @@ function calendarCommand(name) {
|
|
|
36
36
|
name,
|
|
37
37
|
action: "calendar",
|
|
38
38
|
description: "Show deadline, reminder, and scheduled event calendar views.",
|
|
39
|
+
arguments: [{ name: "view", required: false, description: "Calendar view: agenda|day|week|month." }],
|
|
39
40
|
flags: [...calendarFlags],
|
|
40
|
-
run: async (context) =>
|
|
41
|
+
run: async (context) => {
|
|
42
|
+
// Extension flags are parsed loosely, so context.args still contains flag
|
|
43
|
+
// tokens (e.g. ["day", "--date", "+7d"]). Only the leading non-flag tokens
|
|
44
|
+
// are true positionals, so a positional view combined with --date/--from/etc.
|
|
45
|
+
// must not be mistaken for multiple positional views.
|
|
46
|
+
const firstFlagIndex = context.args.findIndex((arg) => arg.startsWith("-"));
|
|
47
|
+
const positionalArgs = firstFlagIndex === -1 ? context.args : context.args.slice(0, firstFlagIndex);
|
|
48
|
+
const positionalView = positionalArgs[0]?.trim();
|
|
49
|
+
if (positionalArgs.length > 1) {
|
|
50
|
+
throw new Error("Calendar accepts at most one positional view: agenda|day|week|month.");
|
|
51
|
+
}
|
|
52
|
+
return runCalendarPackage(
|
|
53
|
+
{
|
|
54
|
+
...context.options,
|
|
55
|
+
...(positionalView && context.options.view === undefined ? { view: positionalView } : {}),
|
|
56
|
+
},
|
|
57
|
+
context.global,
|
|
58
|
+
);
|
|
59
|
+
},
|
|
41
60
|
};
|
|
42
61
|
}
|
|
43
62
|
|
|
@@ -29,7 +29,7 @@ const calendarFlags = [
|
|
|
29
29
|
{ long: "--assignee-filter", value_name: "value", value_type: "string", description: "Filter assignee presence." },
|
|
30
30
|
{ long: "--sprint", value_name: "value", value_type: "string", description: "Filter by sprint." },
|
|
31
31
|
{ long: "--release", value_name: "value", value_type: "string", description: "Filter by release." },
|
|
32
|
-
{ long: "--include", value_name: "value", value_type: "string", description: "Include sources: deadlines|reminders|events|all." },
|
|
32
|
+
{ long: "--include", value_name: "value", value_type: "string", description: "Include sources: deadlines|reminders|events|scheduled|all." },
|
|
33
33
|
{ long: "--recurrence-lookahead-days", value_name: "n", value_type: "string", description: "Bound open-ended recurrence lookahead days." },
|
|
34
34
|
{ long: "--recurrence-lookback-days", value_name: "n", value_type: "string", description: "Bound open-ended recurrence lookback days." },
|
|
35
35
|
{ long: "--occurrence-limit", value_name: "n", value_type: "string", description: "Cap generated occurrences per recurring event." },
|
|
@@ -42,8 +42,27 @@ function calendarCommand(name: "calendar" | "cal"): CommandDefinition {
|
|
|
42
42
|
name,
|
|
43
43
|
action: "calendar",
|
|
44
44
|
description: "Show deadline, reminder, and scheduled event calendar views.",
|
|
45
|
+
arguments: [{ name: "view", required: false, description: "Calendar view: agenda|day|week|month." }],
|
|
45
46
|
flags: [...calendarFlags],
|
|
46
|
-
run: async (context) =>
|
|
47
|
+
run: async (context) => {
|
|
48
|
+
// Extension flags are parsed loosely, so context.args still contains flag
|
|
49
|
+
// tokens (e.g. ["day", "--date", "+7d"]). Only the leading non-flag tokens
|
|
50
|
+
// are true positionals, so a positional view combined with --date/--from/etc.
|
|
51
|
+
// must not be mistaken for multiple positional views.
|
|
52
|
+
const firstFlagIndex = context.args.findIndex((arg) => arg.startsWith("-"));
|
|
53
|
+
const positionalArgs = firstFlagIndex === -1 ? context.args : context.args.slice(0, firstFlagIndex);
|
|
54
|
+
const positionalView = positionalArgs[0]?.trim();
|
|
55
|
+
if (positionalArgs.length > 1) {
|
|
56
|
+
throw new Error("Calendar accepts at most one positional view: agenda|day|week|month.");
|
|
57
|
+
}
|
|
58
|
+
return runCalendarPackage(
|
|
59
|
+
{
|
|
60
|
+
...(context.options as CalendarOptions),
|
|
61
|
+
...(positionalView && (context.options as CalendarOptions).view === undefined ? { view: positionalView } : {}),
|
|
62
|
+
},
|
|
63
|
+
context.global,
|
|
64
|
+
);
|
|
65
|
+
},
|
|
47
66
|
};
|
|
48
67
|
}
|
|
49
68
|
|
|
@@ -6,9 +6,13 @@ First-party package that restores optional advanced search surfaces in bare-core
|
|
|
6
6
|
|
|
7
7
|
- Adds `pm search-advanced` with:
|
|
8
8
|
- `--mode keyword|semantic|hybrid`
|
|
9
|
+
- `--semantic`, `--hybrid`
|
|
9
10
|
- `--include-linked`
|
|
10
11
|
- `--title-exact`
|
|
11
12
|
- `--phrase-exact`
|
|
13
|
+
- `--type`, `--tag`, `--priority`
|
|
14
|
+
- `--deadline-before`, `--deadline-after`
|
|
15
|
+
- `--limit`, `--fields`, `--compact`, `--full`
|
|
12
16
|
- Adds `pm reindex` with:
|
|
13
17
|
- `--mode keyword|semantic|hybrid`
|
|
14
18
|
- `--progress`
|
|
@@ -23,5 +27,9 @@ pm install search-advanced --project
|
|
|
23
27
|
|
|
24
28
|
```bash
|
|
25
29
|
pm search-advanced "vector cache" --mode hybrid --limit 5 --json
|
|
30
|
+
pm search-advanced --hybrid "vector cache" --limit 5 --json
|
|
31
|
+
pm search-advanced "calendar package" --mode keyword --fields id,title,score --compact --json
|
|
26
32
|
pm reindex --mode hybrid --progress --json
|
|
27
33
|
```
|
|
34
|
+
|
|
35
|
+
Without `--mode`, `--semantic`, or `--hybrid`, `search-advanced` stays keyword-first for fast agent reads.
|
|
@@ -15,6 +15,16 @@ const searchAdvancedFlags = [
|
|
|
15
15
|
value_type: "string",
|
|
16
16
|
description: "Search mode override: keyword|semantic|hybrid.",
|
|
17
17
|
},
|
|
18
|
+
{
|
|
19
|
+
long: "--semantic",
|
|
20
|
+
value_type: "boolean",
|
|
21
|
+
description: "Alias for --mode semantic.",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
long: "--hybrid",
|
|
25
|
+
value_type: "boolean",
|
|
26
|
+
description: "Alias for --mode hybrid.",
|
|
27
|
+
},
|
|
18
28
|
{
|
|
19
29
|
long: "--include-linked",
|
|
20
30
|
value_type: "boolean",
|
|
@@ -45,6 +55,70 @@ const searchAdvancedFlags = [
|
|
|
45
55
|
value_type: "boolean",
|
|
46
56
|
description: "Alias for --phrase-exact.",
|
|
47
57
|
},
|
|
58
|
+
{
|
|
59
|
+
long: "--type",
|
|
60
|
+
value_name: "value",
|
|
61
|
+
value_type: "string",
|
|
62
|
+
description: "Filter by item type.",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
long: "--tag",
|
|
66
|
+
value_name: "value",
|
|
67
|
+
value_type: "string",
|
|
68
|
+
description: "Filter by tag.",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
long: "--priority",
|
|
72
|
+
value_name: "value",
|
|
73
|
+
value_type: "string",
|
|
74
|
+
description: "Filter by priority.",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
long: "--deadline-before",
|
|
78
|
+
value_name: "date",
|
|
79
|
+
value_type: "string",
|
|
80
|
+
description: "Filter to items with deadlines before a date.",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
long: "--deadline_before",
|
|
84
|
+
value_name: "date",
|
|
85
|
+
value_type: "string",
|
|
86
|
+
description: "Alias for --deadline-before.",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
long: "--deadline-after",
|
|
90
|
+
value_name: "date",
|
|
91
|
+
value_type: "string",
|
|
92
|
+
description: "Filter to items with deadlines after a date.",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
long: "--deadline_after",
|
|
96
|
+
value_name: "date",
|
|
97
|
+
value_type: "string",
|
|
98
|
+
description: "Alias for --deadline-after.",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
long: "--limit",
|
|
102
|
+
value_name: "count",
|
|
103
|
+
value_type: "string",
|
|
104
|
+
description: "Limit the number of search results.",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
long: "--fields",
|
|
108
|
+
value_name: "list",
|
|
109
|
+
value_type: "string",
|
|
110
|
+
description: "Return only selected result fields.",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
long: "--compact",
|
|
114
|
+
value_type: "boolean",
|
|
115
|
+
description: "Return compact token-efficient search results.",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
long: "--full",
|
|
119
|
+
value_type: "boolean",
|
|
120
|
+
description: "Return full search results.",
|
|
121
|
+
},
|
|
48
122
|
];
|
|
49
123
|
|
|
50
124
|
const reindexFlags = [
|
|
@@ -16,6 +16,16 @@ const searchAdvancedFlags = [
|
|
|
16
16
|
value_type: "string",
|
|
17
17
|
description: "Search mode override: keyword|semantic|hybrid.",
|
|
18
18
|
},
|
|
19
|
+
{
|
|
20
|
+
long: "--semantic",
|
|
21
|
+
value_type: "boolean",
|
|
22
|
+
description: "Alias for --mode semantic.",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
long: "--hybrid",
|
|
26
|
+
value_type: "boolean",
|
|
27
|
+
description: "Alias for --mode hybrid.",
|
|
28
|
+
},
|
|
19
29
|
{
|
|
20
30
|
long: "--include-linked",
|
|
21
31
|
value_type: "boolean",
|
|
@@ -46,6 +56,70 @@ const searchAdvancedFlags = [
|
|
|
46
56
|
value_type: "boolean",
|
|
47
57
|
description: "Alias for --phrase-exact.",
|
|
48
58
|
},
|
|
59
|
+
{
|
|
60
|
+
long: "--type",
|
|
61
|
+
value_name: "value",
|
|
62
|
+
value_type: "string",
|
|
63
|
+
description: "Filter by item type.",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
long: "--tag",
|
|
67
|
+
value_name: "value",
|
|
68
|
+
value_type: "string",
|
|
69
|
+
description: "Filter by tag.",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
long: "--priority",
|
|
73
|
+
value_name: "value",
|
|
74
|
+
value_type: "string",
|
|
75
|
+
description: "Filter by priority.",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
long: "--deadline-before",
|
|
79
|
+
value_name: "date",
|
|
80
|
+
value_type: "string",
|
|
81
|
+
description: "Filter to items with deadlines before a date.",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
long: "--deadline_before",
|
|
85
|
+
value_name: "date",
|
|
86
|
+
value_type: "string",
|
|
87
|
+
description: "Alias for --deadline-before.",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
long: "--deadline-after",
|
|
91
|
+
value_name: "date",
|
|
92
|
+
value_type: "string",
|
|
93
|
+
description: "Filter to items with deadlines after a date.",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
long: "--deadline_after",
|
|
97
|
+
value_name: "date",
|
|
98
|
+
value_type: "string",
|
|
99
|
+
description: "Alias for --deadline-after.",
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
long: "--limit",
|
|
103
|
+
value_name: "count",
|
|
104
|
+
value_type: "string",
|
|
105
|
+
description: "Limit the number of search results.",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
long: "--fields",
|
|
109
|
+
value_name: "list",
|
|
110
|
+
value_type: "string",
|
|
111
|
+
description: "Return only selected result fields.",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
long: "--compact",
|
|
115
|
+
value_type: "boolean",
|
|
116
|
+
description: "Return compact token-efficient search results.",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
long: "--full",
|
|
120
|
+
value_type: "boolean",
|
|
121
|
+
description: "Return full search results.",
|
|
122
|
+
},
|
|
49
123
|
] as const;
|
|
50
124
|
|
|
51
125
|
const reindexFlags = [
|
|
@@ -48,6 +48,9 @@ function readStringOption(options, key, aliases = []) {
|
|
|
48
48
|
return undefined;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
const BOOLEAN_TRUE_VALUES = new Set(["true", "1", "yes", "on"]);
|
|
52
|
+
const BOOLEAN_FALSE_VALUES = new Set(["false", "0", "no", "off"]);
|
|
53
|
+
|
|
51
54
|
function readBooleanOption(options, key, aliases = []) {
|
|
52
55
|
const keys = [key, ...aliases];
|
|
53
56
|
for (const candidate of keys) {
|
|
@@ -60,10 +63,10 @@ function readBooleanOption(options, key, aliases = []) {
|
|
|
60
63
|
}
|
|
61
64
|
if (typeof value === "string") {
|
|
62
65
|
const normalized = value.trim().toLowerCase();
|
|
63
|
-
if (normalized
|
|
66
|
+
if (BOOLEAN_TRUE_VALUES.has(normalized)) {
|
|
64
67
|
return true;
|
|
65
68
|
}
|
|
66
|
-
if (normalized
|
|
69
|
+
if (BOOLEAN_FALSE_VALUES.has(normalized)) {
|
|
67
70
|
return false;
|
|
68
71
|
}
|
|
69
72
|
}
|
|
@@ -71,24 +74,79 @@ function readBooleanOption(options, key, aliases = []) {
|
|
|
71
74
|
return undefined;
|
|
72
75
|
}
|
|
73
76
|
|
|
77
|
+
const SEARCH_VALUE_FLAGS = new Set([
|
|
78
|
+
"--mode",
|
|
79
|
+
"--type",
|
|
80
|
+
"--tag",
|
|
81
|
+
"--priority",
|
|
82
|
+
"--deadline-before",
|
|
83
|
+
"--deadline_before",
|
|
84
|
+
"--deadline-after",
|
|
85
|
+
"--deadline_after",
|
|
86
|
+
"--limit",
|
|
87
|
+
"--fields",
|
|
88
|
+
]);
|
|
89
|
+
|
|
90
|
+
const SEARCH_BOOLEAN_FLAGS = new Set([
|
|
91
|
+
"--semantic",
|
|
92
|
+
"--hybrid",
|
|
93
|
+
"--include-linked",
|
|
94
|
+
"--include_linked",
|
|
95
|
+
"--title-exact",
|
|
96
|
+
"--title_exact",
|
|
97
|
+
"--phrase-exact",
|
|
98
|
+
"--phrase_exact",
|
|
99
|
+
"--compact",
|
|
100
|
+
"--full",
|
|
101
|
+
"--json",
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
function stripSearchOptionTokens(args) {
|
|
105
|
+
const queryTokens = [];
|
|
106
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
107
|
+
const token = args[index]?.trim() ?? "";
|
|
108
|
+
const equalsIndex = token.indexOf("=");
|
|
109
|
+
const flagName = equalsIndex > 0 ? token.slice(0, equalsIndex) : token;
|
|
110
|
+
if (SEARCH_VALUE_FLAGS.has(flagName)) {
|
|
111
|
+
if (equalsIndex < 0) {
|
|
112
|
+
index += 1;
|
|
113
|
+
}
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (SEARCH_BOOLEAN_FLAGS.has(flagName)) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (token.length > 0) {
|
|
120
|
+
queryTokens.push(token);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return queryTokens;
|
|
124
|
+
}
|
|
125
|
+
|
|
74
126
|
function resolveSearchQuery(args) {
|
|
75
|
-
const query = args
|
|
76
|
-
.map((value) => value.trim())
|
|
77
|
-
.filter((value) => value.length > 0)
|
|
78
|
-
.join(" ");
|
|
127
|
+
const query = stripSearchOptionTokens(args).join(" ");
|
|
79
128
|
if (query.length === 0) {
|
|
80
129
|
throw new PmCliError("Search query must not be empty", EXIT_CODE.USAGE);
|
|
81
130
|
}
|
|
82
131
|
return query;
|
|
83
132
|
}
|
|
84
133
|
|
|
85
|
-
function normalizeAdvancedSearchOptions(rawOptions) {
|
|
134
|
+
function normalizeAdvancedSearchOptions(rawOptions, args) {
|
|
86
135
|
const fields = readStringOption(rawOptions, "fields");
|
|
87
136
|
const compactRequested = readBooleanOption(rawOptions, "compact") === true;
|
|
88
137
|
const fullRequested = readBooleanOption(rawOptions, "full") === true;
|
|
89
138
|
const defaultCompact = !compactRequested && !fullRequested && fields === undefined;
|
|
139
|
+
const explicitMode = readStringOption(rawOptions, "mode");
|
|
140
|
+
const argFlags = new Set(args.map((value) => value?.trim() ?? ""));
|
|
141
|
+
const mode =
|
|
142
|
+
explicitMode ??
|
|
143
|
+
(readBooleanOption(rawOptions, "semantic") === true || argFlags.has("--semantic")
|
|
144
|
+
? "semantic"
|
|
145
|
+
: readBooleanOption(rawOptions, "hybrid") === true || argFlags.has("--hybrid")
|
|
146
|
+
? "hybrid"
|
|
147
|
+
: "keyword");
|
|
90
148
|
return {
|
|
91
|
-
mode
|
|
149
|
+
mode,
|
|
92
150
|
includeLinked: readBooleanOption(rawOptions, "includeLinked", ["include_linked"]) === true ? true : undefined,
|
|
93
151
|
titleExact: readBooleanOption(rawOptions, "titleExact", ["title_exact"]) === true ? true : undefined,
|
|
94
152
|
phraseExact: readBooleanOption(rawOptions, "phraseExact", ["phrase_exact"]) === true ? true : undefined,
|
|
@@ -112,7 +170,7 @@ function normalizeReindexOptions(rawOptions) {
|
|
|
112
170
|
}
|
|
113
171
|
|
|
114
172
|
export async function runAdvancedSearchPackage(args, rawOptions, global) {
|
|
115
|
-
return runSearch(resolveSearchQuery(args), normalizeAdvancedSearchOptions(rawOptions), global);
|
|
173
|
+
return runSearch(resolveSearchQuery(args), normalizeAdvancedSearchOptions(rawOptions, args), global);
|
|
116
174
|
}
|
|
117
175
|
|
|
118
176
|
export async function runAdvancedReindexPackage(rawOptions, global) {
|
|
@@ -65,6 +65,9 @@ function readStringOption(options: Record<string, unknown>, key: string, aliases
|
|
|
65
65
|
return undefined;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
const BOOLEAN_TRUE_VALUES = new Set(["true", "1", "yes", "on"]);
|
|
69
|
+
const BOOLEAN_FALSE_VALUES = new Set(["false", "0", "no", "off"]);
|
|
70
|
+
|
|
68
71
|
function readBooleanOption(options: Record<string, unknown>, key: string, aliases: string[] = []): boolean | undefined {
|
|
69
72
|
const keys = [key, ...aliases];
|
|
70
73
|
for (const candidate of keys) {
|
|
@@ -77,10 +80,10 @@ function readBooleanOption(options: Record<string, unknown>, key: string, aliase
|
|
|
77
80
|
}
|
|
78
81
|
if (typeof value === "string") {
|
|
79
82
|
const normalized = value.trim().toLowerCase();
|
|
80
|
-
if (normalized
|
|
83
|
+
if (BOOLEAN_TRUE_VALUES.has(normalized)) {
|
|
81
84
|
return true;
|
|
82
85
|
}
|
|
83
|
-
if (normalized
|
|
86
|
+
if (BOOLEAN_FALSE_VALUES.has(normalized)) {
|
|
84
87
|
return false;
|
|
85
88
|
}
|
|
86
89
|
}
|
|
@@ -88,24 +91,79 @@ function readBooleanOption(options: Record<string, unknown>, key: string, aliase
|
|
|
88
91
|
return undefined;
|
|
89
92
|
}
|
|
90
93
|
|
|
94
|
+
const SEARCH_VALUE_FLAGS = new Set([
|
|
95
|
+
"--mode",
|
|
96
|
+
"--type",
|
|
97
|
+
"--tag",
|
|
98
|
+
"--priority",
|
|
99
|
+
"--deadline-before",
|
|
100
|
+
"--deadline_before",
|
|
101
|
+
"--deadline-after",
|
|
102
|
+
"--deadline_after",
|
|
103
|
+
"--limit",
|
|
104
|
+
"--fields",
|
|
105
|
+
]);
|
|
106
|
+
|
|
107
|
+
const SEARCH_BOOLEAN_FLAGS = new Set([
|
|
108
|
+
"--semantic",
|
|
109
|
+
"--hybrid",
|
|
110
|
+
"--include-linked",
|
|
111
|
+
"--include_linked",
|
|
112
|
+
"--title-exact",
|
|
113
|
+
"--title_exact",
|
|
114
|
+
"--phrase-exact",
|
|
115
|
+
"--phrase_exact",
|
|
116
|
+
"--compact",
|
|
117
|
+
"--full",
|
|
118
|
+
"--json",
|
|
119
|
+
]);
|
|
120
|
+
|
|
121
|
+
function stripSearchOptionTokens(args: string[]): string[] {
|
|
122
|
+
const queryTokens: string[] = [];
|
|
123
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
124
|
+
const token = args[index]?.trim() ?? "";
|
|
125
|
+
const equalsIndex = token.indexOf("=");
|
|
126
|
+
const flagName = equalsIndex > 0 ? token.slice(0, equalsIndex) : token;
|
|
127
|
+
if (SEARCH_VALUE_FLAGS.has(flagName)) {
|
|
128
|
+
if (equalsIndex < 0) {
|
|
129
|
+
index += 1;
|
|
130
|
+
}
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (SEARCH_BOOLEAN_FLAGS.has(flagName)) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (token.length > 0) {
|
|
137
|
+
queryTokens.push(token);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return queryTokens;
|
|
141
|
+
}
|
|
142
|
+
|
|
91
143
|
function resolveSearchQuery(args: string[]): string {
|
|
92
|
-
const query = args
|
|
93
|
-
.map((value) => value.trim())
|
|
94
|
-
.filter((value) => value.length > 0)
|
|
95
|
-
.join(" ");
|
|
144
|
+
const query = stripSearchOptionTokens(args).join(" ");
|
|
96
145
|
if (query.length === 0) {
|
|
97
146
|
throw new PmCliError("Search query must not be empty", EXIT_CODE.USAGE);
|
|
98
147
|
}
|
|
99
148
|
return query;
|
|
100
149
|
}
|
|
101
150
|
|
|
102
|
-
function normalizeAdvancedSearchOptions(rawOptions: Record<string, unknown
|
|
151
|
+
function normalizeAdvancedSearchOptions(rawOptions: Record<string, unknown>, args: string[]): SearchOptions {
|
|
103
152
|
const fields = readStringOption(rawOptions, "fields");
|
|
104
153
|
const compactRequested = readBooleanOption(rawOptions, "compact") === true;
|
|
105
154
|
const fullRequested = readBooleanOption(rawOptions, "full") === true;
|
|
106
155
|
const defaultCompact = !compactRequested && !fullRequested && fields === undefined;
|
|
156
|
+
const explicitMode = readStringOption(rawOptions, "mode");
|
|
157
|
+
const argFlags = new Set(args.map((value) => value?.trim() ?? ""));
|
|
158
|
+
const mode =
|
|
159
|
+
explicitMode ??
|
|
160
|
+
(readBooleanOption(rawOptions, "semantic") === true || argFlags.has("--semantic")
|
|
161
|
+
? "semantic"
|
|
162
|
+
: readBooleanOption(rawOptions, "hybrid") === true || argFlags.has("--hybrid")
|
|
163
|
+
? "hybrid"
|
|
164
|
+
: "keyword");
|
|
107
165
|
return {
|
|
108
|
-
mode
|
|
166
|
+
mode,
|
|
109
167
|
includeLinked: readBooleanOption(rawOptions, "includeLinked", ["include_linked"]) === true ? true : undefined,
|
|
110
168
|
titleExact: readBooleanOption(rawOptions, "titleExact", ["title_exact"]) === true ? true : undefined,
|
|
111
169
|
phraseExact: readBooleanOption(rawOptions, "phraseExact", ["phrase_exact"]) === true ? true : undefined,
|
|
@@ -133,7 +191,7 @@ export async function runAdvancedSearchPackage(
|
|
|
133
191
|
rawOptions: Record<string, unknown>,
|
|
134
192
|
global: GlobalOptions,
|
|
135
193
|
): Promise<SearchResult> {
|
|
136
|
-
return runSearch(resolveSearchQuery(args), normalizeAdvancedSearchOptions(rawOptions), global);
|
|
194
|
+
return runSearch(resolveSearchQuery(args), normalizeAdvancedSearchOptions(rawOptions, args), global);
|
|
137
195
|
}
|
|
138
196
|
|
|
139
197
|
export async function runAdvancedReindexPackage(
|