@unbrained/pm-cli 2026.5.2 → 2026.5.3-5
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/AGENTS.md +8 -1
- package/CHANGELOG.md +53 -0
- package/README.md +9 -1
- package/dist/cli/bootstrap-args.d.ts +18 -0
- package/dist/cli/bootstrap-args.js +242 -0
- package/dist/cli/bootstrap-args.js.map +1 -0
- package/dist/cli/commander-usage.d.ts +17 -0
- package/dist/cli/commander-usage.js +178 -0
- package/dist/cli/commander-usage.js.map +1 -0
- package/dist/cli/commands/activity.js +1 -9
- package/dist/cli/commands/activity.js.map +1 -1
- package/dist/cli/commands/calendar.js +3 -29
- package/dist/cli/commands/calendar.js.map +1 -1
- package/dist/cli/commands/comments.js +1 -9
- package/dist/cli/commands/comments.js.map +1 -1
- package/dist/cli/commands/config.d.ts +21 -3
- package/dist/cli/commands/config.js +118 -2
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/context.d.ts +90 -1
- package/dist/cli/commands/context.js +485 -23
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/dedupe-audit.js +2 -11
- package/dist/cli/commands/dedupe-audit.js.map +1 -1
- package/dist/cli/commands/history.js +1 -9
- package/dist/cli/commands/history.js.map +1 -1
- package/dist/cli/commands/learnings.js +1 -9
- package/dist/cli/commands/learnings.js.map +1 -1
- package/dist/cli/commands/list.js +3 -29
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/normalize.js +9 -6
- package/dist/cli/commands/normalize.js.map +1 -1
- package/dist/cli/commands/notes.js +1 -9
- package/dist/cli/commands/notes.js.map +1 -1
- package/dist/cli/commands/reindex.js +2 -7
- package/dist/cli/commands/reindex.js.map +1 -1
- package/dist/cli/commands/search.js +4 -35
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/test-runs.js +1 -11
- package/dist/cli/commands/test-runs.js.map +1 -1
- package/dist/cli/error-guidance.d.ts +13 -0
- package/dist/cli/error-guidance.js +43 -4
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/extension-command-help.d.ts +48 -0
- package/dist/cli/extension-command-help.js +389 -0
- package/dist/cli/extension-command-help.js.map +1 -0
- package/dist/cli/help-content.js +9 -3
- package/dist/cli/help-content.js.map +1 -1
- package/dist/cli/help-json-payload.d.ts +25 -0
- package/dist/cli/help-json-payload.js +265 -0
- package/dist/cli/help-json-payload.js.map +1 -0
- package/dist/cli/main.js +996 -4468
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/migration-gates.d.ts +22 -0
- package/dist/cli/migration-gates.js +146 -0
- package/dist/cli/migration-gates.js.map +1 -0
- package/dist/cli/register-list-query.d.ts +2 -0
- package/dist/cli/register-list-query.js +317 -0
- package/dist/cli/register-list-query.js.map +1 -0
- package/dist/cli/register-mutation.d.ts +2 -0
- package/dist/cli/register-mutation.js +795 -0
- package/dist/cli/register-mutation.js.map +1 -0
- package/dist/cli/register-operations.d.ts +2 -0
- package/dist/cli/register-operations.js +610 -0
- package/dist/cli/register-operations.js.map +1 -0
- package/dist/cli/register-setup.d.ts +2 -0
- package/dist/cli/register-setup.js +334 -0
- package/dist/cli/register-setup.js.map +1 -0
- package/dist/cli/registration-helpers.d.ts +53 -0
- package/dist/cli/registration-helpers.js +669 -0
- package/dist/cli/registration-helpers.js.map +1 -0
- package/dist/cli/shared-parsers.d.ts +6 -0
- package/dist/cli/shared-parsers.js +40 -0
- package/dist/cli/shared-parsers.js.map +1 -0
- package/dist/core/search/http-client.d.ts +29 -0
- package/dist/core/search/http-client.js +64 -0
- package/dist/core/search/http-client.js.map +1 -0
- package/dist/core/search/providers.d.ts +3 -13
- package/dist/core/search/providers.js +19 -69
- package/dist/core/search/providers.js.map +1 -1
- package/dist/core/search/semantic-defaults.js +2 -7
- package/dist/core/search/semantic-defaults.js.map +1 -1
- package/dist/core/search/vector-stores.d.ts +3 -13
- package/dist/core/search/vector-stores.js +17 -66
- package/dist/core/search/vector-stores.js.map +1 -1
- package/dist/core/sentry/helpers.d.ts +23 -2
- package/dist/core/sentry/helpers.js +101 -3
- package/dist/core/sentry/helpers.js.map +1 -1
- package/dist/core/sentry/instrument.d.ts +21 -0
- package/dist/core/sentry/instrument.js +34 -3
- package/dist/core/sentry/instrument.js.map +1 -1
- package/dist/core/shared/constants.d.ts +3 -0
- package/dist/core/shared/constants.js +58 -1
- package/dist/core/shared/constants.js.map +1 -1
- package/dist/core/store/front-matter-cache.d.ts +6 -0
- package/dist/core/store/front-matter-cache.js +150 -0
- package/dist/core/store/front-matter-cache.js.map +1 -0
- package/dist/core/store/item-store.js +2 -1
- package/dist/core/store/item-store.js.map +1 -1
- package/dist/core/store/settings.js +36 -0
- package/dist/core/store/settings.js.map +1 -1
- package/dist/core/telemetry/observability.d.ts +24 -0
- package/dist/core/telemetry/observability.js +185 -0
- package/dist/core/telemetry/observability.js.map +1 -0
- package/dist/core/telemetry/runtime.d.ts +27 -3
- package/dist/core/telemetry/runtime.js +298 -13
- package/dist/core/telemetry/runtime.js.map +1 -1
- package/dist/sdk/cli-contracts.js +28 -0
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/types.d.ts +21 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -1
- package/docs/ARCHITECTURE.md +7 -1
- package/docs/COMMANDS.md +11 -1
- package/docs/RELEASING.md +56 -29
- package/package.json +8 -3
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
import { pathExists } from "../core/fs/fs-utils.js";
|
|
2
|
+
import { resolveItemTypeRegistry } from "../core/item/type-registry.js";
|
|
3
|
+
import { normalizeStatusInput } from "../core/item/status.js";
|
|
4
|
+
import { resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry } from "../core/schema/runtime-schema.js";
|
|
5
|
+
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
6
|
+
import { PmCliError } from "../core/shared/errors.js";
|
|
7
|
+
import { listAllFrontMatter } from "../core/store/item-store.js";
|
|
8
|
+
import { getSettingsPath, resolvePmRoot } from "../core/store/paths.js";
|
|
9
|
+
import { readSettings } from "../core/store/settings.js";
|
|
10
|
+
import { getActiveExtensionRegistrations } from "../core/extensions/index.js";
|
|
11
|
+
import { runClaim, runClose, runCompletion, runContracts, runGc, runHealth, runRelease, runStartBackgroundRun, runStats, runTest, runTestAll, runTestRunsList, runTestRunsLogs, runTestRunsResume, runTestRunsStatus, runTestRunsStop, runTestRunsWorker, runUpdate, runValidate, } from "./commands/index.js";
|
|
12
|
+
import { buildBackgroundTestAllCommandArgs, buildBackgroundTestCommandArgs, collect, getGlobalOptions, invalidateSearchCachesForMutation, printError, printResult, writeStdout, } from "./registration-helpers.js";
|
|
13
|
+
export function registerOperationCommands(program) {
|
|
14
|
+
program
|
|
15
|
+
.command("test")
|
|
16
|
+
.argument("<id>", "Item id")
|
|
17
|
+
.option("--add <value>", "Add linked test entry (CSV/markdown pairs or - for stdin)", collect)
|
|
18
|
+
.option("--remove <value>", "Remove linked test entry by command/path (command=<value>, path=<value>, markdown pairs, plain value, or - for stdin)", collect)
|
|
19
|
+
.option("--run", "Run linked test commands")
|
|
20
|
+
.option("--background", "Run linked tests in managed background mode")
|
|
21
|
+
.option("--timeout <seconds>", "Default run timeout in seconds")
|
|
22
|
+
.option("--progress", "Emit linked-test progress to stderr (always shown in TTY, opt-in for non-TTY)")
|
|
23
|
+
.option("--env-set <value>", "Set environment variable(s) for linked-test runs (KEY=VALUE, repeatable)", collect)
|
|
24
|
+
.option("--env-clear <value>", "Clear environment variable(s) for linked-test runs (NAME, repeatable)", collect)
|
|
25
|
+
.option("--shared-host-safe", "Apply additive shared-host-safe runtime defaults for linked-test runs")
|
|
26
|
+
.option("--pm-context <mode>", "PM linked-test context mode: schema|tracker|auto (default: schema)")
|
|
27
|
+
.option("--override-linked-pm-context", "Force run-level --pm-context to override per-linked-test pm_context_mode metadata")
|
|
28
|
+
.option("--fail-on-context-mismatch", "Fail linked PM commands when context item counts differ")
|
|
29
|
+
.option("--fail-on-skipped", "Treat skipped linked tests as dependency failures")
|
|
30
|
+
.option("--fail-on-empty-test-run", "Treat successful linked-test commands that report zero executed tests as failures")
|
|
31
|
+
.option("--require-assertions-for-pm", "Require assertion metadata for linked PM command tests")
|
|
32
|
+
.option("--check-context", "Preflight linked PM command context diagnostics before executing commands")
|
|
33
|
+
.option("--auto-pm-context", "Auto-remediate PM tracker-read context mismatches by routing those linked commands through tracker context")
|
|
34
|
+
.option("--author <value>", "Mutation author")
|
|
35
|
+
.option("--message <value>", "History message")
|
|
36
|
+
.option("--force", "Force ownership override")
|
|
37
|
+
.description("Manage tests linked to an item and optionally run them.")
|
|
38
|
+
.action(async (id, options, command) => {
|
|
39
|
+
const globalOptions = getGlobalOptions(command);
|
|
40
|
+
const startedAt = Date.now();
|
|
41
|
+
const addValues = Array.isArray(options.add) ? options.add : [];
|
|
42
|
+
const removeValues = Array.isArray(options.remove) ? options.remove : [];
|
|
43
|
+
const runInBackground = options.background === true;
|
|
44
|
+
if (runInBackground && options.run !== true) {
|
|
45
|
+
throw new PmCliError("--background requires --run", EXIT_CODE.USAGE);
|
|
46
|
+
}
|
|
47
|
+
if (runInBackground && (addValues.length > 0 || removeValues.length > 0)) {
|
|
48
|
+
throw new PmCliError("--background does not support --add/--remove; update linked tests first, then run in background", EXIT_CODE.USAGE);
|
|
49
|
+
}
|
|
50
|
+
if (runInBackground) {
|
|
51
|
+
const result = await runStartBackgroundRun({
|
|
52
|
+
kind: "test",
|
|
53
|
+
commandArgs: buildBackgroundTestCommandArgs(id, { ...options, add: addValues, remove: removeValues }),
|
|
54
|
+
targetId: id,
|
|
55
|
+
author: typeof options.author === "string" ? options.author : undefined,
|
|
56
|
+
noExtensions: globalOptions.noExtensions === true,
|
|
57
|
+
}, globalOptions);
|
|
58
|
+
printResult(result, globalOptions);
|
|
59
|
+
if (globalOptions.profile) {
|
|
60
|
+
printError(`profile:command=test took_ms=${Date.now() - startedAt}`);
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const result = await runTest(id, {
|
|
65
|
+
add: addValues,
|
|
66
|
+
remove: removeValues,
|
|
67
|
+
run: Boolean(options.run),
|
|
68
|
+
timeout: typeof options.timeout === "string" ? options.timeout : undefined,
|
|
69
|
+
progress: Boolean(options.progress),
|
|
70
|
+
envSet: Array.isArray(options.envSet) ? options.envSet : [],
|
|
71
|
+
envClear: Array.isArray(options.envClear) ? options.envClear : [],
|
|
72
|
+
sharedHostSafe: Boolean(options.sharedHostSafe),
|
|
73
|
+
pmContext: typeof options.pmContext === "string" ? options.pmContext : undefined,
|
|
74
|
+
overrideLinkedPmContext: Boolean(options.overrideLinkedPmContext),
|
|
75
|
+
failOnContextMismatch: Boolean(options.failOnContextMismatch),
|
|
76
|
+
failOnSkipped: Boolean(options.failOnSkipped),
|
|
77
|
+
failOnEmptyTestRun: Boolean(options.failOnEmptyTestRun),
|
|
78
|
+
requireAssertionsForPm: Boolean(options.requireAssertionsForPm),
|
|
79
|
+
checkContext: Boolean(options.checkContext),
|
|
80
|
+
autoPmContext: Boolean(options.autoPmContext),
|
|
81
|
+
author: typeof options.author === "string" ? options.author : undefined,
|
|
82
|
+
message: typeof options.message === "string" ? options.message : undefined,
|
|
83
|
+
force: Boolean(options.force),
|
|
84
|
+
}, globalOptions);
|
|
85
|
+
if (addValues.length > 0 || removeValues.length > 0 || options.run === true) {
|
|
86
|
+
await invalidateSearchCachesForMutation(globalOptions, result);
|
|
87
|
+
}
|
|
88
|
+
printResult(result, globalOptions);
|
|
89
|
+
if (result.run_results.some((entry) => entry.status === "failed") || result.fail_on_skipped_triggered === true) {
|
|
90
|
+
process.exitCode = EXIT_CODE.DEPENDENCY_FAILED;
|
|
91
|
+
}
|
|
92
|
+
if (globalOptions.profile) {
|
|
93
|
+
printError(`profile:command=test took_ms=${Date.now() - startedAt}`);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
program
|
|
97
|
+
.command("test-all")
|
|
98
|
+
.description("Run linked tests across matching items.")
|
|
99
|
+
.option("--status <value>", "Filter items by status before running tests")
|
|
100
|
+
.option("--limit <n>", "Limit matching items before running linked tests")
|
|
101
|
+
.option("--offset <n>", "Skip matching items before running linked tests")
|
|
102
|
+
.option("--background", "Run linked tests in managed background mode")
|
|
103
|
+
.option("--timeout <seconds>", "Default run timeout in seconds")
|
|
104
|
+
.option("--progress", "Emit linked-test progress to stderr (always shown in TTY, opt-in for non-TTY)")
|
|
105
|
+
.option("--env-set <value>", "Set environment variable(s) for linked-test runs (KEY=VALUE, repeatable)", collect)
|
|
106
|
+
.option("--env-clear <value>", "Clear environment variable(s) for linked-test runs (NAME, repeatable)", collect)
|
|
107
|
+
.option("--shared-host-safe", "Apply additive shared-host-safe runtime defaults for linked-test runs")
|
|
108
|
+
.option("--pm-context <mode>", "PM linked-test context mode: schema|tracker|auto (default: schema)")
|
|
109
|
+
.option("--override-linked-pm-context", "Force run-level --pm-context to override per-linked-test pm_context_mode metadata")
|
|
110
|
+
.option("--fail-on-context-mismatch", "Fail linked PM commands when context item counts differ")
|
|
111
|
+
.option("--fail-on-skipped", "Treat skipped linked tests as dependency failures")
|
|
112
|
+
.option("--fail-on-empty-test-run", "Treat successful linked-test commands that report zero executed tests as failures")
|
|
113
|
+
.option("--require-assertions-for-pm", "Require assertion metadata for linked PM command tests")
|
|
114
|
+
.option("--check-context", "Preflight linked PM command context diagnostics before executing commands")
|
|
115
|
+
.option("--auto-pm-context", "Auto-remediate PM tracker-read context mismatches by routing those linked commands through tracker context")
|
|
116
|
+
.action(async (options, command) => {
|
|
117
|
+
const globalOptions = getGlobalOptions(command);
|
|
118
|
+
const startedAt = Date.now();
|
|
119
|
+
const runInBackground = options.background === true;
|
|
120
|
+
if (runInBackground) {
|
|
121
|
+
const result = await runStartBackgroundRun({
|
|
122
|
+
kind: "test-all",
|
|
123
|
+
commandArgs: buildBackgroundTestAllCommandArgs(options),
|
|
124
|
+
statusFilter: typeof options.status === "string" ? options.status : undefined,
|
|
125
|
+
noExtensions: globalOptions.noExtensions === true,
|
|
126
|
+
}, globalOptions);
|
|
127
|
+
printResult(result, globalOptions);
|
|
128
|
+
if (globalOptions.profile) {
|
|
129
|
+
printError(`profile:command=test-all took_ms=${Date.now() - startedAt}`);
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const result = await runTestAll({
|
|
134
|
+
status: typeof options.status === "string" ? options.status : undefined,
|
|
135
|
+
limit: typeof options.limit === "string" ? options.limit : undefined,
|
|
136
|
+
offset: typeof options.offset === "string" ? options.offset : undefined,
|
|
137
|
+
timeout: typeof options.timeout === "string" ? options.timeout : undefined,
|
|
138
|
+
progress: Boolean(options.progress),
|
|
139
|
+
envSet: Array.isArray(options.envSet) ? options.envSet : [],
|
|
140
|
+
envClear: Array.isArray(options.envClear) ? options.envClear : [],
|
|
141
|
+
sharedHostSafe: Boolean(options.sharedHostSafe),
|
|
142
|
+
pmContext: typeof options.pmContext === "string" ? options.pmContext : undefined,
|
|
143
|
+
overrideLinkedPmContext: Boolean(options.overrideLinkedPmContext),
|
|
144
|
+
failOnContextMismatch: Boolean(options.failOnContextMismatch),
|
|
145
|
+
failOnSkipped: Boolean(options.failOnSkipped),
|
|
146
|
+
failOnEmptyTestRun: Boolean(options.failOnEmptyTestRun),
|
|
147
|
+
requireAssertionsForPm: Boolean(options.requireAssertionsForPm),
|
|
148
|
+
checkContext: Boolean(options.checkContext),
|
|
149
|
+
autoPmContext: Boolean(options.autoPmContext),
|
|
150
|
+
}, globalOptions);
|
|
151
|
+
await invalidateSearchCachesForMutation(globalOptions, { ids: result.results.map((entry) => entry.id) });
|
|
152
|
+
printResult(result, globalOptions);
|
|
153
|
+
if (result.failed > 0 || result.fail_on_skipped_triggered === true) {
|
|
154
|
+
process.exitCode = EXIT_CODE.DEPENDENCY_FAILED;
|
|
155
|
+
}
|
|
156
|
+
if (globalOptions.profile) {
|
|
157
|
+
printError(`profile:command=test-all took_ms=${Date.now() - startedAt}`);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
const testRunsCommand = program
|
|
161
|
+
.command("test-runs")
|
|
162
|
+
.description("Manage background linked-test runs.")
|
|
163
|
+
.action(async (_options, command) => {
|
|
164
|
+
const globalOptions = getGlobalOptions(command);
|
|
165
|
+
const startedAt = Date.now();
|
|
166
|
+
const result = await runTestRunsList({}, globalOptions);
|
|
167
|
+
printResult(result, globalOptions);
|
|
168
|
+
if (globalOptions.profile) {
|
|
169
|
+
printError(`profile:command=test-runs took_ms=${Date.now() - startedAt}`);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
testRunsCommand
|
|
173
|
+
.command("list")
|
|
174
|
+
.option("--status <value>", "Filter by background run status")
|
|
175
|
+
.option("--limit <value>", "Limit number of runs returned")
|
|
176
|
+
.description("List background test runs.")
|
|
177
|
+
.action(async (options, command) => {
|
|
178
|
+
const globalOptions = getGlobalOptions(command);
|
|
179
|
+
const startedAt = Date.now();
|
|
180
|
+
const result = await runTestRunsList({
|
|
181
|
+
status: typeof options.status === "string" ? options.status : undefined,
|
|
182
|
+
limit: typeof options.limit === "string" ? options.limit : undefined,
|
|
183
|
+
}, globalOptions);
|
|
184
|
+
printResult(result, globalOptions);
|
|
185
|
+
if (globalOptions.profile) {
|
|
186
|
+
printError(`profile:command=test-runs list took_ms=${Date.now() - startedAt}`);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
testRunsCommand
|
|
190
|
+
.command("status")
|
|
191
|
+
.argument("<runId>", "Background run id")
|
|
192
|
+
.description("Show status, health, and resource snapshot for a background run.")
|
|
193
|
+
.action(async (runId, _options, command) => {
|
|
194
|
+
const globalOptions = getGlobalOptions(command);
|
|
195
|
+
const startedAt = Date.now();
|
|
196
|
+
const result = await runTestRunsStatus(runId, globalOptions);
|
|
197
|
+
printResult(result, globalOptions);
|
|
198
|
+
if (globalOptions.profile) {
|
|
199
|
+
printError(`profile:command=test-runs status took_ms=${Date.now() - startedAt}`);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
testRunsCommand
|
|
203
|
+
.command("logs")
|
|
204
|
+
.argument("<runId>", "Background run id")
|
|
205
|
+
.option("--stream <value>", "Log stream selector: stdout|stderr|both")
|
|
206
|
+
.option("--tail <value>", "Tail number of lines per selected stream")
|
|
207
|
+
.description("Show tailed logs for a background run.")
|
|
208
|
+
.action(async (runId, options, command) => {
|
|
209
|
+
const globalOptions = getGlobalOptions(command);
|
|
210
|
+
const startedAt = Date.now();
|
|
211
|
+
const result = await runTestRunsLogs(runId, {
|
|
212
|
+
stream: typeof options.stream === "string" ? options.stream : undefined,
|
|
213
|
+
tail: typeof options.tail === "string" ? options.tail : undefined,
|
|
214
|
+
}, globalOptions);
|
|
215
|
+
printResult(result, globalOptions);
|
|
216
|
+
if (globalOptions.profile) {
|
|
217
|
+
printError(`profile:command=test-runs logs took_ms=${Date.now() - startedAt}`);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
testRunsCommand
|
|
221
|
+
.command("stop")
|
|
222
|
+
.argument("<runId>", "Background run id")
|
|
223
|
+
.option("--force", "Force-stop via SIGKILL")
|
|
224
|
+
.description("Stop a running background test run.")
|
|
225
|
+
.action(async (runId, options, command) => {
|
|
226
|
+
const globalOptions = getGlobalOptions(command);
|
|
227
|
+
const startedAt = Date.now();
|
|
228
|
+
const result = await runTestRunsStop(runId, { force: options.force === true }, globalOptions);
|
|
229
|
+
printResult(result, globalOptions);
|
|
230
|
+
if (globalOptions.profile) {
|
|
231
|
+
printError(`profile:command=test-runs stop took_ms=${Date.now() - startedAt}`);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
testRunsCommand
|
|
235
|
+
.command("resume")
|
|
236
|
+
.argument("<runId>", "Background run id")
|
|
237
|
+
.option("--author <value>", "Resume author (falls back to PM_AUTHOR/settings)")
|
|
238
|
+
.description("Resume a previously terminal background test run by starting a new attempt.")
|
|
239
|
+
.action(async (runId, options, command) => {
|
|
240
|
+
const globalOptions = getGlobalOptions(command);
|
|
241
|
+
const startedAt = Date.now();
|
|
242
|
+
const result = await runTestRunsResume(runId, {
|
|
243
|
+
author: typeof options.author === "string" ? options.author : undefined,
|
|
244
|
+
noExtensions: globalOptions.noExtensions === true,
|
|
245
|
+
}, globalOptions);
|
|
246
|
+
printResult(result, globalOptions);
|
|
247
|
+
if (globalOptions.profile) {
|
|
248
|
+
printError(`profile:command=test-runs resume took_ms=${Date.now() - startedAt}`);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
program
|
|
252
|
+
.command("test-runs-worker", { hidden: true })
|
|
253
|
+
.argument("<runId>", "Background run id")
|
|
254
|
+
.description("Internal background worker command.")
|
|
255
|
+
.action(async (runId, _options, command) => {
|
|
256
|
+
const globalOptions = getGlobalOptions(command);
|
|
257
|
+
await runTestRunsWorker(runId, globalOptions);
|
|
258
|
+
});
|
|
259
|
+
program
|
|
260
|
+
.command("stats")
|
|
261
|
+
.description("Show project tracker statistics.")
|
|
262
|
+
.action(async (_options, command) => {
|
|
263
|
+
const globalOptions = getGlobalOptions(command);
|
|
264
|
+
const startedAt = Date.now();
|
|
265
|
+
const result = await runStats(globalOptions);
|
|
266
|
+
printResult(result, globalOptions);
|
|
267
|
+
if (globalOptions.profile) {
|
|
268
|
+
printError(`profile:command=stats took_ms=${Date.now() - startedAt}`);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
program
|
|
272
|
+
.command("health")
|
|
273
|
+
.description("Show project tracker health checks.")
|
|
274
|
+
.option("--strict-directories", "Treat optional item-type directories as required failures")
|
|
275
|
+
.option("--check-only", "Run read-only health diagnostics without refreshing vectors")
|
|
276
|
+
.option("--check-telemetry", "Probe telemetry endpoint health and include network diagnostics")
|
|
277
|
+
.option("--no-refresh", "Disable automatic vector refresh attempts during health checks")
|
|
278
|
+
.option("--refresh-vectors", "Explicitly enable vector refresh attempts during health checks")
|
|
279
|
+
.option("--verbose-stale-items", "Include full stale vectorization ID lists in health output")
|
|
280
|
+
.option("--strict-exit", "Return non-zero exit when health warnings are present (ok=false)")
|
|
281
|
+
.option("--fail-on-warn", "Alias for --strict-exit")
|
|
282
|
+
.action(async (options, command) => {
|
|
283
|
+
const globalOptions = getGlobalOptions(command);
|
|
284
|
+
const startedAt = Date.now();
|
|
285
|
+
const result = await runHealth(globalOptions, {
|
|
286
|
+
strictDirectories: Boolean(options.strictDirectories),
|
|
287
|
+
checkOnly: Boolean(options.checkOnly),
|
|
288
|
+
checkTelemetry: Boolean(options.checkTelemetry),
|
|
289
|
+
noRefresh: Boolean(options.noRefresh),
|
|
290
|
+
refreshVectors: Boolean(options.refreshVectors),
|
|
291
|
+
verboseStaleItems: Boolean(options.verboseStaleItems),
|
|
292
|
+
});
|
|
293
|
+
printResult(result, globalOptions);
|
|
294
|
+
const strictExit = Boolean(options.strictExit) || Boolean(options.failOnWarn);
|
|
295
|
+
if (strictExit && !result.ok) {
|
|
296
|
+
process.exitCode = EXIT_CODE.GENERIC_FAILURE;
|
|
297
|
+
}
|
|
298
|
+
if (globalOptions.profile) {
|
|
299
|
+
printError(`profile:command=health took_ms=${Date.now() - startedAt}`);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
program
|
|
303
|
+
.command("validate")
|
|
304
|
+
.description("Run standalone metadata, resolution, lifecycle, files, linked-command reference, and history drift validation checks.")
|
|
305
|
+
.option("--check-metadata", "Run metadata completeness checks")
|
|
306
|
+
.option("--metadata-profile <value>", "Select metadata validation profile for --check-metadata (core|strict|custom)")
|
|
307
|
+
.option("--check-resolution", "Run closed-item resolution metadata checks")
|
|
308
|
+
.option("--check-lifecycle", "Run active-item lifecycle governance drift checks")
|
|
309
|
+
.option("--check-stale-blockers", "Include stale blocker-pattern diagnostics in lifecycle checks")
|
|
310
|
+
.option("--dependency-cycle-severity <value>", "Set dependency-cycle warning policy for lifecycle checks (off|warn|error)")
|
|
311
|
+
.option("--check-files", "Run linked-file and orphaned-file checks")
|
|
312
|
+
.option("--check-command-references", "Run linked-command PM-ID reference checks")
|
|
313
|
+
.option("--scan-mode <value>", "Select file candidate scan mode for --check-files (default|tracked-all|tracked-all-strict)")
|
|
314
|
+
.option("--include-pm-internals", "Include PM storage internals in tracked-all candidate scans")
|
|
315
|
+
.option("--verbose-file-lists", "Include full file-path lists for validate --check-files details")
|
|
316
|
+
.option("--strict-exit", "Return non-zero exit when validation warnings are present (ok=false)")
|
|
317
|
+
.option("--fail-on-warn", "Alias for --strict-exit")
|
|
318
|
+
.option("--check-history-drift", "Run item/history hash drift checks")
|
|
319
|
+
.action(async (options, command) => {
|
|
320
|
+
const globalOptions = getGlobalOptions(command);
|
|
321
|
+
const startedAt = Date.now();
|
|
322
|
+
const result = await runValidate({
|
|
323
|
+
checkMetadata: Boolean(options.checkMetadata),
|
|
324
|
+
metadataProfile: typeof options.metadataProfile === "string" ? options.metadataProfile : undefined,
|
|
325
|
+
checkResolution: Boolean(options.checkResolution),
|
|
326
|
+
checkLifecycle: Boolean(options.checkLifecycle),
|
|
327
|
+
checkStaleBlockers: Boolean(options.checkStaleBlockers),
|
|
328
|
+
dependencyCycleSeverity: typeof options.dependencyCycleSeverity === "string" ? options.dependencyCycleSeverity : undefined,
|
|
329
|
+
checkFiles: Boolean(options.checkFiles),
|
|
330
|
+
checkCommandReferences: Boolean(options.checkCommandReferences),
|
|
331
|
+
scanMode: typeof options.scanMode === "string" ? options.scanMode : undefined,
|
|
332
|
+
includePmInternals: Boolean(options.includePmInternals),
|
|
333
|
+
verboseFileLists: Boolean(options.verboseFileLists),
|
|
334
|
+
checkHistoryDrift: Boolean(options.checkHistoryDrift),
|
|
335
|
+
}, globalOptions);
|
|
336
|
+
printResult(result, globalOptions);
|
|
337
|
+
const strictExit = Boolean(options.strictExit) || Boolean(options.failOnWarn);
|
|
338
|
+
if (strictExit && !result.ok) {
|
|
339
|
+
process.exitCode = EXIT_CODE.GENERIC_FAILURE;
|
|
340
|
+
}
|
|
341
|
+
if (globalOptions.profile) {
|
|
342
|
+
printError(`profile:command=validate took_ms=${Date.now() - startedAt}`);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
program
|
|
346
|
+
.command("gc")
|
|
347
|
+
.option("--dry-run", "Preview cleanup targets without deleting files")
|
|
348
|
+
.option("--scope <value>", "Limit cleanup to one or more scopes (comma-separated or repeatable): index, embeddings, runtime", collect)
|
|
349
|
+
.description("Clean optional cache artifacts and show a summary.")
|
|
350
|
+
.action(async (options, command) => {
|
|
351
|
+
const globalOptions = getGlobalOptions(command);
|
|
352
|
+
const startedAt = Date.now();
|
|
353
|
+
const result = await runGc(globalOptions, {
|
|
354
|
+
dryRun: options.dryRun === true,
|
|
355
|
+
scope: Array.isArray(options.scope) ? options.scope : [],
|
|
356
|
+
});
|
|
357
|
+
printResult(result, globalOptions);
|
|
358
|
+
if (globalOptions.profile) {
|
|
359
|
+
printError(`profile:command=gc took_ms=${Date.now() - startedAt}`);
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
program
|
|
363
|
+
.command("contracts")
|
|
364
|
+
.description("Show machine-readable command and schema contracts for agents.")
|
|
365
|
+
.option("--action <value>", "Filter tool schema branches to a specific action")
|
|
366
|
+
.option("--command <value>", "Scope contracts output to one CLI command (narrow-by-default)")
|
|
367
|
+
.option("--schema-only", "Return schema-focused output only")
|
|
368
|
+
.option("--flags-only", "Return command flag contracts only")
|
|
369
|
+
.option("--availability-only", "Return action availability surface only")
|
|
370
|
+
.option("--runtime-only", "Include only actions invocable in the current runtime")
|
|
371
|
+
.option("--active-only", "Alias for --runtime-only")
|
|
372
|
+
.action(async (options, command) => {
|
|
373
|
+
const globalOptions = getGlobalOptions(command);
|
|
374
|
+
const startedAt = Date.now();
|
|
375
|
+
const result = await runContracts({
|
|
376
|
+
action: typeof options.action === "string" ? options.action : undefined,
|
|
377
|
+
command: typeof options.command === "string" ? options.command : undefined,
|
|
378
|
+
schemaOnly: Boolean(options.schemaOnly),
|
|
379
|
+
flagsOnly: Boolean(options.flagsOnly),
|
|
380
|
+
availabilityOnly: Boolean(options.availabilityOnly),
|
|
381
|
+
runtimeOnly: Boolean(options.runtimeOnly) || Boolean(options.activeOnly),
|
|
382
|
+
}, globalOptions);
|
|
383
|
+
printResult(result, globalOptions);
|
|
384
|
+
if (globalOptions.profile) {
|
|
385
|
+
printError(`profile:command=contracts took_ms=${Date.now() - startedAt}`);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
program
|
|
389
|
+
.command("claim")
|
|
390
|
+
.argument("<id>", "Item id")
|
|
391
|
+
.option("--author <value>", "Mutation author")
|
|
392
|
+
.option("--message <value>", "History message")
|
|
393
|
+
.option("--force", "Force claim override")
|
|
394
|
+
.description("Claim an item for active work.")
|
|
395
|
+
.action(async (id, options, command) => {
|
|
396
|
+
const globalOptions = getGlobalOptions(command);
|
|
397
|
+
const startedAt = Date.now();
|
|
398
|
+
const result = await runClaim(id, Boolean(options.force), globalOptions, {
|
|
399
|
+
author: typeof options.author === "string" ? options.author : undefined,
|
|
400
|
+
message: typeof options.message === "string" ? options.message : undefined,
|
|
401
|
+
});
|
|
402
|
+
await invalidateSearchCachesForMutation(globalOptions, result);
|
|
403
|
+
printResult(result, globalOptions);
|
|
404
|
+
if (globalOptions.profile) {
|
|
405
|
+
printError(`profile:command=claim took_ms=${Date.now() - startedAt}`);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
program
|
|
409
|
+
.command("release")
|
|
410
|
+
.argument("<id>", "Item id")
|
|
411
|
+
.option("--author <value>", "Mutation author")
|
|
412
|
+
.option("--message <value>", "History message")
|
|
413
|
+
.option("--allow-audit-release", "Allow non-owner release handoffs without requiring --force")
|
|
414
|
+
.option("--force", "Force release override")
|
|
415
|
+
.description("Release an item's active claim.")
|
|
416
|
+
.action(async (id, options, command) => {
|
|
417
|
+
const globalOptions = getGlobalOptions(command);
|
|
418
|
+
const startedAt = Date.now();
|
|
419
|
+
const result = await runRelease(id, Boolean(options.force), globalOptions, {
|
|
420
|
+
author: typeof options.author === "string" ? options.author : undefined,
|
|
421
|
+
message: typeof options.message === "string" ? options.message : undefined,
|
|
422
|
+
allowAuditRelease: options.allowAuditRelease === true,
|
|
423
|
+
});
|
|
424
|
+
await invalidateSearchCachesForMutation(globalOptions, result);
|
|
425
|
+
printResult(result, globalOptions);
|
|
426
|
+
if (globalOptions.profile) {
|
|
427
|
+
printError(`profile:command=release took_ms=${Date.now() - startedAt}`);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
program
|
|
431
|
+
.command("start-task")
|
|
432
|
+
.argument("<id>", "Item id")
|
|
433
|
+
.option("--author <value>", "Mutation author")
|
|
434
|
+
.option("--message <value>", "History message")
|
|
435
|
+
.option("--force", "Force ownership or terminal override when required")
|
|
436
|
+
.description("Lifecycle alias: claim an item and move it to in_progress.")
|
|
437
|
+
.action(async (id, options, command) => {
|
|
438
|
+
const globalOptions = getGlobalOptions(command);
|
|
439
|
+
const startedAt = Date.now();
|
|
440
|
+
const pmRoot = resolvePmRoot(process.cwd(), globalOptions.path);
|
|
441
|
+
const settings = await readSettings(pmRoot);
|
|
442
|
+
const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
|
|
443
|
+
const inProgressStatus = normalizeStatusInput("in_progress", statusRegistry) ?? statusRegistry.open_status;
|
|
444
|
+
const force = Boolean(options.force);
|
|
445
|
+
const mutationOptions = {
|
|
446
|
+
author: typeof options.author === "string" ? options.author : undefined,
|
|
447
|
+
message: typeof options.message === "string" ? options.message : undefined,
|
|
448
|
+
};
|
|
449
|
+
const claimResult = await runClaim(id, force, globalOptions, mutationOptions);
|
|
450
|
+
await invalidateSearchCachesForMutation(globalOptions, claimResult);
|
|
451
|
+
const updateResult = await runUpdate(id, { ...mutationOptions, status: inProgressStatus, force }, globalOptions);
|
|
452
|
+
await invalidateSearchCachesForMutation(globalOptions, updateResult);
|
|
453
|
+
printResult({ id, action: "start_task", claim: claimResult, update: updateResult }, globalOptions);
|
|
454
|
+
if (globalOptions.profile) {
|
|
455
|
+
printError(`profile:command=start-task took_ms=${Date.now() - startedAt}`);
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
program
|
|
459
|
+
.command("pause-task")
|
|
460
|
+
.argument("<id>", "Item id")
|
|
461
|
+
.option("--author <value>", "Mutation author")
|
|
462
|
+
.option("--message <value>", "History message")
|
|
463
|
+
.option("--force", "Force ownership override when required")
|
|
464
|
+
.description("Lifecycle alias: move an item to open and release its claim.")
|
|
465
|
+
.action(async (id, options, command) => {
|
|
466
|
+
const globalOptions = getGlobalOptions(command);
|
|
467
|
+
const startedAt = Date.now();
|
|
468
|
+
const pmRoot = resolvePmRoot(process.cwd(), globalOptions.path);
|
|
469
|
+
const settings = await readSettings(pmRoot);
|
|
470
|
+
const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
|
|
471
|
+
const openStatus = statusRegistry.open_status;
|
|
472
|
+
const force = Boolean(options.force);
|
|
473
|
+
const mutationOptions = {
|
|
474
|
+
author: typeof options.author === "string" ? options.author : undefined,
|
|
475
|
+
message: typeof options.message === "string" ? options.message : undefined,
|
|
476
|
+
};
|
|
477
|
+
const updateResult = await runUpdate(id, { ...mutationOptions, status: openStatus, force }, globalOptions);
|
|
478
|
+
await invalidateSearchCachesForMutation(globalOptions, updateResult);
|
|
479
|
+
const releaseResult = await runRelease(id, force, globalOptions, mutationOptions);
|
|
480
|
+
await invalidateSearchCachesForMutation(globalOptions, releaseResult);
|
|
481
|
+
printResult({ id, action: "pause_task", update: updateResult, release: releaseResult }, globalOptions);
|
|
482
|
+
if (globalOptions.profile) {
|
|
483
|
+
printError(`profile:command=pause-task took_ms=${Date.now() - startedAt}`);
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
program
|
|
487
|
+
.command("close-task")
|
|
488
|
+
.argument("<id>", "Item id")
|
|
489
|
+
.argument("<reason>", "Close reason text")
|
|
490
|
+
.option("--author <value>", "Mutation author")
|
|
491
|
+
.option("--message <value>", "History message")
|
|
492
|
+
.option("--validate-close <value>", "Close-time validation mode: off|warn|strict")
|
|
493
|
+
.option("--force", "Force ownership or terminal override when required")
|
|
494
|
+
.description("Lifecycle alias: close an item with reason and release assignment metadata.")
|
|
495
|
+
.action(async (id, reason, options, command) => {
|
|
496
|
+
const globalOptions = getGlobalOptions(command);
|
|
497
|
+
const startedAt = Date.now();
|
|
498
|
+
const force = Boolean(options.force);
|
|
499
|
+
const mutationOptions = {
|
|
500
|
+
author: typeof options.author === "string" ? options.author : undefined,
|
|
501
|
+
message: typeof options.message === "string" ? options.message : undefined,
|
|
502
|
+
};
|
|
503
|
+
const closeResult = await runClose(id, reason, {
|
|
504
|
+
...mutationOptions,
|
|
505
|
+
validateClose: typeof options.validateClose === "string" ? options.validateClose : undefined,
|
|
506
|
+
force,
|
|
507
|
+
}, globalOptions);
|
|
508
|
+
await invalidateSearchCachesForMutation(globalOptions, closeResult);
|
|
509
|
+
const releaseResult = await runRelease(id, force, globalOptions, mutationOptions);
|
|
510
|
+
await invalidateSearchCachesForMutation(globalOptions, releaseResult);
|
|
511
|
+
printResult({ id, action: "close_task", close: closeResult, release: releaseResult }, globalOptions);
|
|
512
|
+
if (globalOptions.profile) {
|
|
513
|
+
printError(`profile:command=close-task took_ms=${Date.now() - startedAt}`);
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
program
|
|
517
|
+
.command("completion")
|
|
518
|
+
.argument("<shell>", "Shell type: bash, zsh, or fish")
|
|
519
|
+
.option("--eager-tags", "Embed current tracker tags directly in generated scripts (legacy eager mode)")
|
|
520
|
+
.description("Generate shell completion for pm.")
|
|
521
|
+
.action(async (shell, options, command) => {
|
|
522
|
+
const globalOptions = getGlobalOptions(command);
|
|
523
|
+
const pmRoot = resolvePmRoot(process.cwd(), globalOptions.path);
|
|
524
|
+
let completionTypes;
|
|
525
|
+
let completionTags;
|
|
526
|
+
let completionStatuses;
|
|
527
|
+
const completionCommandFlags = {};
|
|
528
|
+
const eagerTags = Boolean(options.eagerTags);
|
|
529
|
+
if (await pathExists(getSettingsPath(pmRoot))) {
|
|
530
|
+
const settings = await readSettings(pmRoot);
|
|
531
|
+
const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
|
|
532
|
+
const runtimeFieldRegistry = resolveRuntimeFieldRegistry(settings.schema);
|
|
533
|
+
const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
|
|
534
|
+
completionTypes = typeRegistry.types;
|
|
535
|
+
completionStatuses = statusRegistry.definitions.map((definition) => definition.id);
|
|
536
|
+
for (const [commandKey, definitions] of runtimeFieldRegistry.command_to_fields.entries()) {
|
|
537
|
+
if (commandKey !== "list" &&
|
|
538
|
+
commandKey !== "create" &&
|
|
539
|
+
commandKey !== "update" &&
|
|
540
|
+
commandKey !== "search" &&
|
|
541
|
+
commandKey !== "calendar" &&
|
|
542
|
+
commandKey !== "context") {
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
const runtimeFlags = new Set();
|
|
546
|
+
for (const definition of definitions) {
|
|
547
|
+
runtimeFlags.add(`--${definition.cli_flag}`);
|
|
548
|
+
for (const alias of definition.cli_aliases) {
|
|
549
|
+
if (alias.startsWith("--") || (alias.startsWith("-") && !alias.startsWith("--"))) {
|
|
550
|
+
runtimeFlags.add(alias);
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
runtimeFlags.add(`--${alias}`);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
completionCommandFlags[commandKey] = [...runtimeFlags].sort((left, right) => left.localeCompare(right));
|
|
558
|
+
}
|
|
559
|
+
if (completionCommandFlags.update) {
|
|
560
|
+
completionCommandFlags["update-many"] = [...completionCommandFlags.update];
|
|
561
|
+
}
|
|
562
|
+
if (eagerTags) {
|
|
563
|
+
const items = await listAllFrontMatter(pmRoot, settings.item_format, typeRegistry.type_to_folder, undefined, settings.schema);
|
|
564
|
+
completionTags = [...new Set(items.flatMap((item) => item.tags ?? []).map((tag) => tag.trim()).filter((tag) => tag.length > 0))]
|
|
565
|
+
.sort((left, right) => left.localeCompare(right));
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
const result = runCompletion(shell, completionTypes, completionTags ?? [], eagerTags, {
|
|
569
|
+
statuses: completionStatuses,
|
|
570
|
+
command_flags: completionCommandFlags,
|
|
571
|
+
});
|
|
572
|
+
if (globalOptions.json) {
|
|
573
|
+
printResult(result, globalOptions);
|
|
574
|
+
}
|
|
575
|
+
else if (!globalOptions.quiet) {
|
|
576
|
+
writeStdout(`${result.script}\n`);
|
|
577
|
+
}
|
|
578
|
+
if (globalOptions.profile) {
|
|
579
|
+
printError(`profile:command=completion took_ms=0`);
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
program
|
|
583
|
+
.command("completion-tags", { hidden: true })
|
|
584
|
+
.description("Internal dynamic completion tag source.")
|
|
585
|
+
.action(async (_options, command) => {
|
|
586
|
+
const globalOptions = getGlobalOptions(command);
|
|
587
|
+
const startedAt = Date.now();
|
|
588
|
+
const pmRoot = resolvePmRoot(process.cwd(), globalOptions.path);
|
|
589
|
+
let tags = [];
|
|
590
|
+
if (await pathExists(getSettingsPath(pmRoot))) {
|
|
591
|
+
const settings = await readSettings(pmRoot);
|
|
592
|
+
const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
|
|
593
|
+
const items = await listAllFrontMatter(pmRoot, settings.item_format, typeRegistry.type_to_folder, undefined, settings.schema);
|
|
594
|
+
tags = [...new Set(items.flatMap((item) => item.tags ?? []).map((tag) => tag.trim()).filter((tag) => tag.length > 0))].sort((left, right) => left.localeCompare(right));
|
|
595
|
+
}
|
|
596
|
+
if (globalOptions.json) {
|
|
597
|
+
printResult({ tags, count: tags.length }, globalOptions);
|
|
598
|
+
}
|
|
599
|
+
else if (!globalOptions.quiet) {
|
|
600
|
+
writeStdout(tags.join("\n"));
|
|
601
|
+
if (tags.length > 0) {
|
|
602
|
+
writeStdout("\n");
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
if (globalOptions.profile) {
|
|
606
|
+
printError(`profile:command=completion-tags took_ms=${Date.now() - startedAt}`);
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
//# sourceMappingURL=register-operations.js.map
|