@unbrained/pm-cli 2026.8.14 → 2026.8.16
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/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +51 -11
- package/dist/cli/commander-usage.js +17 -4
- package/dist/cli/error-guidance.d.ts +7 -0
- package/dist/cli/error-guidance.js +65 -25
- package/dist/cli/main.js +3 -2
- package/dist/cli/register-history-author.js +16 -11
- package/dist/cli/register-mutation.js +4 -2
- package/dist/cli/register-operations.js +5 -5
- package/dist/cli-bundle/bundle-manifest.json +148 -148
- package/dist/cli-bundle/chunks/chunk-47OQEOQB.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-XAVMOK6B.js → chunk-73UGEBRS.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-HCIYWD6M.js +35 -0
- package/dist/cli-bundle/chunks/{chunk-FIW4P64F.js → chunk-I2LUWWR5.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-SBRKH6OR.js → chunk-IC5W2T34.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TMJ7URWS.js → chunk-PANOOBIS.js} +9 -9
- package/dist/cli-bundle/chunks/{chunk-BFALV3YP.js → chunk-RIS565OA.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TXMEUUUY.js → chunk-TK6N7HGM.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-TOFG2URD.js +197 -0
- package/dist/cli-bundle/chunks/{chunk-G5JUB66K.js → chunk-URW4QRMI.js} +65 -59
- package/dist/cli-bundle/chunks/{register-list-query-T3EHHNNV.js → register-list-query-EYCXHZAG.js} +2 -2
- package/dist/cli-bundle/chunks/register-mutation-7YVIG54J.js +20 -0
- package/dist/cli-bundle/chunks/register-operations-KGDNRMCL.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-3YXZ444E.js → register-setup-NVXBOD5I.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-PPFGQDSI.js → chunk-4JPEBFFC.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-5NMFSX26.js +155 -0
- package/dist/cli-bundle/focused-chunks/{chunk-YOOI3UZX.js → chunk-6ROKKT4X.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-725JSCMP.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-XDNAW5OI.js → chunk-C7JUBRFP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-4DQ2YERC.js → chunk-CODV5LUT.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-DQ6SMTBF.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-HAACPSUW.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-WCVE2NIG.js → chunk-J4UFYHOD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-JX5Z344Q.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-L4RDYBIQ.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-KSEDUWVZ.js → chunk-NJ5RLEFD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-K7RWWOAG.js → chunk-QYZERYR5.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-SSNDYZTM.js +8 -0
- package/dist/cli-bundle/focused-chunks/chunk-T46KLOIB.js +50 -0
- package/dist/cli-bundle/focused-chunks/{chunk-KFSZ3BP6.js → chunk-TZATVC4G.js} +6 -6
- package/dist/cli-bundle/focused-chunks/chunk-WY3WRPVN.js +2 -0
- package/dist/cli-bundle/main.js +13 -13
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +1 -1
- package/dist/cli-bundle/sdk-core.js +32 -35
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +32 -31
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +2 -2
- package/dist/core/diagnostics/remediation.js +7 -2
- package/dist/core/extensions/reserved-host-flags.js +3 -2
- package/dist/core/history/replay.d.ts +14 -1
- package/dist/core/history/replay.js +45 -8
- package/dist/core/history/workspace-history.js +32 -10
- package/dist/core/output/output.d.ts +2 -0
- package/dist/core/output/output.js +7 -3
- package/dist/core/shared/command-types.d.ts +2 -0
- package/dist/core/shared/command-types.js +2 -2
- package/dist/core/shared/errors.d.ts +14 -0
- package/dist/core/shared/errors.js +2 -2
- package/dist/core/store/item-store.js +28 -2
- package/dist/mcp/tool-definitions.js +9 -5
- package/dist/sdk/agent/refusal-reachability.d.ts +69 -0
- package/dist/sdk/agent/refusal-reachability.js +159 -3
- package/dist/sdk/author-attribution.d.ts +56 -11
- package/dist/sdk/author-attribution.js +174 -50
- package/dist/sdk/cli-bootstrap.d.ts +2 -0
- package/dist/sdk/cli-bootstrap.js +7 -2
- package/dist/sdk/cli-contracts/completeness.js +3 -2
- package/dist/sdk/cli-contracts/flag-contracts.js +6 -2
- package/dist/sdk/cli-contracts/registration-helpers.js +3 -2
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
- package/dist/sdk/cli-contracts/runtime-contracts.js +23 -7
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +22 -5
- package/dist/sdk/cli-contracts/tool-schema.js +20 -5
- package/dist/sdk/cli-program.js +3 -2
- package/dist/sdk/completion.js +11 -4
- package/dist/sdk/core.d.ts +2 -2
- package/dist/sdk/core.js +3 -3
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +50 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +74 -14
- package/dist/sdk/governance/assurance-action.d.ts +7 -1
- package/dist/sdk/governance/assurance-action.js +7 -6
- package/dist/sdk/governance/assurance-mutation-error.d.ts +42 -1
- package/dist/sdk/governance/assurance-mutation-error.js +27 -3
- package/dist/sdk/governance/assurance-runtime.js +12 -11
- package/dist/sdk/governance/assurance.d.ts +9 -0
- package/dist/sdk/governance/assurance.js +80 -14
- package/dist/sdk/governance/coverage-assurance.d.ts +24 -0
- package/dist/sdk/governance/coverage-assurance.js +61 -0
- package/dist/sdk/governance/extension-host-version.d.ts +25 -0
- package/dist/sdk/governance/extension-host-version.js +116 -0
- package/dist/sdk/governance/health.d.ts +32 -1
- package/dist/sdk/governance/health.js +119 -27
- package/dist/sdk/governance/provenance-health.d.ts +27 -0
- package/dist/sdk/governance/provenance-health.js +95 -3
- package/dist/sdk/governance/validate.js +7 -8
- package/dist/sdk/governance.d.ts +6 -0
- package/dist/sdk/governance.js +8 -2
- package/dist/sdk/history-repair.d.ts +13 -1
- package/dist/sdk/history-repair.js +62 -18
- package/dist/sdk/index.d.ts +2 -1
- package/dist/sdk/index.js +4 -3
- package/dist/sdk/linked-artifacts.js +16 -5
- package/dist/sdk/pagination.d.ts +15 -0
- package/dist/sdk/pagination.js +9 -5
- package/dist/sdk/query/context.d.ts +5 -1
- package/dist/sdk/query/context.js +14 -5
- package/dist/sdk/read-output/continuation.d.ts +11 -0
- package/dist/sdk/read-output/continuation.js +132 -0
- package/dist/sdk/read-output-budget.d.ts +1 -1
- package/dist/sdk/read-output-budget.js +14 -10
- package/dist/sdk/read-output-contracts.d.ts +66 -2
- package/dist/sdk/read-output-contracts.js +185 -19
- package/dist/sdk/read-output-rows.d.ts +2 -0
- package/dist/sdk/read-output-rows.js +15 -2
- package/dist/sdk/runtime-input.js +4 -2
- package/dist/sdk/runtime.d.ts +2 -5
- package/dist/sdk/runtime.js +3 -2
- package/docs/ASSURANCE.md +59 -2
- package/docs/COMMANDS.md +8 -2
- package/docs/READ_OUTPUT_CONTRACTS.md +55 -8
- package/docs/RELEASING.md +54 -11
- package/docs/SDK_CONTEXT_INTEGRITY.md +94 -4
- package/docs/SDK_CONTEXT_TRUTH_CONTRACTS.md +13 -5
- package/marketplace.json +2 -2
- package/package.json +3 -3
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/sdk/public-surface.json +1241 -180
- package/dist/cli-bundle/chunks/chunk-BBOFSVAK.js +0 -197
- package/dist/cli-bundle/chunks/chunk-YAMTJL6Y.js +0 -34
- package/dist/cli-bundle/chunks/chunk-YSVSMJ2B.js +0 -2
- package/dist/cli-bundle/chunks/register-mutation-E27WCLSZ.js +0 -20
- package/dist/cli-bundle/chunks/register-operations-4R6I7CPY.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-F43TT2QQ.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-KYUQGTSB.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-LZ4MV3RH.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-PGXJQLCT.js +0 -155
- package/dist/cli-bundle/focused-chunks/chunk-Q4YY3XNF.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-QK753U3U.js +0 -46
- package/dist/cli-bundle/focused-chunks/chunk-QUMB2J27.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-SM7MTG27.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-ZM6TZVHC.js +0 -2
|
@@ -1,12 +1,12 @@
|
|
|
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]="06d21369-1339-54b2-8d78-442f02e24cef")}catch(e){}}();
|
|
3
3
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
4
4
|
import { PmCliError } from "../../core/shared/errors.js";
|
|
5
5
|
import { ASSURANCE_GATE_TRIGGERS, evaluateAssuranceGate, getAssuranceDeclaration, listAssuranceDeclarations, listAssuranceVerdicts, putAssuranceDeclaration, recordAssuranceVerdict, removeAssuranceDeclaration, } from "./assurance.js";
|
|
6
6
|
import { ASSURANCE_PRESET_IDS, acceptAssuranceProposals, applyAssurancePreset, createAssurancePreset, deriveAssuranceProposals, promoteAssuranceAssertion, } from "./assurance-presets.js";
|
|
7
7
|
import { MAX_ASSURANCE_VERDICT_LIMIT } from "./assurance-limits.js";
|
|
8
8
|
import { normalizeAssuranceEvaluation, normalizeAssuranceMutation, } from "./assurance-mutation-error.js";
|
|
9
|
-
import { createAssuranceWorkspaceContext } from "./assurance-runtime.js";
|
|
9
|
+
import { createAssuranceWorkspaceContext, } from "./assurance-runtime.js";
|
|
10
10
|
import { resolvePmRoot } from "../runtime-primitives.js";
|
|
11
11
|
import { parseRuntimeInteger, readRuntimeString } from "../runtime-input.js";
|
|
12
12
|
/** Assurance registry and evaluation verbs shared by every transport. */
|
|
@@ -173,7 +173,7 @@ async function runAdoptionAction(action, input, pmRoot) {
|
|
|
173
173
|
message: input.message,
|
|
174
174
|
}));
|
|
175
175
|
}
|
|
176
|
-
async function runGateAction(input, pmRoot) {
|
|
176
|
+
async function runGateAction(input, pmRoot, runtime) {
|
|
177
177
|
if (!input.id) {
|
|
178
178
|
throw new PmCliError("assurance run requires a gate id", EXIT_CODE.USAGE);
|
|
179
179
|
}
|
|
@@ -188,6 +188,7 @@ async function runGateAction(input, pmRoot) {
|
|
|
188
188
|
const [document, workspaceContext] = await Promise.all([
|
|
189
189
|
readDocument(pmRoot),
|
|
190
190
|
createAssuranceWorkspaceContext(pmRoot, {
|
|
191
|
+
...runtime.workspace,
|
|
191
192
|
tree_id: input.tree,
|
|
192
193
|
trigger,
|
|
193
194
|
}),
|
|
@@ -205,7 +206,7 @@ async function runGateAction(input, pmRoot) {
|
|
|
205
206
|
return verdict;
|
|
206
207
|
}
|
|
207
208
|
/** Execute one assurance request through the public assurance SDK primitives. */
|
|
208
|
-
export async function runAssuranceAction(input, global = {}) {
|
|
209
|
+
export async function runAssuranceAction(input, global = {}, runtime = {}) {
|
|
209
210
|
const action = parseAction(input.action);
|
|
210
211
|
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
211
212
|
if (action === "presets" ||
|
|
@@ -218,7 +219,7 @@ export async function runAssuranceAction(input, global = {}) {
|
|
|
218
219
|
return runVerdictsAction(input, pmRoot);
|
|
219
220
|
}
|
|
220
221
|
if (action === "run") {
|
|
221
|
-
return runGateAction(input, pmRoot);
|
|
222
|
+
return runGateAction(input, pmRoot, runtime);
|
|
222
223
|
}
|
|
223
224
|
const kind = parseKind(input.kind);
|
|
224
225
|
if (action === "list")
|
|
@@ -281,4 +282,4 @@ export function runAssuranceDispatch(args, options, global) {
|
|
|
281
282
|
}, global);
|
|
282
283
|
}
|
|
283
284
|
//# sourceMappingURL=assurance-action.js.map
|
|
284
|
-
//# debugId=
|
|
285
|
+
//# debugId=06d21369-1339-54b2-8d78-442f02e24cef
|
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
/** Machine-readable location of a refused assurance evaluation. */
|
|
2
|
+
export interface AssuranceEvaluationRefusalContext {
|
|
3
|
+
/** Gate being evaluated. */
|
|
4
|
+
gate_id?: string;
|
|
5
|
+
/** Assertion whose measurement failed. */
|
|
6
|
+
assertion_id?: string;
|
|
7
|
+
/** Measurement whose source failed. */
|
|
8
|
+
measurement_id?: string;
|
|
9
|
+
/** Measurement source discriminant. */
|
|
10
|
+
source_kind?: string;
|
|
11
|
+
/** Field selected from a graph, validate, or health result. */
|
|
12
|
+
field?: string;
|
|
13
|
+
/** Validate or health check selected by the source. */
|
|
14
|
+
check?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Machine-readable location of a failed measurement source resolution. */
|
|
17
|
+
export interface AssuranceSourceResolutionContext {
|
|
18
|
+
/** Measurement that owns the failed source, once evaluation identifies it. */
|
|
19
|
+
measurement_id?: string;
|
|
20
|
+
/** Measurement source discriminant. */
|
|
21
|
+
source_kind: string;
|
|
22
|
+
/** Field selected from the source result. */
|
|
23
|
+
field: string;
|
|
24
|
+
/** Optional validate or health check selector. */
|
|
25
|
+
check?: string;
|
|
26
|
+
}
|
|
1
27
|
/** Expected declaration-validation or mutation-policy refusal. */
|
|
2
28
|
export declare class AssuranceMutationRefusalError extends TypeError {
|
|
3
29
|
/** Create one typed refusal while retaining TypeError compatibility for SDK callers. */
|
|
@@ -5,8 +31,23 @@ export declare class AssuranceMutationRefusalError extends TypeError {
|
|
|
5
31
|
}
|
|
6
32
|
/** Expected gate-policy refusal caused by an incomplete or disallowed provider contract. */
|
|
7
33
|
export declare class AssuranceEvaluationRefusalError extends TypeError {
|
|
34
|
+
/** Structured evaluation location retained across CLI, SDK, and MCP. */
|
|
35
|
+
readonly context: AssuranceEvaluationRefusalContext;
|
|
8
36
|
/** Create one typed refusal while retaining TypeError compatibility for SDK callers. */
|
|
9
|
-
constructor(message: string);
|
|
37
|
+
constructor(message: string, context?: AssuranceEvaluationRefusalContext);
|
|
38
|
+
}
|
|
39
|
+
/** Expected failure to resolve one declared external measurement source. */
|
|
40
|
+
export declare class AssuranceSourceResolutionError extends TypeError {
|
|
41
|
+
/** Measurement that owns the failed source, once evaluation identifies it. */
|
|
42
|
+
readonly measurement_id?: string;
|
|
43
|
+
/** Measurement source discriminant. */
|
|
44
|
+
readonly source_kind: string;
|
|
45
|
+
/** Field selected from the source result. */
|
|
46
|
+
readonly field: string;
|
|
47
|
+
/** Optional validate or health check selector. */
|
|
48
|
+
readonly check?: string;
|
|
49
|
+
/** Create one source-local refusal before gate context is attached. */
|
|
50
|
+
constructor(message: string, context: AssuranceSourceResolutionContext);
|
|
10
51
|
}
|
|
11
52
|
/** Normalize only expected assurance mutation refusals for CLI and MCP hosts. */
|
|
12
53
|
export declare function normalizeAssuranceMutation<T>(operation: () => Promise<T>): Promise<T>;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* faults before transport layers normalize them into stable usage errors.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
!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]="
|
|
8
|
+
!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]="d2d5135a-8110-527e-8530-653b25b792a4")}catch(e){}}();
|
|
9
9
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
10
10
|
import { PmCliError } from "../../core/shared/errors.js";
|
|
11
11
|
/** Expected declaration-validation or mutation-policy refusal. */
|
|
@@ -18,10 +18,33 @@ export class AssuranceMutationRefusalError extends TypeError {
|
|
|
18
18
|
}
|
|
19
19
|
/** Expected gate-policy refusal caused by an incomplete or disallowed provider contract. */
|
|
20
20
|
export class AssuranceEvaluationRefusalError extends TypeError {
|
|
21
|
+
/** Structured evaluation location retained across CLI, SDK, and MCP. */
|
|
22
|
+
context;
|
|
21
23
|
/** Create one typed refusal while retaining TypeError compatibility for SDK callers. */
|
|
22
|
-
constructor(message) {
|
|
24
|
+
constructor(message, context = {}) {
|
|
23
25
|
super(message);
|
|
24
26
|
this.name = "AssuranceEvaluationRefusalError";
|
|
27
|
+
this.context = context;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Expected failure to resolve one declared external measurement source. */
|
|
31
|
+
export class AssuranceSourceResolutionError extends TypeError {
|
|
32
|
+
/** Measurement that owns the failed source, once evaluation identifies it. */
|
|
33
|
+
measurement_id;
|
|
34
|
+
/** Measurement source discriminant. */
|
|
35
|
+
source_kind;
|
|
36
|
+
/** Field selected from the source result. */
|
|
37
|
+
field;
|
|
38
|
+
/** Optional validate or health check selector. */
|
|
39
|
+
check;
|
|
40
|
+
/** Create one source-local refusal before gate context is attached. */
|
|
41
|
+
constructor(message, context) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = "AssuranceSourceResolutionError";
|
|
44
|
+
this.measurement_id = context.measurement_id;
|
|
45
|
+
this.source_kind = context.source_kind;
|
|
46
|
+
this.field = context.field;
|
|
47
|
+
this.check = context.check;
|
|
25
48
|
}
|
|
26
49
|
}
|
|
27
50
|
/** Normalize only expected assurance mutation refusals for CLI and MCP hosts. */
|
|
@@ -49,10 +72,11 @@ export async function normalizeAssuranceEvaluation(operation) {
|
|
|
49
72
|
throw new PmCliError(error.message, EXIT_CODE.USAGE, {
|
|
50
73
|
code: "invalid_argument_value",
|
|
51
74
|
reason: "assurance_evaluation_refused",
|
|
75
|
+
...error.context,
|
|
52
76
|
});
|
|
53
77
|
}
|
|
54
78
|
throw error;
|
|
55
79
|
}
|
|
56
80
|
}
|
|
57
81
|
//# sourceMappingURL=assurance-mutation-error.js.map
|
|
58
|
-
//# debugId=
|
|
82
|
+
//# debugId=d2d5135a-8110-527e-8530-653b25b792a4
|
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
* and verdict semantics in the host-neutral assurance module.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
!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]="
|
|
8
|
+
!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]="f9c26dab-b2fb-5ca0-b575-682b4b0bb830")}catch(e){}}();
|
|
9
9
|
import { execFile } from "node:child_process";
|
|
10
10
|
import { promisify } from "node:util";
|
|
11
11
|
import { runGraph } from "../graph/run.js";
|
|
12
12
|
import { runHealth } from "./health.js";
|
|
13
13
|
import { runValidate } from "./validate.js";
|
|
14
|
+
import { AssuranceSourceResolutionError } from "./assurance-mutation-error.js";
|
|
14
15
|
import { getActiveExtensionRegistrations, resolvePortableWorkspaceContext, } from "../../core/extensions/index.js";
|
|
15
16
|
import { resolveRegisteredAssuranceMeasurementProvider } from "../../core/extensions/runtime-registrations.js";
|
|
16
17
|
import { stableStringify } from "../../core/shared/serialization.js";
|
|
@@ -86,13 +87,13 @@ async function runRegisteredProvider(provider, source, pmRoot, trigger) {
|
|
|
86
87
|
clearTimeout(timeoutHandle);
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
|
-
function valueAtPath(input, field) {
|
|
90
|
+
function valueAtPath(input, field, sourceKind, check) {
|
|
90
91
|
let current = input;
|
|
91
92
|
for (const segment of field.split(".")) {
|
|
92
93
|
if (typeof current !== "object" ||
|
|
93
94
|
current === null ||
|
|
94
95
|
Array.isArray(current)) {
|
|
95
|
-
throw new
|
|
96
|
+
throw new AssuranceSourceResolutionError(`assurance field ${field} is not present`, { source_kind: sourceKind, field, ...(check ? { check } : {}) });
|
|
96
97
|
}
|
|
97
98
|
current = current[segment];
|
|
98
99
|
}
|
|
@@ -102,17 +103,17 @@ function valueAtPath(input, field) {
|
|
|
102
103
|
current.every((entry) => typeof entry === "string")) {
|
|
103
104
|
return current;
|
|
104
105
|
}
|
|
105
|
-
throw new
|
|
106
|
+
throw new AssuranceSourceResolutionError(`assurance field ${field} must resolve to a finite number or string array`, { source_kind: sourceKind, field, ...(check ? { check } : {}) });
|
|
106
107
|
}
|
|
107
|
-
function checkValue(result, checkName, field) {
|
|
108
|
+
function checkValue(result, checkName, field, sourceKind) {
|
|
108
109
|
const check = result.checks.find((entry) => entry.name === checkName);
|
|
109
110
|
if (!check)
|
|
110
|
-
throw new
|
|
111
|
+
throw new AssuranceSourceResolutionError(`assurance check ${checkName} is not present`, { source_kind: sourceKind, field, check: checkName });
|
|
111
112
|
const value = field === "status" || field === "ok"
|
|
112
113
|
? check.ok
|
|
113
114
|
? 0
|
|
114
115
|
: 1
|
|
115
|
-
: valueAtPath(check.details, field);
|
|
116
|
+
: valueAtPath(check.details, field, sourceKind, checkName);
|
|
116
117
|
return { value, population_size: 1, cost: result.checks.length };
|
|
117
118
|
}
|
|
118
119
|
async function resolveTreeId(pmRoot, explicit) {
|
|
@@ -205,7 +206,7 @@ export async function createAssuranceWorkspaceContext(pmRoot, options = {}) {
|
|
|
205
206
|
}
|
|
206
207
|
const result = await pending;
|
|
207
208
|
return {
|
|
208
|
-
value: valueAtPath(result, source.field),
|
|
209
|
+
value: valueAtPath(result, source.field, source.kind),
|
|
209
210
|
population_size: items.length,
|
|
210
211
|
cost: items.length,
|
|
211
212
|
};
|
|
@@ -213,12 +214,12 @@ export async function createAssuranceWorkspaceContext(pmRoot, options = {}) {
|
|
|
213
214
|
if (source.kind === "validate") {
|
|
214
215
|
validateRun ??= runValidate({ counts: true }, global);
|
|
215
216
|
const result = await validateRun;
|
|
216
|
-
return checkValue(result, source.check, source.field);
|
|
217
|
+
return checkValue(result, source.check, source.field, source.kind);
|
|
217
218
|
}
|
|
218
219
|
if (source.kind === "health") {
|
|
219
220
|
healthRun ??= runHealth(global, { checkOnly: true, full: true });
|
|
220
221
|
const result = await healthRun;
|
|
221
|
-
return checkValue(result, source.check, source.field);
|
|
222
|
+
return checkValue(result, source.check, source.field, source.kind);
|
|
222
223
|
}
|
|
223
224
|
const hostProvider = options.providers?.[source.provider];
|
|
224
225
|
if (hostProvider)
|
|
@@ -232,4 +233,4 @@ export async function createAssuranceWorkspaceContext(pmRoot, options = {}) {
|
|
|
232
233
|
};
|
|
233
234
|
}
|
|
234
235
|
//# sourceMappingURL=assurance-runtime.js.map
|
|
235
|
-
//# debugId=
|
|
236
|
+
//# debugId=f9c26dab-b2fb-5ca0-b575-682b4b0bb830
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export declare const ASSURANCE_DOCUMENT_VERSION: 1;
|
|
3
3
|
/** Supported lifecycle points that can evaluate a gate. */
|
|
4
4
|
export declare const ASSURANCE_GATE_TRIGGERS: readonly ["pre-commit", "pre-push", "pre-merge", "ci", "pre-release", "post-release", "scheduled", "on-claim", "on-close"];
|
|
5
|
+
/** Supported discriminants for built-in, delegated, and derived measurements. */
|
|
6
|
+
export declare const ASSURANCE_MEASUREMENT_SOURCE_KINDS: readonly ["items", "dependency_kind", "graph", "validate", "health", "history", "links", "provider", "derived"];
|
|
5
7
|
/** Gate lifecycle trigger. */
|
|
6
8
|
export type AssuranceGateTrigger = (typeof ASSURANCE_GATE_TRIGGERS)[number];
|
|
7
9
|
/** Assertion enforcement strength. */
|
|
@@ -401,6 +403,13 @@ export interface AssuranceGateVerdict {
|
|
|
401
403
|
exit_code: 0 | 1;
|
|
402
404
|
/** Per-assertion receipts. */
|
|
403
405
|
assertions: AssuranceAssertionVerdict[];
|
|
406
|
+
/** Total assertions evaluated before any transport projection or compaction. */
|
|
407
|
+
assertions_total: number;
|
|
408
|
+
/** Stable selector for iterating assertion evidence across transports. */
|
|
409
|
+
row_contract: {
|
|
410
|
+
row_keys: ["assertions"];
|
|
411
|
+
jq_selector: ".assertions[]";
|
|
412
|
+
};
|
|
404
413
|
/** Aggregate compute receipt. */
|
|
405
414
|
cost: AssuranceMeasurementCost;
|
|
406
415
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* one deterministic SDK path.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!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]="
|
|
10
|
+
!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]="2bf52d6d-7e4f-5ec5-86bd-3e817ef521bb")}catch(e){}}();
|
|
11
11
|
import { createHash } from "node:crypto";
|
|
12
12
|
import path from "node:path";
|
|
13
13
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
@@ -15,7 +15,7 @@ import { PmCliError } from "../../core/shared/errors.js";
|
|
|
15
15
|
import { appendWorkspaceAuditEvent, mutateWorkspaceJsonWithHistory, readFileIfExists, readHistoryEntries, readSettings, resolveAuthor, stableStringify, WORKSPACE_HISTORY_ID, getWorkspaceHistoryPath, } from "../runtime-primitives.js";
|
|
16
16
|
import { resolveCanonicalRelationshipKind } from "../relationships.js";
|
|
17
17
|
import { MAX_ASSURANCE_VERDICT_LIMIT } from "./assurance-limits.js";
|
|
18
|
-
import { AssuranceEvaluationRefusalError, AssuranceMutationRefusalError, } from "./assurance-mutation-error.js";
|
|
18
|
+
import { AssuranceEvaluationRefusalError, AssuranceMutationRefusalError, AssuranceSourceResolutionError, } from "./assurance-mutation-error.js";
|
|
19
19
|
/** Current serialized assurance registry format. */
|
|
20
20
|
export const ASSURANCE_DOCUMENT_VERSION = 1;
|
|
21
21
|
/** Supported lifecycle points that can evaluate a gate. */
|
|
@@ -30,6 +30,18 @@ export const ASSURANCE_GATE_TRIGGERS = [
|
|
|
30
30
|
"on-claim",
|
|
31
31
|
"on-close",
|
|
32
32
|
];
|
|
33
|
+
/** Supported discriminants for built-in, delegated, and derived measurements. */
|
|
34
|
+
export const ASSURANCE_MEASUREMENT_SOURCE_KINDS = [
|
|
35
|
+
"items",
|
|
36
|
+
"dependency_kind",
|
|
37
|
+
"graph",
|
|
38
|
+
"validate",
|
|
39
|
+
"health",
|
|
40
|
+
"history",
|
|
41
|
+
"links",
|
|
42
|
+
"provider",
|
|
43
|
+
"derived",
|
|
44
|
+
];
|
|
33
45
|
const POLARITY_KEYS = [
|
|
34
46
|
"ceiling",
|
|
35
47
|
"floor",
|
|
@@ -161,7 +173,15 @@ export function validateMeasurementDefinition(definition) {
|
|
|
161
173
|
if (definition.max_cost !== undefined) {
|
|
162
174
|
requireFiniteNonNegative(definition.max_cost, "measurement.max_cost");
|
|
163
175
|
}
|
|
164
|
-
const
|
|
176
|
+
const candidateSource = definition.source;
|
|
177
|
+
if (Object.prototype.toString.call(candidateSource) !== "[object Object]") {
|
|
178
|
+
throw new AssuranceMutationRefusalError(`measurement.source.kind must be one of ${ASSURANCE_MEASUREMENT_SOURCE_KINDS.join(", ")}`);
|
|
179
|
+
}
|
|
180
|
+
const sourceKind = Reflect.get(candidateSource, "kind");
|
|
181
|
+
if (!ASSURANCE_MEASUREMENT_SOURCE_KINDS.includes(sourceKind)) {
|
|
182
|
+
throw new AssuranceMutationRefusalError(`measurement.source.kind must be one of ${ASSURANCE_MEASUREMENT_SOURCE_KINDS.join(", ")}`);
|
|
183
|
+
}
|
|
184
|
+
const source = candidateSource;
|
|
165
185
|
if (source.kind === "items") {
|
|
166
186
|
validateItemsMeasurementSource(source);
|
|
167
187
|
}
|
|
@@ -240,14 +260,25 @@ function validateGateProviderPolicy(policy) {
|
|
|
240
260
|
/** Validate and return one gate declaration. */
|
|
241
261
|
export function validateGateDefinition(definition) {
|
|
242
262
|
requireStableId(definition.id, "gate.id");
|
|
263
|
+
if (!Array.isArray(definition.assertion_ids)) {
|
|
264
|
+
throw new AssuranceMutationRefusalError("gate.assertion_ids is required and must be an array");
|
|
265
|
+
}
|
|
243
266
|
if (definition.assertion_ids.length === 0) {
|
|
244
267
|
throw new AssuranceMutationRefusalError("gate requires at least one assertion");
|
|
245
268
|
}
|
|
246
269
|
for (const id of definition.assertion_ids)
|
|
247
270
|
requireStableId(id, "gate.assertion_id");
|
|
271
|
+
if (!Array.isArray(definition.triggers)) {
|
|
272
|
+
throw new AssuranceMutationRefusalError(`gate.triggers is required and must be an array of ${ASSURANCE_GATE_TRIGGERS.join(", ")}`);
|
|
273
|
+
}
|
|
248
274
|
if (definition.triggers.length === 0) {
|
|
249
275
|
throw new AssuranceMutationRefusalError("gate requires at least one trigger");
|
|
250
276
|
}
|
|
277
|
+
for (const trigger of definition.triggers) {
|
|
278
|
+
if (!ASSURANCE_GATE_TRIGGERS.includes(trigger)) {
|
|
279
|
+
throw new AssuranceMutationRefusalError(`gate trigger must be one of ${ASSURANCE_GATE_TRIGGERS.join(", ")}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
251
282
|
if (definition.provider_policy) {
|
|
252
283
|
validateGateProviderPolicy(definition.provider_policy);
|
|
253
284
|
}
|
|
@@ -543,16 +574,10 @@ async function evaluateMeasurementInternal(definition, context, definitions, sta
|
|
|
543
574
|
if (builtin !== null) {
|
|
544
575
|
result = builtin;
|
|
545
576
|
}
|
|
546
|
-
else
|
|
547
|
-
definition.source.kind === "validate" ||
|
|
548
|
-
definition.source.kind === "health" ||
|
|
549
|
-
definition.source.kind === "provider") {
|
|
577
|
+
else {
|
|
550
578
|
result = await context.external(definition.source);
|
|
551
579
|
providerCalls = 1;
|
|
552
580
|
}
|
|
553
|
-
else {
|
|
554
|
-
throw new TypeError(`unsupported assurance source ${definition.source.kind}`);
|
|
555
|
-
}
|
|
556
581
|
}
|
|
557
582
|
const ownCost = {
|
|
558
583
|
units: result.cost,
|
|
@@ -587,7 +612,21 @@ function evaluateMeasurementCached(definition, context, definitions, stack, stat
|
|
|
587
612
|
const cached = state.cache.get(definition.id);
|
|
588
613
|
if (cached)
|
|
589
614
|
return cached;
|
|
590
|
-
const evaluation = evaluateMeasurementInternal(definition, context, definitions, stack, state)
|
|
615
|
+
const evaluation = evaluateMeasurementInternal(definition, context, definitions, stack, state).catch((error) => {
|
|
616
|
+
if (error instanceof AssuranceSourceResolutionError &&
|
|
617
|
+
error.measurement_id === undefined) {
|
|
618
|
+
const sourceContext = {
|
|
619
|
+
measurement_id: definition.id,
|
|
620
|
+
source_kind: error.source_kind,
|
|
621
|
+
field: error.field,
|
|
622
|
+
...(error.check ? { check: error.check } : {}),
|
|
623
|
+
};
|
|
624
|
+
const sourceError = new AssuranceSourceResolutionError(error.message, sourceContext);
|
|
625
|
+
sourceError.cause = error;
|
|
626
|
+
throw sourceError;
|
|
627
|
+
}
|
|
628
|
+
throw error;
|
|
629
|
+
});
|
|
591
630
|
state.cache.set(definition.id, evaluation);
|
|
592
631
|
return evaluation;
|
|
593
632
|
}
|
|
@@ -664,6 +703,28 @@ function enforceGateProviderPolicy(gate, document, context, trigger) {
|
|
|
664
703
|
}
|
|
665
704
|
}
|
|
666
705
|
}
|
|
706
|
+
async function evaluateGateMeasurement(gateId, assertionId, definition, context, definitions) {
|
|
707
|
+
try {
|
|
708
|
+
return await evaluateMeasurement(definition, context, definitions);
|
|
709
|
+
}
|
|
710
|
+
catch (error) {
|
|
711
|
+
if (error instanceof AssuranceSourceResolutionError) {
|
|
712
|
+
const checkLocation = error.check ? ` check ${error.check}` : "";
|
|
713
|
+
const measurementId = error.measurement_id ?? definition.id;
|
|
714
|
+
const refusal = new AssuranceEvaluationRefusalError(`assurance gate ${gateId} assertion ${assertionId} measurement ${measurementId} source ${error.source_kind}${checkLocation} field ${error.field} could not resolve: ${error.message}`, {
|
|
715
|
+
gate_id: gateId,
|
|
716
|
+
assertion_id: assertionId,
|
|
717
|
+
measurement_id: measurementId,
|
|
718
|
+
source_kind: error.source_kind,
|
|
719
|
+
field: error.field,
|
|
720
|
+
...(error.check ? { check: error.check } : {}),
|
|
721
|
+
});
|
|
722
|
+
refusal.cause = error;
|
|
723
|
+
throw refusal;
|
|
724
|
+
}
|
|
725
|
+
throw error;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
667
728
|
/** Evaluate a named gate into one presentation-independent verdict document. */
|
|
668
729
|
export async function evaluateAssuranceGate(gateId, document, context, options) {
|
|
669
730
|
validateAssuranceDocument(document);
|
|
@@ -688,7 +749,7 @@ export async function evaluateAssuranceGate(gateId, document, context, options)
|
|
|
688
749
|
else if (assertionDefinition.scope.kind === "filter") {
|
|
689
750
|
const scopeMeasurementId = assertionDefinition.scope.measurement_id;
|
|
690
751
|
const scopeDefinition = document.measurements.find((entry) => entry.id === scopeMeasurementId);
|
|
691
|
-
const scope = await
|
|
752
|
+
const scope = await evaluateGateMeasurement(gateDefinition.id, assertionDefinition.id, scopeDefinition, context, document.measurements);
|
|
692
753
|
const contributorIds = new Set(scope.contributors);
|
|
693
754
|
scopedContext = {
|
|
694
755
|
...context,
|
|
@@ -698,7 +759,7 @@ export async function evaluateAssuranceGate(gateId, document, context, options)
|
|
|
698
759
|
const owner = context.items.find((item) => item.id === assertionDefinition.owner_item_id);
|
|
699
760
|
const ownerTerminal = owner !== undefined &&
|
|
700
761
|
new Set(context.terminal_statuses ?? ["closed", "canceled"]).has(owner.status);
|
|
701
|
-
return evaluateAssuranceAssertion(assertionDefinition, await
|
|
762
|
+
return evaluateAssuranceAssertion(assertionDefinition, await evaluateGateMeasurement(gateDefinition.id, assertionDefinition.id, measurementDefinition, scopedContext, document.measurements), { owner_terminal: ownerTerminal });
|
|
702
763
|
});
|
|
703
764
|
const blocking = assertions.some((entry) => entry.verdict === "fail" && entry.enforcement === "block");
|
|
704
765
|
const warning = assertions.some((entry) => entry.verdict === "fail" && entry.enforcement === "warn");
|
|
@@ -711,6 +772,11 @@ export async function evaluateAssuranceGate(gateId, document, context, options)
|
|
|
711
772
|
verdict: blocking ? "block" : warning ? "warn" : "pass",
|
|
712
773
|
exit_code: blocking ? 1 : 0,
|
|
713
774
|
assertions,
|
|
775
|
+
assertions_total: assertions.length,
|
|
776
|
+
row_contract: {
|
|
777
|
+
row_keys: ["assertions"],
|
|
778
|
+
jq_selector: ".assertions[]",
|
|
779
|
+
},
|
|
714
780
|
cost: sumCosts(assertions.map((entry) => entry.cost), Math.max(0, ...assertions.map((entry) => entry.cost.duration_ms))),
|
|
715
781
|
};
|
|
716
782
|
}
|
|
@@ -940,4 +1006,4 @@ export async function listAssuranceVerdicts(pmRoot, options = {}) {
|
|
|
940
1006
|
.slice(0, limit);
|
|
941
1007
|
}
|
|
942
1008
|
//# sourceMappingURL=assurance.js.map
|
|
943
|
-
//# debugId=
|
|
1009
|
+
//# debugId=2bf52d6d-7e4f-5ec5-86bd-3e817ef521bb
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/governance/coverage-assurance
|
|
3
|
+
*
|
|
4
|
+
* Provides exact integer coverage assurance for repository and package gates.
|
|
5
|
+
*/
|
|
6
|
+
/** Coverage metrics required by the exact repository quality contract. */
|
|
7
|
+
export declare const PM_EXACT_COVERAGE_METRICS: readonly ["lines", "branches", "functions", "statements"];
|
|
8
|
+
/** Required exact coverage metric. */
|
|
9
|
+
export type PmExactCoverageMetric = (typeof PM_EXACT_COVERAGE_METRICS)[number];
|
|
10
|
+
/** One exact uncovered-count finding. */
|
|
11
|
+
export interface PmCoverageDeficit {
|
|
12
|
+
/** Coverage summary entry or source filename. */
|
|
13
|
+
file: string;
|
|
14
|
+
/** Deficient required metric. */
|
|
15
|
+
metric: PmExactCoverageMetric;
|
|
16
|
+
/** Integer statements or paths not covered. */
|
|
17
|
+
uncovered: number;
|
|
18
|
+
/** Exact covered count. */
|
|
19
|
+
covered: number;
|
|
20
|
+
/** Exact total count. */
|
|
21
|
+
total: number;
|
|
22
|
+
}
|
|
23
|
+
/** Return exact uncovered counts for every summary entry and required metric. */
|
|
24
|
+
export declare function findCoverageDeficits(summary: unknown): PmCoverageDeficit[];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/governance/coverage-assurance
|
|
3
|
+
*
|
|
4
|
+
* Provides exact integer coverage assurance for repository and package gates.
|
|
5
|
+
*/
|
|
6
|
+
/** Coverage metrics required by the exact repository quality contract. */
|
|
7
|
+
|
|
8
|
+
!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]="340305b6-e3c8-5daa-bfbe-4a9c62a6d039")}catch(e){}}();
|
|
9
|
+
export const PM_EXACT_COVERAGE_METRICS = [
|
|
10
|
+
"lines",
|
|
11
|
+
"branches",
|
|
12
|
+
"functions",
|
|
13
|
+
"statements",
|
|
14
|
+
];
|
|
15
|
+
/** Require a coverage report entry to expose an object-shaped metric map. */
|
|
16
|
+
function assertCoverageEntry(file, entry) {
|
|
17
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
18
|
+
throw new TypeError(`Coverage entry for ${file} must be an object.`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Return exact validated counts for one required metric. */
|
|
22
|
+
function coverageCounts(file, metric, value) {
|
|
23
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
24
|
+
throw new TypeError(`Coverage entry ${file} has invalid ${metric} counts.`);
|
|
25
|
+
}
|
|
26
|
+
const counts = value;
|
|
27
|
+
if (typeof counts.covered !== "number" ||
|
|
28
|
+
typeof counts.total !== "number" ||
|
|
29
|
+
!Number.isInteger(counts.covered) ||
|
|
30
|
+
!Number.isInteger(counts.total) ||
|
|
31
|
+
counts.covered < 0 ||
|
|
32
|
+
counts.total < counts.covered) {
|
|
33
|
+
throw new TypeError(`Coverage entry ${file} has invalid ${metric} counts.`);
|
|
34
|
+
}
|
|
35
|
+
return { covered: counts.covered, total: counts.total };
|
|
36
|
+
}
|
|
37
|
+
/** Return exact uncovered counts for every summary entry and required metric. */
|
|
38
|
+
export function findCoverageDeficits(summary) {
|
|
39
|
+
if (typeof summary !== "object" ||
|
|
40
|
+
summary === null ||
|
|
41
|
+
Array.isArray(summary)) {
|
|
42
|
+
throw new TypeError("Coverage summary must be a JSON object.");
|
|
43
|
+
}
|
|
44
|
+
if (!("total" in summary)) {
|
|
45
|
+
throw new TypeError("Coverage summary is missing the total entry.");
|
|
46
|
+
}
|
|
47
|
+
const deficits = [];
|
|
48
|
+
for (const [file, entry] of Object.entries(summary)) {
|
|
49
|
+
assertCoverageEntry(file, entry);
|
|
50
|
+
for (const metric of PM_EXACT_COVERAGE_METRICS) {
|
|
51
|
+
const counts = coverageCounts(file, metric, entry[metric]);
|
|
52
|
+
const uncovered = counts.total - counts.covered;
|
|
53
|
+
if (uncovered > 0) {
|
|
54
|
+
deficits.push({ file, metric, uncovered, ...counts });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return deficits;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=coverage-assurance.js.map
|
|
61
|
+
//# debugId=340305b6-e3c8-5daa-bfbe-4a9c62a6d039
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { LoadedExtension } from "../../core/extensions/loader.js";
|
|
2
|
+
/** One distinct resolvable pm-cli installation and its extension consumers. */
|
|
3
|
+
export interface ExtensionHostVersionCopy {
|
|
4
|
+
/** Installed pm-cli version. */
|
|
5
|
+
version: string;
|
|
6
|
+
/** Privacy-safe workspace-relative package manifest location. */
|
|
7
|
+
path: string;
|
|
8
|
+
/** Dependency layout that exposed this copy. */
|
|
9
|
+
layout: "host" | "npm" | "pnpm" | "other";
|
|
10
|
+
/** Loaded extensions resolving this copy. */
|
|
11
|
+
consumers: string[];
|
|
12
|
+
}
|
|
13
|
+
/** Extension/host version census returned by the health SDK. */
|
|
14
|
+
export interface ExtensionHostVersionCensus {
|
|
15
|
+
/** Version of the process-hosting pm-cli package. */
|
|
16
|
+
host_version: string | null;
|
|
17
|
+
/** Every distinct relevant copy resolved by the host or an extension. */
|
|
18
|
+
copies: ExtensionHostVersionCopy[];
|
|
19
|
+
/** Copies whose version differs from the process host. */
|
|
20
|
+
mismatches: ExtensionHostVersionCopy[];
|
|
21
|
+
/** Stable health warning tokens for mismatched copies. */
|
|
22
|
+
warnings: string[];
|
|
23
|
+
}
|
|
24
|
+
/** Scan the host plus the nearest pm-cli package resolvable by every loaded extension. */
|
|
25
|
+
export declare function scanExtensionHostVersions(loadedExtensions: readonly LoadedExtension[], workspaceRoot: string, hostPackageRoot?: string): Promise<ExtensionHostVersionCensus>;
|