@unbrained/pm-cli 2026.6.11 → 2026.6.12
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 +28 -0
- package/dist/cli/commands/completion.js +20 -8
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/create.js +6 -3
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +2 -0
- package/dist/cli/commands/docs.js +2 -2
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/files.d.ts +2 -0
- package/dist/cli/commands/files.js +2 -2
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/health.d.ts +1 -1
- package/dist/cli/commands/health.js +77 -2
- package/dist/cli/commands/health.js.map +1 -1
- package/dist/cli/commands/history-repair.d.ts +36 -0
- package/dist/cli/commands/history-repair.js +68 -3
- package/dist/cli/commands/history-repair.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.js +3 -3
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/linked-artifacts.d.ts +18 -0
- package/dist/cli/commands/linked-artifacts.js +26 -3
- package/dist/cli/commands/linked-artifacts.js.map +1 -1
- package/dist/cli/commands/plan.d.ts +6 -0
- package/dist/cli/commands/plan.js +93 -32
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +20 -0
- package/dist/cli/commands/validate.js +292 -28
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/help-content.js +7 -3
- package/dist/cli/help-content.js.map +1 -1
- package/dist/cli/register-mutation.js +47 -16
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-operations.js +10 -2
- package/dist/cli/register-operations.js.map +1 -1
- package/dist/cli/register-setup.js +16 -16
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli-bundle/chunks/{chunk-P2PSODAQ.js → chunk-35P4GT6E.js} +110 -9
- package/dist/cli-bundle/chunks/chunk-35P4GT6E.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-B65UUCGQ.js → chunk-37CYVF73.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-J3GD64J2.js → chunk-7AMK6DOW.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-J3GD64J2.js.map → chunk-7AMK6DOW.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-IKOH24GZ.js → chunk-AX4GEVQC.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-IKOH24GZ.js.map → chunk-AX4GEVQC.js.map} +2 -2
- package/dist/cli-bundle/chunks/chunk-C6SAP27O.js +187 -0
- package/dist/cli-bundle/chunks/chunk-C6SAP27O.js.map +1 -0
- package/dist/cli-bundle/chunks/chunk-EKS6O2IR.js +217 -0
- package/dist/cli-bundle/chunks/chunk-EKS6O2IR.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-PSD7F7DX.js → chunk-KBPQHXWG.js} +17 -4
- package/dist/cli-bundle/chunks/chunk-KBPQHXWG.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-3SLOMKCJ.js → chunk-L5EPZQIC.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-NAWVUHXH.js +220 -0
- package/dist/cli-bundle/chunks/chunk-NAWVUHXH.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-UOO6BYIA.js → chunk-PNYAAB4S.js} +21 -188
- package/dist/cli-bundle/chunks/chunk-PNYAAB4S.js.map +1 -0
- package/dist/cli-bundle/chunks/chunk-R2OUQVBK.js +190 -0
- package/dist/cli-bundle/chunks/chunk-R2OUQVBK.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-LCSCXBGT.js → chunk-R4VWYWRN.js} +19 -193
- package/dist/cli-bundle/chunks/chunk-R4VWYWRN.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-7RIT3OCD.js → chunk-SO55HRA5.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-FXRU333M.js → chunk-UIG4TW2H.js} +110 -9
- package/dist/cli-bundle/chunks/chunk-UIG4TW2H.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-E5DUIJA4.js → chunk-WPDMBIX6.js} +16 -3
- package/dist/cli-bundle/chunks/chunk-WPDMBIX6.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-IH4MBKK7.js → chunk-XWMF3POR.js} +2 -2
- package/dist/cli-bundle/chunks/{contracts-3NKWYKKU.js → contracts-2G66IGIA.js} +2 -2
- package/dist/cli-bundle/chunks/{contracts-MIXBWJIB.js → contracts-PJCHYSO5.js} +2 -2
- package/dist/cli-bundle/chunks/{create-IFA26O2I.js → create-5433DP3G.js} +2 -2
- package/dist/cli-bundle/chunks/{create-JVXYHYH4.js → create-VWLWS34Z.js} +2 -2
- package/dist/cli-bundle/chunks/{docs-5WMBVQT2.js → docs-I3BAF5WH.js} +4 -4
- package/dist/cli-bundle/chunks/docs-I3BAF5WH.js.map +1 -0
- package/dist/cli-bundle/chunks/{docs-MB53UJAJ.js → docs-MXLGZUIT.js} +3 -3
- package/dist/cli-bundle/chunks/docs-MXLGZUIT.js.map +7 -0
- package/dist/cli-bundle/chunks/{files-GVMNVLCB.js → files-FYP3MDPX.js} +3 -3
- package/dist/cli-bundle/chunks/files-FYP3MDPX.js.map +7 -0
- package/dist/cli-bundle/chunks/{files-DLB5LJEP.js → files-GUXUM2MB.js} +4 -4
- package/dist/cli-bundle/chunks/files-GUXUM2MB.js.map +1 -0
- package/dist/cli-bundle/chunks/{gc-2WEPW6D6.js → gc-FENB2ESG.js} +12 -174
- package/dist/cli-bundle/chunks/gc-FENB2ESG.js.map +1 -0
- package/dist/cli-bundle/chunks/{gc-4Z3IKHAZ.js → gc-KGQG66SA.js} +10 -179
- package/dist/cli-bundle/chunks/gc-KGQG66SA.js.map +7 -0
- package/dist/cli-bundle/chunks/{health-YO5LRWN4.js → health-7MTXAVR2.js} +71 -4
- package/dist/cli-bundle/chunks/health-7MTXAVR2.js.map +7 -0
- package/dist/cli-bundle/chunks/{health-4ZYB3IYQ.js → health-E4D7KGHD.js} +72 -5
- package/dist/cli-bundle/chunks/health-E4D7KGHD.js.map +1 -0
- package/dist/cli-bundle/chunks/{history-repair-KVPFJKOS.js → history-repair-OSQOKJ3E.js} +61 -3
- package/dist/cli-bundle/chunks/history-repair-OSQOKJ3E.js.map +7 -0
- package/dist/cli-bundle/chunks/{history-repair-RUGKD3YR.js → history-repair-SBK7P34V.js} +62 -4
- package/dist/cli-bundle/chunks/history-repair-SBK7P34V.js.map +1 -0
- package/dist/cli-bundle/chunks/{plan-VNUG3WZZ.js → plan-2YTQYWGM.js} +52 -12
- package/dist/cli-bundle/chunks/plan-2YTQYWGM.js.map +1 -0
- package/dist/cli-bundle/chunks/{plan-FQLMJRLZ.js → plan-7IVSICR6.js} +51 -11
- package/dist/cli-bundle/chunks/plan-7IVSICR6.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-list-query-VHDXWEPP.js → register-list-query-4UPMHONX.js} +3 -3
- package/dist/cli-bundle/chunks/{register-list-query-NPE3ECJQ.js → register-list-query-7VOW2C3W.js} +3 -3
- package/dist/cli-bundle/chunks/{register-mutation-EAYNLGOS.js → register-mutation-FARSGYRD.js} +43 -26
- package/dist/cli-bundle/chunks/{register-mutation-EAYNLGOS.js.map → register-mutation-FARSGYRD.js.map} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-DG53FCBV.js → register-mutation-LJDNVREU.js} +44 -27
- package/dist/cli-bundle/chunks/{register-mutation-DG53FCBV.js.map → register-mutation-LJDNVREU.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-operations-AM6KTWB6.js → register-operations-FFTYAL42.js} +17 -13
- package/dist/cli-bundle/chunks/register-operations-FFTYAL42.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-operations-FWFE64JG.js → register-operations-HCJKDUA6.js} +16 -12
- package/dist/cli-bundle/chunks/{register-operations-FWFE64JG.js.map → register-operations-HCJKDUA6.js.map} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-IKX5524L.js → register-setup-6AVIUOCC.js} +19 -19
- package/dist/cli-bundle/chunks/register-setup-6AVIUOCC.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-setup-G4QYI3RX.js → register-setup-KVNLO5OJ.js} +18 -18
- package/dist/cli-bundle/chunks/register-setup-KVNLO5OJ.js.map +7 -0
- package/dist/cli-bundle/chunks/{update-2EVXOC7V.js → update-36JM7YZT.js} +3 -3
- package/dist/cli-bundle/chunks/{update-5A2B6QYB.js → update-I246PCLO.js} +3 -3
- package/dist/cli-bundle/chunks/{update-many-V4LA3C4H.js → update-many-F4IKDWZB.js} +3 -3
- package/dist/cli-bundle/chunks/{update-many-TUGU5YXQ.js → update-many-NTWZ5YT3.js} +3 -3
- package/dist/cli-bundle/chunks/{validate-EQTT6WVX.js → validate-46KCRHL7.js} +448 -36
- package/dist/cli-bundle/chunks/validate-46KCRHL7.js.map +1 -0
- package/dist/cli-bundle/chunks/{validate-XN4I4DPL.js → validate-CRFMPTYD.js} +468 -35
- package/dist/cli-bundle/chunks/validate-CRFMPTYD.js.map +7 -0
- package/dist/cli-bundle/main.js +24 -10
- package/dist/cli-bundle/main.js.map +2 -2
- package/dist/core/diagnostics/remediation.js +19 -6
- package/dist/core/diagnostics/remediation.js.map +1 -1
- package/dist/core/lock/lock-gc.d.ts +31 -0
- package/dist/core/lock/lock-gc.js +120 -62
- package/dist/core/lock/lock-gc.js.map +1 -1
- package/dist/core/telemetry/consent.js +18 -3
- package/dist/core/telemetry/consent.js.map +1 -1
- package/dist/core/validate/fix-planning.d.ts +130 -0
- package/dist/core/validate/fix-planning.js +202 -0
- package/dist/core/validate/fix-planning.js.map +1 -0
- package/dist/core/validate/missing-by-type.d.ts +21 -0
- package/dist/core/validate/missing-by-type.js +39 -0
- package/dist/core/validate/missing-by-type.js.map +1 -0
- package/dist/core/validate/stale-file-classification.d.ts +41 -0
- package/dist/core/validate/stale-file-classification.js +73 -0
- package/dist/core/validate/stale-file-classification.js.map +1 -0
- package/dist/mcp/server.js +41 -8
- package/dist/mcp/server.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +38 -2
- package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -1
- package/dist/sdk/cli-contracts.d.ts +6 -1
- package/dist/sdk/cli-contracts.js +74 -7
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/docs/AGENT_GUIDE.md +6 -1
- package/docs/COMMANDS.md +23 -1
- package/package.json +1 -1
- package/dist/cli-bundle/chunks/chunk-E5DUIJA4.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-FXRU333M.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-LCSCXBGT.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-P2PSODAQ.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-PSD7F7DX.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-UOO6BYIA.js.map +0 -1
- package/dist/cli-bundle/chunks/docs-5WMBVQT2.js.map +0 -1
- package/dist/cli-bundle/chunks/docs-MB53UJAJ.js.map +0 -7
- package/dist/cli-bundle/chunks/files-DLB5LJEP.js.map +0 -1
- package/dist/cli-bundle/chunks/files-GVMNVLCB.js.map +0 -7
- package/dist/cli-bundle/chunks/gc-2WEPW6D6.js.map +0 -1
- package/dist/cli-bundle/chunks/gc-4Z3IKHAZ.js.map +0 -7
- package/dist/cli-bundle/chunks/health-4ZYB3IYQ.js.map +0 -1
- package/dist/cli-bundle/chunks/health-YO5LRWN4.js.map +0 -7
- package/dist/cli-bundle/chunks/history-repair-KVPFJKOS.js.map +0 -7
- package/dist/cli-bundle/chunks/history-repair-RUGKD3YR.js.map +0 -1
- package/dist/cli-bundle/chunks/plan-FQLMJRLZ.js.map +0 -7
- package/dist/cli-bundle/chunks/plan-VNUG3WZZ.js.map +0 -1
- package/dist/cli-bundle/chunks/register-operations-AM6KTWB6.js.map +0 -1
- package/dist/cli-bundle/chunks/register-setup-G4QYI3RX.js.map +0 -7
- package/dist/cli-bundle/chunks/register-setup-IKX5524L.js.map +0 -1
- package/dist/cli-bundle/chunks/validate-EQTT6WVX.js.map +0 -1
- package/dist/cli-bundle/chunks/validate-XN4I4DPL.js.map +0 -7
- /package/dist/cli-bundle/chunks/{chunk-B65UUCGQ.js.map → chunk-37CYVF73.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-3SLOMKCJ.js.map → chunk-L5EPZQIC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-7RIT3OCD.js.map → chunk-SO55HRA5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-IH4MBKK7.js.map → chunk-XWMF3POR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{contracts-3NKWYKKU.js.map → contracts-2G66IGIA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{contracts-MIXBWJIB.js.map → contracts-PJCHYSO5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-IFA26O2I.js.map → create-5433DP3G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-JVXYHYH4.js.map → create-VWLWS34Z.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-list-query-VHDXWEPP.js.map → register-list-query-4UPMHONX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-list-query-NPE3ECJQ.js.map → register-list-query-7VOW2C3W.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-2EVXOC7V.js.map → update-36JM7YZT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-5A2B6QYB.js.map → update-I246PCLO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-V4LA3C4H.js.map → update-many-F4IKDWZB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-TUGU5YXQ.js.map → update-many-NTWZ5YT3.js.map} +0 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="50b9ae79-2f9d-56b7-8b52-24c0a6416cd8")}catch(e){}}();
|
|
3
3
|
import {
|
|
4
|
-
buildRemediationCommands
|
|
5
|
-
|
|
6
|
-
} from "./chunk-UOO6BYIA.js";
|
|
4
|
+
buildRemediationCommands
|
|
5
|
+
} from "./chunk-PNYAAB4S.js";
|
|
7
6
|
import {
|
|
8
7
|
extractReferencedPmItemIdsFromCommand
|
|
9
8
|
} from "./chunk-EWFY7SLA.js";
|
|
9
|
+
import {
|
|
10
|
+
scanHistoryDrift
|
|
11
|
+
} from "./chunk-C6SAP27O.js";
|
|
10
12
|
import "./chunk-ZYNJNPYD.js";
|
|
11
13
|
import "./chunk-4HFU4UO2.js";
|
|
12
14
|
import "./chunk-I7NYDZDV.js";
|
|
@@ -49,6 +51,205 @@ import { realpathSync } from "node:fs";
|
|
|
49
51
|
import { execFile } from "node:child_process";
|
|
50
52
|
import path from "node:path";
|
|
51
53
|
import { promisify } from "node:util";
|
|
54
|
+
|
|
55
|
+
// dist/core/validate/fix-planning.js
|
|
56
|
+
var DEFAULT_GRANTED_FIX_SCOPES = ["metadata", "resolution"];
|
|
57
|
+
var SUPPORTED_FIX_SCOPES = ["metadata", "resolution", "lifecycle"];
|
|
58
|
+
var DEFAULT_RESOLUTION_BACKFILL_VALUE = "completed";
|
|
59
|
+
function quoteForCommand(value) {
|
|
60
|
+
return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
|
|
61
|
+
}
|
|
62
|
+
function toMeaningfulValue(value) {
|
|
63
|
+
const trimmed = value?.trim();
|
|
64
|
+
return trimmed !== void 0 && trimmed.length > 0 ? trimmed : void 0;
|
|
65
|
+
}
|
|
66
|
+
function planResolutionBackfillFixes(rows) {
|
|
67
|
+
const fixes = [];
|
|
68
|
+
for (const row of rows) {
|
|
69
|
+
if (!row.missing_fields.includes("resolution")) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const value = toMeaningfulValue(row.close_reason) ?? DEFAULT_RESOLUTION_BACKFILL_VALUE;
|
|
73
|
+
fixes.push({
|
|
74
|
+
item_id: row.id,
|
|
75
|
+
check: "resolution",
|
|
76
|
+
field: "resolution",
|
|
77
|
+
kind: "set_resolution",
|
|
78
|
+
value,
|
|
79
|
+
command: `pm update ${row.id} --resolution ${quoteForCommand(value)}`,
|
|
80
|
+
gate: "resolution"
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return fixes;
|
|
84
|
+
}
|
|
85
|
+
function planCloseReasonBackfillFixes(rows) {
|
|
86
|
+
const fixes = [];
|
|
87
|
+
for (const row of rows) {
|
|
88
|
+
const value = toMeaningfulValue(row.resolution);
|
|
89
|
+
if (value === void 0) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
fixes.push({
|
|
93
|
+
item_id: row.id,
|
|
94
|
+
check: "metadata",
|
|
95
|
+
field: "close_reason",
|
|
96
|
+
kind: "set_close_reason",
|
|
97
|
+
value,
|
|
98
|
+
command: `pm update ${row.id} --close-reason ${quoteForCommand(value)}`,
|
|
99
|
+
gate: "metadata"
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return fixes;
|
|
103
|
+
}
|
|
104
|
+
function planTerminalParentFixes(rows) {
|
|
105
|
+
return rows.map((row) => {
|
|
106
|
+
if (row.grandparent_id !== void 0 && row.grandparent_active === true) {
|
|
107
|
+
return {
|
|
108
|
+
item_id: row.id,
|
|
109
|
+
check: "lifecycle",
|
|
110
|
+
field: "parent",
|
|
111
|
+
kind: "reparent",
|
|
112
|
+
parent_id: row.grandparent_id,
|
|
113
|
+
command: `pm update ${row.id} --parent ${row.grandparent_id}`,
|
|
114
|
+
gate: "lifecycle"
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
item_id: row.id,
|
|
119
|
+
check: "lifecycle",
|
|
120
|
+
field: "parent",
|
|
121
|
+
kind: "unset_parent",
|
|
122
|
+
command: `pm update ${row.id} --unset parent`,
|
|
123
|
+
gate: "lifecycle"
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function planStaleLinkPruneFixes(rows) {
|
|
128
|
+
const fixes = [];
|
|
129
|
+
for (const row of rows) {
|
|
130
|
+
if (row.classification !== "deleted") {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const noun = row.link_kind === "files" ? "files" : "docs";
|
|
134
|
+
fixes.push({
|
|
135
|
+
item_id: row.item_id,
|
|
136
|
+
check: "files",
|
|
137
|
+
field: row.link_kind,
|
|
138
|
+
kind: row.link_kind === "files" ? "prune_file_link" : "prune_doc_link",
|
|
139
|
+
path: row.path,
|
|
140
|
+
command: `pm ${noun} ${row.item_id} --remove ${quoteForCommand(row.path)}`
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return fixes;
|
|
144
|
+
}
|
|
145
|
+
function resolveGrantedFixScopes(rawScopes) {
|
|
146
|
+
const tokens = (rawScopes ?? []).flatMap((raw) => raw.split(",")).map((raw) => raw.trim()).filter((raw) => raw.length > 0);
|
|
147
|
+
if (tokens.length === 0) {
|
|
148
|
+
if (rawScopes !== void 0 && rawScopes.length > 0) {
|
|
149
|
+
throw new PmCliError(`--fix-scope values must not be empty. Supported values: ${SUPPORTED_FIX_SCOPES.join(", ")}.`, EXIT_CODE.USAGE);
|
|
150
|
+
}
|
|
151
|
+
return new Set(DEFAULT_GRANTED_FIX_SCOPES);
|
|
152
|
+
}
|
|
153
|
+
const granted = /* @__PURE__ */ new Set();
|
|
154
|
+
for (const raw of tokens) {
|
|
155
|
+
const normalized = raw.toLowerCase().replaceAll("-", "_");
|
|
156
|
+
if (SUPPORTED_FIX_SCOPES.includes(normalized)) {
|
|
157
|
+
granted.add(normalized);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
throw new PmCliError(`Unknown --fix-scope value "${raw}". Supported values: ${SUPPORTED_FIX_SCOPES.join(", ")}.`, EXIT_CODE.USAGE);
|
|
161
|
+
}
|
|
162
|
+
return granted;
|
|
163
|
+
}
|
|
164
|
+
function partitionFixesByGrant(fixes, granted) {
|
|
165
|
+
const applicable = [];
|
|
166
|
+
const gated = [];
|
|
167
|
+
for (const fix of fixes) {
|
|
168
|
+
if (fix.gate !== void 0 && !granted.has(fix.gate)) {
|
|
169
|
+
gated.push(fix);
|
|
170
|
+
} else {
|
|
171
|
+
applicable.push(fix);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return { applicable, gated };
|
|
175
|
+
}
|
|
176
|
+
function toFixOutputRow(fix) {
|
|
177
|
+
return {
|
|
178
|
+
item_id: fix.item_id,
|
|
179
|
+
check: fix.check,
|
|
180
|
+
field: fix.field,
|
|
181
|
+
command: fix.command,
|
|
182
|
+
...fix.gate !== void 0 ? { gate: fix.gate } : {}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// dist/core/validate/missing-by-type.js
|
|
187
|
+
function buildMissingByTypeCounts(occurrences) {
|
|
188
|
+
const countsByType = /* @__PURE__ */ new Map();
|
|
189
|
+
for (const occurrence of occurrences) {
|
|
190
|
+
let fieldCounts = countsByType.get(occurrence.item_type);
|
|
191
|
+
if (!fieldCounts) {
|
|
192
|
+
fieldCounts = /* @__PURE__ */ new Map();
|
|
193
|
+
countsByType.set(occurrence.item_type, fieldCounts);
|
|
194
|
+
}
|
|
195
|
+
fieldCounts.set(occurrence.field, (fieldCounts.get(occurrence.field) ?? 0) + 1);
|
|
196
|
+
}
|
|
197
|
+
const result = {};
|
|
198
|
+
for (const type of [...countsByType.keys()].sort((left, right) => left.localeCompare(right))) {
|
|
199
|
+
const fieldCounts = countsByType.get(type);
|
|
200
|
+
const fields = {};
|
|
201
|
+
for (const field of [...fieldCounts.keys()].sort((left, right) => left.localeCompare(right))) {
|
|
202
|
+
fields[field] = fieldCounts.get(field);
|
|
203
|
+
}
|
|
204
|
+
result[type] = fields;
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// dist/core/validate/stale-file-classification.js
|
|
210
|
+
var DEFAULT_STALE_PATH_CANDIDATE_LIMIT = 3;
|
|
211
|
+
function basenameOf(relativePath) {
|
|
212
|
+
const lastSlash = Math.max(relativePath.lastIndexOf("/"), relativePath.lastIndexOf("\\"));
|
|
213
|
+
return lastSlash === -1 ? relativePath : relativePath.slice(lastSlash + 1);
|
|
214
|
+
}
|
|
215
|
+
function classifyStaleLinkedPaths(stalePaths, candidateFiles, candidateLimit = DEFAULT_STALE_PATH_CANDIDATE_LIMIT) {
|
|
216
|
+
const limit = Number.isFinite(candidateLimit) && candidateLimit >= 1 ? Math.floor(candidateLimit) : DEFAULT_STALE_PATH_CANDIDATE_LIMIT;
|
|
217
|
+
const candidatesByBasename = /* @__PURE__ */ new Map();
|
|
218
|
+
for (const candidate of candidateFiles) {
|
|
219
|
+
const basename = basenameOf(candidate);
|
|
220
|
+
if (basename.length === 0) {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
const bucket = candidatesByBasename.get(basename);
|
|
224
|
+
if (bucket) {
|
|
225
|
+
bucket.push(candidate);
|
|
226
|
+
} else {
|
|
227
|
+
candidatesByBasename.set(basename, [candidate]);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return stalePaths.map((stalePath) => {
|
|
231
|
+
const matches = (candidatesByBasename.get(basenameOf(stalePath)) ?? []).filter((candidate) => candidate !== stalePath).sort((left, right) => left.localeCompare(right));
|
|
232
|
+
if (matches.length === 0) {
|
|
233
|
+
return {
|
|
234
|
+
path: stalePath,
|
|
235
|
+
classification: "deleted",
|
|
236
|
+
candidates: [],
|
|
237
|
+
candidates_truncated: false
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
path: stalePath,
|
|
242
|
+
classification: "moved",
|
|
243
|
+
candidates: matches.slice(0, limit),
|
|
244
|
+
candidates_truncated: matches.length > limit
|
|
245
|
+
};
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
function summarizeStaleLinkedPathClassifications(classified) {
|
|
249
|
+
return classified.map((entry) => entry.classification === "moved" ? `${entry.path}:moved:${entry.candidates[0]}` : `${entry.path}:deleted`);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// dist/cli/commands/validate.js
|
|
52
253
|
var FILE_SCAN_DIRECTORIES = ["src", "tests", "docs"];
|
|
53
254
|
var FILE_SCAN_ROOT_FILES = [
|
|
54
255
|
"README.md",
|
|
@@ -520,17 +721,32 @@ function resolveRequestedChecks(options) {
|
|
|
520
721
|
requested.add("command_references");
|
|
521
722
|
}
|
|
522
723
|
if (requested.size === 0) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
724
|
+
if (options.autoFix) {
|
|
725
|
+
requested.add("metadata");
|
|
726
|
+
requested.add("resolution");
|
|
727
|
+
requested.add("lifecycle");
|
|
728
|
+
}
|
|
729
|
+
if (options.pruneMissing) {
|
|
730
|
+
requested.add("files");
|
|
731
|
+
}
|
|
732
|
+
if (requested.size === 0) {
|
|
733
|
+
requested.add("metadata");
|
|
734
|
+
requested.add("resolution");
|
|
735
|
+
requested.add("lifecycle");
|
|
736
|
+
requested.add("files");
|
|
737
|
+
requested.add("command_references");
|
|
738
|
+
requested.add("history_drift");
|
|
739
|
+
}
|
|
740
|
+
return requested;
|
|
741
|
+
}
|
|
742
|
+
if (options.pruneMissing) {
|
|
526
743
|
requested.add("files");
|
|
527
|
-
requested.add("command_references");
|
|
528
|
-
requested.add("history_drift");
|
|
529
744
|
}
|
|
530
745
|
return requested;
|
|
531
746
|
}
|
|
532
747
|
function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagnostics) {
|
|
533
748
|
const missingByField = Object.fromEntries(SUPPORTED_METADATA_REQUIRED_FIELDS.map((field) => [field, []]));
|
|
749
|
+
const itemsById = new Map(items.map((item) => [item.id, item]));
|
|
534
750
|
for (const item of items) {
|
|
535
751
|
for (const field of SUPPORTED_METADATA_REQUIRED_FIELDS) {
|
|
536
752
|
if (!isMetadataFieldMissing(item, field, statusRegistry)) {
|
|
@@ -555,6 +771,14 @@ function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagno
|
|
|
555
771
|
counts[countKey] = value;
|
|
556
772
|
}
|
|
557
773
|
}
|
|
774
|
+
const missingFieldOccurrences = [];
|
|
775
|
+
for (const field of metadataPolicy.required_fields) {
|
|
776
|
+
for (const itemId of missingByField[field] ?? []) {
|
|
777
|
+
const itemType = itemsById.get(itemId)?.type;
|
|
778
|
+
missingFieldOccurrences.push({ item_type: typeof itemType === "string" && itemType.length > 0 ? itemType : "Unknown", field });
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
const missingByType = buildMissingByTypeCounts(missingFieldOccurrences);
|
|
558
782
|
const details = {
|
|
559
783
|
checked_items: items.length,
|
|
560
784
|
metadata_profile: metadataPolicy.profile,
|
|
@@ -562,7 +786,8 @@ function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagno
|
|
|
562
786
|
metadata_profile_fallback_to_core: metadataPolicy.fallback_to_core,
|
|
563
787
|
required_fields: [...metadataPolicy.required_fields],
|
|
564
788
|
supported_required_fields: [...SUPPORTED_METADATA_REQUIRED_FIELDS],
|
|
565
|
-
counts
|
|
789
|
+
counts,
|
|
790
|
+
missing_by_type: missingByType
|
|
566
791
|
};
|
|
567
792
|
if (metadataPolicy.configured_custom_fields.length > 0) {
|
|
568
793
|
details.configured_custom_required_fields = [...metadataPolicy.configured_custom_fields];
|
|
@@ -581,13 +806,18 @@ function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagno
|
|
|
581
806
|
details[idsKey] = summarized.values;
|
|
582
807
|
details[truncatedKey] = summarized.truncated;
|
|
583
808
|
}
|
|
809
|
+
const closeReasonBackfillRows = metadataPolicy.required_fields.includes("close_reason") ? (missingByField.close_reason ?? []).map((itemId) => ({
|
|
810
|
+
id: itemId,
|
|
811
|
+
resolution: toNonEmptyStringOrUndefined(itemsById.get(itemId)?.resolution)
|
|
812
|
+
})) : [];
|
|
584
813
|
return {
|
|
585
814
|
check: {
|
|
586
815
|
name: "metadata",
|
|
587
816
|
status: warningTokens.length === 0 ? "ok" : "warn",
|
|
588
817
|
details
|
|
589
818
|
},
|
|
590
|
-
warnings: warningTokens
|
|
819
|
+
warnings: warningTokens,
|
|
820
|
+
closeReasonBackfillRows
|
|
591
821
|
};
|
|
592
822
|
}
|
|
593
823
|
function buildResolutionCheck(items, statusRegistry, verboseDiagnostics) {
|
|
@@ -595,6 +825,7 @@ function buildResolutionCheck(items, statusRegistry, verboseDiagnostics) {
|
|
|
595
825
|
terminalDoneStatuses.add(statusRegistry.close_status);
|
|
596
826
|
const closedItems = items.filter((item) => terminalDoneStatuses.has(normalizeStatusForRegistry(item.status, statusRegistry)));
|
|
597
827
|
const missingResolutionRows = [];
|
|
828
|
+
const resolutionBackfillRows = [];
|
|
598
829
|
for (const item of closedItems) {
|
|
599
830
|
const missingFields = RESOLUTION_FIELD_KEYS.filter((field) => !toNonEmptyStringOrUndefined(item[field]));
|
|
600
831
|
if (missingFields.length === 0) {
|
|
@@ -604,6 +835,11 @@ function buildResolutionCheck(items, statusRegistry, verboseDiagnostics) {
|
|
|
604
835
|
id: item.id,
|
|
605
836
|
missing_fields: missingFields
|
|
606
837
|
});
|
|
838
|
+
resolutionBackfillRows.push({
|
|
839
|
+
id: item.id,
|
|
840
|
+
missing_fields: missingFields,
|
|
841
|
+
close_reason: toNonEmptyStringOrUndefined(item.close_reason)
|
|
842
|
+
});
|
|
607
843
|
}
|
|
608
844
|
const warnings = missingResolutionRows.length > 0 ? [`validate_resolution_missing_fields:${missingResolutionRows.length}`] : [];
|
|
609
845
|
const diagnosticLimit = verboseDiagnostics ? Number.POSITIVE_INFINITY : DIAGNOSTIC_LIST_SUMMARY_LIMIT;
|
|
@@ -623,7 +859,8 @@ function buildResolutionCheck(items, statusRegistry, verboseDiagnostics) {
|
|
|
623
859
|
missing_resolution_remediation_hints_truncated: summarizedHints.truncated
|
|
624
860
|
}
|
|
625
861
|
},
|
|
626
|
-
warnings
|
|
862
|
+
warnings,
|
|
863
|
+
resolutionBackfillRows
|
|
627
864
|
};
|
|
628
865
|
}
|
|
629
866
|
function buildLifecycleDependencyGraph(activeItems) {
|
|
@@ -744,6 +981,7 @@ function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverit
|
|
|
744
981
|
const activeItems = items.filter((item) => !isTerminalStatus(item.status, statusRegistry));
|
|
745
982
|
const closureLikeRows = [];
|
|
746
983
|
const terminalParentRows = [];
|
|
984
|
+
const terminalParentFixRows = [];
|
|
747
985
|
const staleBlockerRows = [];
|
|
748
986
|
for (const item of activeItems) {
|
|
749
987
|
const closureLikeFields = Object.entries(lifecyclePatternPolicy.closure_like_metadata_field_patterns).filter(([field, patterns]) => {
|
|
@@ -769,6 +1007,14 @@ function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverit
|
|
|
769
1007
|
parent_id: parent.id,
|
|
770
1008
|
parent_status: parent.status
|
|
771
1009
|
});
|
|
1010
|
+
const grandparentId = toMeaningfulString(parent.parent);
|
|
1011
|
+
const grandparent = grandparentId ? itemsById.get(grandparentId) : void 0;
|
|
1012
|
+
terminalParentFixRows.push({
|
|
1013
|
+
id: item.id,
|
|
1014
|
+
parent_id: parent.id,
|
|
1015
|
+
grandparent_id: grandparent?.id,
|
|
1016
|
+
grandparent_active: grandparent !== void 0 && !isTerminalStatus(grandparent.status, statusRegistry)
|
|
1017
|
+
});
|
|
772
1018
|
}
|
|
773
1019
|
}
|
|
774
1020
|
if (includeStaleBlockers) {
|
|
@@ -806,6 +1052,7 @@ function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverit
|
|
|
806
1052
|
}
|
|
807
1053
|
closureLikeRows.sort((left, right) => left.id.localeCompare(right.id));
|
|
808
1054
|
terminalParentRows.sort((left, right) => left.id.localeCompare(right.id) || left.parent_id.localeCompare(right.parent_id));
|
|
1055
|
+
terminalParentFixRows.sort((left, right) => left.id.localeCompare(right.id) || left.parent_id.localeCompare(right.parent_id));
|
|
809
1056
|
staleBlockerRows.sort((left, right) => left.id.localeCompare(right.id));
|
|
810
1057
|
const dependencyCycleDiagnostics = detectLifecycleDependencyCycles(activeItems);
|
|
811
1058
|
const warnings = [];
|
|
@@ -862,31 +1109,43 @@ function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverit
|
|
|
862
1109
|
closure_like_actual_result_pattern_source: lifecyclePatternPolicy.closure_like_metadata_field_pattern_sources.actual_result
|
|
863
1110
|
}
|
|
864
1111
|
},
|
|
865
|
-
warnings
|
|
1112
|
+
warnings,
|
|
1113
|
+
terminalParentFixRows
|
|
866
1114
|
};
|
|
867
1115
|
}
|
|
868
1116
|
async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, includePmInternals, verboseFileLists) {
|
|
869
1117
|
const linkedProjectPaths = /* @__PURE__ */ new Set();
|
|
870
1118
|
const missingLinkedPaths = [];
|
|
1119
|
+
const staleLinkRows = [];
|
|
871
1120
|
for (const item of items) {
|
|
872
|
-
const
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
1121
|
+
const linkedArtifactGroups = [
|
|
1122
|
+
{ link_kind: "files", artifacts: item.files ?? [] },
|
|
1123
|
+
{ link_kind: "docs", artifacts: item.docs ?? [] }
|
|
1124
|
+
];
|
|
1125
|
+
for (const group of linkedArtifactGroups) {
|
|
1126
|
+
for (const artifact of group.artifacts) {
|
|
1127
|
+
if (artifact.scope !== "project") {
|
|
1128
|
+
continue;
|
|
1129
|
+
}
|
|
1130
|
+
const normalizedPath = normalizeRelativePath(artifact.path);
|
|
1131
|
+
if (normalizedPath.length === 0) {
|
|
1132
|
+
continue;
|
|
1133
|
+
}
|
|
1134
|
+
linkedProjectPaths.add(normalizedPath);
|
|
1135
|
+
const absolutePath = path.isAbsolute(artifact.path) ? artifact.path : path.resolve(workspaceRoot, artifact.path);
|
|
1136
|
+
let missing = false;
|
|
1137
|
+
try {
|
|
1138
|
+
const stats = await fs.stat(absolutePath);
|
|
1139
|
+
if (!stats.isFile()) {
|
|
1140
|
+
missing = true;
|
|
1141
|
+
}
|
|
1142
|
+
} catch {
|
|
1143
|
+
missing = true;
|
|
1144
|
+
}
|
|
1145
|
+
if (missing) {
|
|
886
1146
|
missingLinkedPaths.push(normalizedPath);
|
|
1147
|
+
staleLinkRows.push({ item_id: item.id, path: normalizedPath, link_kind: group.link_kind });
|
|
887
1148
|
}
|
|
888
|
-
} catch {
|
|
889
|
-
missingLinkedPaths.push(normalizedPath);
|
|
890
1149
|
}
|
|
891
1150
|
}
|
|
892
1151
|
}
|
|
@@ -910,6 +1169,13 @@ async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, inclu
|
|
|
910
1169
|
};
|
|
911
1170
|
}
|
|
912
1171
|
const orphanedFiles = candidateFiles.filter((candidate) => !linkedProjectPaths.has(candidate));
|
|
1172
|
+
const classifiedStalePaths = classifyStaleLinkedPaths(uniqueMissingLinkedPaths, candidateFiles);
|
|
1173
|
+
const classificationByPath = new Map(classifiedStalePaths.map((entry) => [entry.path, entry.classification]));
|
|
1174
|
+
const movedStalePathCount = classifiedStalePaths.filter((entry) => entry.classification === "moved").length;
|
|
1175
|
+
const staleLinkPruneRows = staleLinkRows.map((row) => ({
|
|
1176
|
+
...row,
|
|
1177
|
+
classification: classificationByPath.get(row.path) ?? "deleted"
|
|
1178
|
+
})).sort((left, right) => left.item_id.localeCompare(right.item_id) || left.path.localeCompare(right.path) || left.link_kind.localeCompare(right.link_kind));
|
|
913
1179
|
const warnings = [];
|
|
914
1180
|
if (strictModeForcesPmInternals) {
|
|
915
1181
|
warnings.push("validate_files_tracked_all_strict_forces_pm_internals");
|
|
@@ -922,6 +1188,7 @@ async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, inclu
|
|
|
922
1188
|
}
|
|
923
1189
|
const summarizedMissing = summarizeFileList(uniqueMissingLinkedPaths, verboseFileLists);
|
|
924
1190
|
const summarizedOrphaned = summarizeFileList(orphanedFiles, verboseFileLists);
|
|
1191
|
+
const summarizedClassifications = summarizeFileList(summarizeStaleLinkedPathClassifications(classifiedStalePaths), verboseFileLists);
|
|
925
1192
|
return {
|
|
926
1193
|
check: {
|
|
927
1194
|
name: "files",
|
|
@@ -952,13 +1219,18 @@ async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, inclu
|
|
|
952
1219
|
missing_linked_paths_total: summarizedMissing.total,
|
|
953
1220
|
missing_linked_paths: summarizedMissing.values,
|
|
954
1221
|
missing_linked_paths_truncated: summarizedMissing.truncated,
|
|
1222
|
+
missing_linked_paths_moved_count: movedStalePathCount,
|
|
1223
|
+
missing_linked_paths_deleted_count: uniqueMissingLinkedPaths.length - movedStalePathCount,
|
|
1224
|
+
missing_linked_path_classifications: summarizedClassifications.values,
|
|
1225
|
+
missing_linked_path_classifications_truncated: summarizedClassifications.truncated,
|
|
955
1226
|
orphaned_paths_count: orphanedFiles.length,
|
|
956
1227
|
orphaned_paths_total: summarizedOrphaned.total,
|
|
957
1228
|
orphaned_paths: summarizedOrphaned.values,
|
|
958
1229
|
orphaned_paths_truncated: summarizedOrphaned.truncated
|
|
959
1230
|
}
|
|
960
1231
|
},
|
|
961
|
-
warnings
|
|
1232
|
+
warnings,
|
|
1233
|
+
staleLinkPruneRows
|
|
962
1234
|
};
|
|
963
1235
|
}
|
|
964
1236
|
async function buildHistoryDriftCheck(pmRoot, items, verboseDiagnostics) {
|
|
@@ -1057,7 +1329,93 @@ function buildCommandReferencesCheck(items, idPrefix, verboseDiagnostics) {
|
|
|
1057
1329
|
warnings
|
|
1058
1330
|
};
|
|
1059
1331
|
}
|
|
1332
|
+
var VALIDATE_AUTO_FIX_MESSAGE = "pm validate auto-fix";
|
|
1333
|
+
async function applyValidateFix(fix, global) {
|
|
1334
|
+
switch (fix.kind) {
|
|
1335
|
+
case "set_resolution":
|
|
1336
|
+
case "set_close_reason":
|
|
1337
|
+
case "reparent":
|
|
1338
|
+
case "unset_parent": {
|
|
1339
|
+
const { runUpdate } = await import("./update-I246PCLO.js");
|
|
1340
|
+
const updateOptions = { message: VALIDATE_AUTO_FIX_MESSAGE };
|
|
1341
|
+
if (fix.kind === "set_resolution") {
|
|
1342
|
+
updateOptions.resolution = fix.value;
|
|
1343
|
+
} else if (fix.kind === "set_close_reason") {
|
|
1344
|
+
updateOptions.closeReason = fix.value;
|
|
1345
|
+
} else if (fix.kind === "reparent") {
|
|
1346
|
+
updateOptions.parent = fix.parent_id;
|
|
1347
|
+
} else {
|
|
1348
|
+
updateOptions.unset = ["parent"];
|
|
1349
|
+
}
|
|
1350
|
+
await runUpdate(fix.item_id, updateOptions, global);
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
case "prune_file_link": {
|
|
1354
|
+
throw new Error(`Unsupported non-batched fix kind: ${fix.kind}`);
|
|
1355
|
+
}
|
|
1356
|
+
case "prune_doc_link": {
|
|
1357
|
+
throw new Error(`Unsupported non-batched fix kind: ${fix.kind}`);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
function pruneBatchKey(fix) {
|
|
1362
|
+
if (fix.kind !== "prune_file_link" && fix.kind !== "prune_doc_link") {
|
|
1363
|
+
return null;
|
|
1364
|
+
}
|
|
1365
|
+
return `${fix.kind}:${fix.item_id}`;
|
|
1366
|
+
}
|
|
1367
|
+
async function applyValidateFixes(applicable, global) {
|
|
1368
|
+
const applied = [];
|
|
1369
|
+
const failed = [];
|
|
1370
|
+
const pruneBatches = /* @__PURE__ */ new Map();
|
|
1371
|
+
for (const fix of applicable) {
|
|
1372
|
+
const batchKey = pruneBatchKey(fix);
|
|
1373
|
+
if (batchKey === null) {
|
|
1374
|
+
try {
|
|
1375
|
+
await applyValidateFix(fix, global);
|
|
1376
|
+
applied.push(fix);
|
|
1377
|
+
} catch (error) {
|
|
1378
|
+
failed.push({ fix, error });
|
|
1379
|
+
}
|
|
1380
|
+
continue;
|
|
1381
|
+
}
|
|
1382
|
+
const existing = pruneBatches.get(batchKey);
|
|
1383
|
+
if (existing) {
|
|
1384
|
+
existing.push(fix);
|
|
1385
|
+
} else {
|
|
1386
|
+
pruneBatches.set(batchKey, [fix]);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
for (const batch of pruneBatches.values()) {
|
|
1390
|
+
const first = batch[0];
|
|
1391
|
+
if (!first) {
|
|
1392
|
+
continue;
|
|
1393
|
+
}
|
|
1394
|
+
const remove = batch.map((fix) => fix.path).filter((value) => typeof value === "string" && value.length > 0);
|
|
1395
|
+
try {
|
|
1396
|
+
if (first.kind === "prune_file_link") {
|
|
1397
|
+
const { runFiles } = await import("./files-GUXUM2MB.js");
|
|
1398
|
+
await runFiles(first.item_id, { remove, message: VALIDATE_AUTO_FIX_MESSAGE }, global);
|
|
1399
|
+
} else {
|
|
1400
|
+
const { runDocs } = await import("./docs-I3BAF5WH.js");
|
|
1401
|
+
await runDocs(first.item_id, { remove, message: VALIDATE_AUTO_FIX_MESSAGE }, global);
|
|
1402
|
+
}
|
|
1403
|
+
applied.push(...batch);
|
|
1404
|
+
} catch (error) {
|
|
1405
|
+
failed.push(...batch.map((fix) => ({ fix, error })));
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
return { applied, failed };
|
|
1409
|
+
}
|
|
1060
1410
|
async function runValidate(options, global) {
|
|
1411
|
+
const fixesRequested = options.autoFix === true || options.pruneMissing === true;
|
|
1412
|
+
if (options.dryRun === true && !fixesRequested) {
|
|
1413
|
+
throw new PmCliError("--dry-run requires --auto-fix or --prune-missing (there is nothing to preview otherwise).", EXIT_CODE.USAGE);
|
|
1414
|
+
}
|
|
1415
|
+
if (options.fixScope !== void 0 && options.fixScope.length > 0 && options.autoFix !== true) {
|
|
1416
|
+
throw new PmCliError("--fix-scope requires --auto-fix.", EXIT_CODE.USAGE);
|
|
1417
|
+
}
|
|
1418
|
+
const grantedFixScopes = resolveGrantedFixScopes(options.fixScope);
|
|
1061
1419
|
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
1062
1420
|
if (!await pathExists(getSettingsPath(pmRoot))) {
|
|
1063
1421
|
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
@@ -1085,17 +1443,29 @@ async function runValidate(options, global) {
|
|
|
1085
1443
|
checks.push(built.check);
|
|
1086
1444
|
warnings.push(...built.warnings);
|
|
1087
1445
|
};
|
|
1446
|
+
let closeReasonBackfillRows = [];
|
|
1447
|
+
let resolutionBackfillRows = [];
|
|
1448
|
+
let terminalParentFixRows = [];
|
|
1449
|
+
let staleLinkPruneRows = [];
|
|
1088
1450
|
if (requestedChecks.has("metadata")) {
|
|
1089
|
-
|
|
1451
|
+
const built = buildMetadataCheck(items, metadataPolicy, statusRegistry, Boolean(options.verboseDiagnostics));
|
|
1452
|
+
closeReasonBackfillRows = built.closeReasonBackfillRows;
|
|
1453
|
+
record(built);
|
|
1090
1454
|
}
|
|
1091
1455
|
if (requestedChecks.has("resolution")) {
|
|
1092
|
-
|
|
1456
|
+
const built = buildResolutionCheck(items, statusRegistry, Boolean(options.verboseDiagnostics));
|
|
1457
|
+
resolutionBackfillRows = built.resolutionBackfillRows;
|
|
1458
|
+
record(built);
|
|
1093
1459
|
}
|
|
1094
1460
|
if (requestedChecks.has("lifecycle")) {
|
|
1095
|
-
|
|
1461
|
+
const built = buildLifecycleCheck(items, Boolean(options.checkStaleBlockers), dependencyCycleSeverity, statusRegistry, lifecyclePatternPolicy, Boolean(options.verboseDiagnostics));
|
|
1462
|
+
terminalParentFixRows = built.terminalParentFixRows;
|
|
1463
|
+
record(built);
|
|
1096
1464
|
}
|
|
1097
1465
|
if (requestedChecks.has("files")) {
|
|
1098
|
-
|
|
1466
|
+
const built = await buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, Boolean(options.includePmInternals), Boolean(options.verboseFileLists));
|
|
1467
|
+
staleLinkPruneRows = built.staleLinkPruneRows;
|
|
1468
|
+
record(built);
|
|
1099
1469
|
}
|
|
1100
1470
|
if (requestedChecks.has("command_references")) {
|
|
1101
1471
|
record(buildCommandReferencesCheck(items, settings.id_prefix, Boolean(options.verboseDiagnostics)));
|
|
@@ -1103,6 +1473,47 @@ async function runValidate(options, global) {
|
|
|
1103
1473
|
if (requestedChecks.has("history_drift")) {
|
|
1104
1474
|
record(await buildHistoryDriftCheck(pmRoot, items, Boolean(options.verboseDiagnostics)));
|
|
1105
1475
|
}
|
|
1476
|
+
let fixes;
|
|
1477
|
+
if (fixesRequested) {
|
|
1478
|
+
const planned = [];
|
|
1479
|
+
if (options.autoFix === true) {
|
|
1480
|
+
planned.push(...planCloseReasonBackfillFixes(closeReasonBackfillRows));
|
|
1481
|
+
planned.push(...planResolutionBackfillFixes(resolutionBackfillRows));
|
|
1482
|
+
planned.push(...planTerminalParentFixes(terminalParentFixRows));
|
|
1483
|
+
}
|
|
1484
|
+
if (options.pruneMissing === true) {
|
|
1485
|
+
planned.push(...planStaleLinkPruneFixes(staleLinkPruneRows));
|
|
1486
|
+
}
|
|
1487
|
+
const { applicable, gated } = partitionFixesByGrant(planned, grantedFixScopes);
|
|
1488
|
+
const dryRun = options.dryRun === true;
|
|
1489
|
+
const appliedFixRows = [];
|
|
1490
|
+
const failedFixRows = [];
|
|
1491
|
+
if (!dryRun) {
|
|
1492
|
+
const applied = await applyValidateFixes(applicable, global);
|
|
1493
|
+
appliedFixRows.push(...applied.applied.map(toFixOutputRow));
|
|
1494
|
+
failedFixRows.push(...applied.failed.map(({ fix, error }) => ({
|
|
1495
|
+
...toFixOutputRow(fix),
|
|
1496
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1497
|
+
})));
|
|
1498
|
+
}
|
|
1499
|
+
fixes = {
|
|
1500
|
+
mode: dryRun ? "dry_run" : "apply",
|
|
1501
|
+
auto_fix: options.autoFix === true,
|
|
1502
|
+
prune_missing: options.pruneMissing === true,
|
|
1503
|
+
granted_fix_scopes: [...grantedFixScopes].sort((left, right) => left.localeCompare(right)),
|
|
1504
|
+
planned_count: planned.length,
|
|
1505
|
+
applied_count: appliedFixRows.length,
|
|
1506
|
+
gated_count: gated.length,
|
|
1507
|
+
failed_count: failedFixRows.length,
|
|
1508
|
+
planned_fixes: planned.map(toFixOutputRow),
|
|
1509
|
+
applied_fixes: appliedFixRows,
|
|
1510
|
+
gated_fixes: gated.map((fix) => ({
|
|
1511
|
+
...toFixOutputRow(fix),
|
|
1512
|
+
gate_hint: `Withheld: re-run with --fix-scope ${fix.gate} to apply.`
|
|
1513
|
+
})),
|
|
1514
|
+
failed_fixes: failedFixRows
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1106
1517
|
const normalizedWarnings = [...new Set(warnings)].sort((left, right) => left.localeCompare(right));
|
|
1107
1518
|
const hasErrors = checks.some((check) => check.status === "error");
|
|
1108
1519
|
return {
|
|
@@ -1110,12 +1521,13 @@ async function runValidate(options, global) {
|
|
|
1110
1521
|
has_warnings: normalizedWarnings.length > 0,
|
|
1111
1522
|
checks,
|
|
1112
1523
|
warnings: normalizedWarnings,
|
|
1524
|
+
...fixes !== void 0 ? { fixes } : {},
|
|
1113
1525
|
generated_at: nowIso()
|
|
1114
1526
|
};
|
|
1115
1527
|
}
|
|
1116
1528
|
export {
|
|
1117
1529
|
runValidate
|
|
1118
1530
|
};
|
|
1119
|
-
//# sourceMappingURL=validate-
|
|
1531
|
+
//# sourceMappingURL=validate-46KCRHL7.js.map
|
|
1120
1532
|
|
|
1121
|
-
//# debugId=
|
|
1533
|
+
//# debugId=50b9ae79-2f9d-56b7-8b52-24c0a6416cd8
|