@unbrained/pm-cli 2026.8.6 → 2026.8.8
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 +65 -0
- package/dist/cli/main.js +6 -3
- package/dist/cli/register-annotations.d.ts +11 -0
- package/dist/cli/register-annotations.js +195 -0
- package/dist/cli/register-history-author.js +7 -30
- package/dist/cli/register-mutation.js +25 -206
- package/dist/cli/register-operations.js +11 -2
- package/dist/cli/runtime-compatibility-boundary.d.ts +17 -0
- package/dist/cli/runtime-compatibility-boundary.js +43 -0
- package/dist/cli/stats-analytics-json.d.ts +9 -0
- package/dist/cli/stats-analytics-json.js +69 -0
- package/dist/cli-bundle/bundle-manifest.json +156 -692
- package/dist/cli-bundle/chunks/chunk-2ZMXX3Q6.js +2068 -0
- package/dist/cli-bundle/chunks/chunk-ALDHXLPS.js +3 -0
- package/dist/cli-bundle/chunks/chunk-CBLA33YK.js +8 -0
- package/dist/cli-bundle/chunks/chunk-GKA54IJM.js +5 -0
- package/dist/cli-bundle/chunks/chunk-KRY7SRUO.js +2 -0
- package/dist/cli-bundle/chunks/chunk-MNJ4NNSY.js +26 -0
- package/dist/cli-bundle/chunks/chunk-NUXRRNAB.js +77 -0
- package/dist/cli-bundle/chunks/chunk-OJPCFDDY.js +13 -0
- package/dist/cli-bundle/chunks/chunk-PFSD3DAN.js +194 -0
- package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +2 -0
- package/dist/cli-bundle/chunks/chunk-SQ7QZFQ6.js +2 -0
- package/dist/cli-bundle/chunks/{register-list-query-QH7ONPKU.js → register-list-query-WFZAMJHZ.js} +8 -8
- package/dist/cli-bundle/chunks/register-mutation-SOKKOTHQ.js +20 -0
- package/dist/cli-bundle/chunks/register-operations-5XQETS6E.js +2 -0
- package/dist/cli-bundle/chunks/register-setup-2HL5ZHMK.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-54EU2UVO.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-N7QN3NE6.js → chunk-5FLBTZJQ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-5GJ57YKN.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-YLPZHWX7.js → chunk-ANTMGYLI.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-CMDS3KYT.js +14 -0
- package/dist/cli-bundle/focused-chunks/{chunk-EYO4F74Z.js → chunk-DMKOMTTY.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-GSW2Y7VZ.js → chunk-F5B3HBEZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-27DK4A5O.js → chunk-FI6DWU2M.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-CL3NB7VW.js → chunk-FNOKJG6N.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-EAXXF2HW.js → chunk-FPDYXZBK.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-XNVXIQ4B.js → chunk-GWI6YIKJ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-6KDHXURF.js → chunk-HCUC62AB.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-GEYU23YS.js → chunk-HGNKPSCB.js} +22 -22
- package/dist/cli-bundle/focused-chunks/chunk-IAS7PMLG.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-TQMFQYXR.js → chunk-PL2EYDJK.js} +29 -29
- package/dist/cli-bundle/focused-chunks/chunk-SM2PJGP3.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-4JC3AOGS.js → chunk-TCSAPH33.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-U646T7Z6.js +18 -0
- package/dist/cli-bundle/focused-chunks/chunk-YKPE4PPY.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-GIERI4YU.js → chunk-YSAHYUXX.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-ZOLDTUU7.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 +38 -37
- 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 +1 -1
- 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 -1
- package/dist/cli.js +14 -4
- package/dist/core/extensions/reserved-host-flags.js +3 -2
- package/dist/core/history/workspace-history.d.ts +22 -2
- package/dist/core/history/workspace-history.js +60 -36
- package/dist/core/output/output.d.ts +2 -0
- package/dist/core/output/output.js +10 -2
- package/dist/core/sentry/helpers.d.ts +10 -0
- package/dist/core/sentry/helpers.js +59 -4
- package/dist/core/shared/command-types.d.ts +2 -0
- package/dist/core/shared/command-types.js +2 -2
- package/dist/core/shared/constants.d.ts +2 -0
- package/dist/core/shared/constants.js +4 -2
- package/dist/mcp/tool-definitions.js +6 -2
- package/dist/sdk/annotations.d.ts +40 -0
- package/dist/sdk/annotations.js +61 -9
- package/dist/sdk/author-attribution.d.ts +12 -0
- package/dist/sdk/author-attribution.js +87 -9
- package/dist/sdk/cli-bootstrap.d.ts +2 -0
- package/dist/sdk/cli-bootstrap.js +7 -2
- package/dist/sdk/cli-contracts/command-exit-contracts.d.ts +118 -0
- package/dist/sdk/cli-contracts/command-exit-contracts.js +152 -0
- package/dist/sdk/cli-contracts/completeness.js +54 -5
- 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 +11 -0
- package/dist/sdk/cli-contracts/runtime-contracts.js +41 -8
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +129 -10
- package/dist/sdk/cli-contracts/tool-schema.d.ts +1 -1
- package/dist/sdk/cli-contracts/tool-schema.js +22 -3
- package/dist/sdk/cli-program.js +3 -2
- package/dist/sdk/comments.d.ts +7 -0
- package/dist/sdk/comments.js +2 -2
- package/dist/sdk/completion.js +12 -5
- package/dist/sdk/contracts.d.ts +2 -0
- package/dist/sdk/contracts.js +3 -2
- package/dist/sdk/core.d.ts +3 -1
- package/dist/sdk/core.js +4 -3
- package/dist/sdk/environment/host-environment-errors.d.ts +27 -0
- package/dist/sdk/environment/host-environment-errors.js +124 -0
- package/dist/sdk/environment/project-runtime-compatibility.d.ts +65 -0
- package/dist/sdk/environment/project-runtime-compatibility.js +385 -0
- package/dist/sdk/environment/source-context.d.ts +23 -0
- package/dist/sdk/environment/source-context.js +29 -0
- package/dist/sdk/error-code-catalog.d.ts +6 -0
- package/dist/sdk/error-code-catalog.js +62 -8
- package/dist/sdk/extension.js +9 -11
- package/dist/sdk/generated-error-code-catalog.js +739 -3
- package/dist/sdk/governance/health.d.ts +11 -3
- package/dist/sdk/governance/health.js +5 -5
- package/dist/sdk/history-analytics.d.ts +141 -0
- package/dist/sdk/history-analytics.js +283 -0
- package/dist/sdk/improvement-ledger-validation.d.ts +3 -0
- package/dist/sdk/improvement-ledger-validation.js +63 -0
- package/dist/sdk/improvement-ledger.d.ts +139 -0
- package/dist/sdk/improvement-ledger.js +261 -0
- package/dist/sdk/index.d.ts +13 -5
- package/dist/sdk/index.js +15 -7
- package/dist/sdk/learnings.d.ts +15 -0
- package/dist/sdk/learnings.js +2 -2
- package/dist/sdk/lifecycle/close-many.d.ts +6 -1
- package/dist/sdk/lifecycle/close-many.js +43 -5
- package/dist/sdk/lifecycle/plan.js +6 -3
- package/dist/sdk/lifecycle/update-many.d.ts +2 -1
- package/dist/sdk/lifecycle/update-many.js +29 -5
- package/dist/sdk/merge/index.d.ts +1 -1
- package/dist/sdk/merge/index.js +3 -3
- package/dist/sdk/merge/install.d.ts +21 -0
- package/dist/sdk/merge/install.js +58 -20
- package/dist/sdk/notes.d.ts +7 -0
- package/dist/sdk/notes.js +2 -2
- package/dist/sdk/read-output-budget.js +24 -22
- package/dist/sdk/read-output-contracts.d.ts +10 -2
- package/dist/sdk/read-output-contracts.js +204 -66
- package/dist/sdk/read-output-rows.d.ts +29 -0
- package/dist/sdk/read-output-rows.js +100 -0
- package/dist/sdk/read-output-session.d.ts +69 -0
- package/dist/sdk/read-output-session.js +200 -0
- package/dist/sdk/runtime-input.d.ts +2 -0
- package/dist/sdk/runtime-input.js +14 -2
- package/dist/sdk/runtime-primitives.d.ts +1 -1
- package/dist/sdk/runtime-primitives.js +3 -3
- package/dist/sdk/runtime-stats-options.d.ts +9 -0
- package/dist/sdk/runtime-stats-options.js +38 -0
- package/dist/sdk/runtime.d.ts +1 -0
- package/dist/sdk/runtime.js +13 -50
- package/dist/sdk/stats.d.ts +40 -0
- package/dist/sdk/stats.js +112 -29
- package/dist/sdk/test/execution.js +4 -2
- package/dist/sdk/test/parsers.js +5 -2
- package/dist/sdk/workspace-snapshot.d.ts +9 -0
- package/dist/sdk/workspace-snapshot.js +48 -16
- package/docs/AGENT_RUNTIME_PRIMITIVES.md +11 -4
- package/docs/IMPROVEMENT_ANALYTICS.md +103 -0
- package/docs/OUTPUT_PROJECTION_CONTRACTS.md +5 -5
- package/docs/README.md +2 -0
- package/docs/READ_OUTPUT_CONTRACTS.md +60 -1
- package/docs/RELEASING.md +27 -2
- package/docs/SCRIPTING.md +27 -1
- package/docs/SDK_CONTEXT_INTEGRITY.md +66 -0
- package/docs/SDK_RUNTIME_BOUNDARIES.md +58 -0
- package/docs/SELF_DESCRIBING_CONTEXT_CONTRACTS.md +13 -0
- package/docs/TESTING.md +17 -0
- package/marketplace.json +2 -2
- package/package.json +6 -4
- 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 +875 -827
- package/dist/cli-bundle/chunks/append-XAJ5Z4XS.js +0 -2
- package/dist/cli-bundle/chunks/chunk-343QETLI.js +0 -2
- package/dist/cli-bundle/chunks/chunk-3KFVGGRE.js +0 -2
- package/dist/cli-bundle/chunks/chunk-3ZJRFYY2.js +0 -23
- package/dist/cli-bundle/chunks/chunk-4AVFKHHC.js +0 -2
- package/dist/cli-bundle/chunks/chunk-4OVGQW22.js +0 -2
- package/dist/cli-bundle/chunks/chunk-5PBP2ZP3.js +0 -2
- package/dist/cli-bundle/chunks/chunk-5ZKQPA44.js +0 -2
- package/dist/cli-bundle/chunks/chunk-A3XQ7VPU.js +0 -2
- package/dist/cli-bundle/chunks/chunk-A6KGKEWT.js +0 -2
- package/dist/cli-bundle/chunks/chunk-AJE3AHPD.js +0 -8
- package/dist/cli-bundle/chunks/chunk-AOBDLU4T.js +0 -2
- package/dist/cli-bundle/chunks/chunk-AYRUGRNS.js +0 -3
- package/dist/cli-bundle/chunks/chunk-BP6EMEDP.js +0 -5
- package/dist/cli-bundle/chunks/chunk-BXCSXK4J.js +0 -2
- package/dist/cli-bundle/chunks/chunk-C3YABSJK.js +0 -2
- package/dist/cli-bundle/chunks/chunk-CA3BURYF.js +0 -2
- package/dist/cli-bundle/chunks/chunk-CHOQ2VAW.js +0 -2
- package/dist/cli-bundle/chunks/chunk-D7I3TUGV.js +0 -2
- package/dist/cli-bundle/chunks/chunk-DQGJ2RWT.js +0 -3
- package/dist/cli-bundle/chunks/chunk-DWOAOZHZ.js +0 -2
- package/dist/cli-bundle/chunks/chunk-E2ZSLTOP.js +0 -2
- package/dist/cli-bundle/chunks/chunk-E7BFPLUZ.js +0 -5
- package/dist/cli-bundle/chunks/chunk-F4NREH3G.js +0 -2
- package/dist/cli-bundle/chunks/chunk-FB7G2HY2.js +0 -2
- package/dist/cli-bundle/chunks/chunk-FDBRXV25.js +0 -2
- package/dist/cli-bundle/chunks/chunk-GU3TSEHD.js +0 -2
- package/dist/cli-bundle/chunks/chunk-HS7OVAUN.js +0 -164
- package/dist/cli-bundle/chunks/chunk-JC6FKIFM.js +0 -2
- package/dist/cli-bundle/chunks/chunk-JFZIS6JF.js +0 -2
- package/dist/cli-bundle/chunks/chunk-JQ4NZ5EB.js +0 -2
- package/dist/cli-bundle/chunks/chunk-L6LGKJX3.js +0 -2
- package/dist/cli-bundle/chunks/chunk-LEPJJ6QC.js +0 -2
- package/dist/cli-bundle/chunks/chunk-M357ZCOR.js +0 -2
- package/dist/cli-bundle/chunks/chunk-M4VEE3FK.js +0 -2
- package/dist/cli-bundle/chunks/chunk-MCS73BKB.js +0 -3
- package/dist/cli-bundle/chunks/chunk-MDTH7SAE.js +0 -19
- package/dist/cli-bundle/chunks/chunk-NE5VRDAI.js +0 -2
- package/dist/cli-bundle/chunks/chunk-OXY3SJ3N.js +0 -2
- package/dist/cli-bundle/chunks/chunk-PECV7L5T.js +0 -2
- package/dist/cli-bundle/chunks/chunk-Q3VOP62W.js +0 -2
- package/dist/cli-bundle/chunks/chunk-QJ7C3JIW.js +0 -2
- package/dist/cli-bundle/chunks/chunk-R6LSRGPS.js +0 -8
- package/dist/cli-bundle/chunks/chunk-R6RKEYYW.js +0 -2
- package/dist/cli-bundle/chunks/chunk-RAFUN7IX.js +0 -2005
- package/dist/cli-bundle/chunks/chunk-RSIC5OPE.js +0 -2
- package/dist/cli-bundle/chunks/chunk-RUAU5OSH.js +0 -2
- package/dist/cli-bundle/chunks/chunk-SD3YXU2U.js +0 -56
- package/dist/cli-bundle/chunks/chunk-SV3YQ4RY.js +0 -2
- package/dist/cli-bundle/chunks/chunk-SVV3DQES.js +0 -2
- package/dist/cli-bundle/chunks/chunk-SXECIECW.js +0 -5
- package/dist/cli-bundle/chunks/chunk-T45OHXDW.js +0 -8
- package/dist/cli-bundle/chunks/chunk-TPKDJ5WL.js +0 -2
- package/dist/cli-bundle/chunks/chunk-UVVXHGYS.js +0 -3
- package/dist/cli-bundle/chunks/chunk-V663653R.js +0 -20
- package/dist/cli-bundle/chunks/chunk-WSI5KZQJ.js +0 -55
- package/dist/cli-bundle/chunks/chunk-XPOQQJTX.js +0 -13
- package/dist/cli-bundle/chunks/chunk-YCCDXBNU.js +0 -2
- package/dist/cli-bundle/chunks/chunk-ZFBWCKYF.js +0 -2
- package/dist/cli-bundle/chunks/close-DI66JMSB.js +0 -2
- package/dist/cli-bundle/chunks/close-many-VFKT6U3O.js +0 -2
- package/dist/cli-bundle/chunks/comments-E73HIEZJ.js +0 -2
- package/dist/cli-bundle/chunks/copy-WBYVLCPC.js +0 -2
- package/dist/cli-bundle/chunks/create-TG67IVFI.js +0 -2
- package/dist/cli-bundle/chunks/delete-6XKUVVQN.js +0 -2
- package/dist/cli-bundle/chunks/deps-AJUGP2OH.js +0 -2
- package/dist/cli-bundle/chunks/docs-QOCLDRKJ.js +0 -2
- package/dist/cli-bundle/chunks/files-3ST5TY64.js +0 -2
- package/dist/cli-bundle/chunks/focus-R2AWS63Y.js +0 -2
- package/dist/cli-bundle/chunks/history-compact-7BJFML4S.js +0 -2
- package/dist/cli-bundle/chunks/history-redact-WJN3HYXR.js +0 -2
- package/dist/cli-bundle/chunks/history-repair-XDNZUB7F.js +0 -2
- package/dist/cli-bundle/chunks/learnings-SZMUPVNA.js +0 -2
- package/dist/cli-bundle/chunks/profile-KL53JIAC.js +0 -2
- package/dist/cli-bundle/chunks/register-mutation-OCRQNZK4.js +0 -20
- package/dist/cli-bundle/chunks/register-operations-HIBJXRGB.js +0 -2
- package/dist/cli-bundle/chunks/register-setup-QWBQ6HBS.js +0 -2
- package/dist/cli-bundle/chunks/restore-FXA5QPM7.js +0 -2
- package/dist/cli-bundle/chunks/schema-QJ27OTRV.js +0 -2
- package/dist/cli-bundle/chunks/update-7GBO4SXG.js +0 -2
- package/dist/cli-bundle/chunks/update-many-VF6ZKQUO.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-74CWP3A4.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-7AZDTGPA.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-7YTZ7A4E.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-LKQXXO62.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-MBBMTDD3.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-ME4XVOBJ.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-QL5H3AQH.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-YHDCGUIW.js +0 -14
|
@@ -45,13 +45,13 @@ export interface RunHealthOptions {
|
|
|
45
45
|
strictDirectories?: boolean;
|
|
46
46
|
/** Treat absent clone-local merge drivers as a required health failure instead of an advisory. */
|
|
47
47
|
requireMergeDrivers?: boolean;
|
|
48
|
-
/**
|
|
48
|
+
/** Preserve the legacy compact check projection while keeping diagnostics read-only. */
|
|
49
49
|
checkOnly?: boolean;
|
|
50
50
|
/** Value that configures or reports check telemetry for this contract. */
|
|
51
51
|
checkTelemetry?: boolean;
|
|
52
|
-
/**
|
|
52
|
+
/** Explicitly document that vector refresh is disabled. */
|
|
53
53
|
noRefresh?: boolean;
|
|
54
|
-
/**
|
|
54
|
+
/** Opt in to the only mutating health operation: refreshing stale vectors. */
|
|
55
55
|
refreshVectors?: boolean;
|
|
56
56
|
/** Value that configures or reports verbose stale items for this contract. */
|
|
57
57
|
verboseStaleItems?: boolean;
|
|
@@ -70,6 +70,12 @@ export interface RunHealthOptions {
|
|
|
70
70
|
/** Value that configures or reports summary for this contract. */
|
|
71
71
|
summary?: boolean;
|
|
72
72
|
}
|
|
73
|
+
interface VectorRefreshPolicy {
|
|
74
|
+
enabled: boolean;
|
|
75
|
+
checkOnly: boolean;
|
|
76
|
+
noRefresh: boolean;
|
|
77
|
+
refreshVectors: boolean;
|
|
78
|
+
}
|
|
73
79
|
interface MigrationStatusEntry {
|
|
74
80
|
layer: "global" | "project";
|
|
75
81
|
name: string;
|
|
@@ -163,6 +169,7 @@ declare function probeTelemetryEndpointHealth(endpoint: string): Promise<{
|
|
|
163
169
|
error?: string;
|
|
164
170
|
}>;
|
|
165
171
|
declare function buildVectorizationProviderDetails(settings: PmSettings, snapshot: VectorizationRuntimeSnapshot): Record<string, unknown>;
|
|
172
|
+
declare function resolveVectorRefreshPolicy(options: RunHealthOptions): VectorRefreshPolicy;
|
|
166
173
|
interface HealthSkipPolicy {
|
|
167
174
|
summaryMode: boolean;
|
|
168
175
|
skipIntegrity: boolean;
|
|
@@ -196,6 +203,7 @@ export declare const _testOnlyHealthCommand: {
|
|
|
196
203
|
resolveActionableUnknownAuthorEventCount: (authorAttribution: HistoryAuthorAttributionScan) => number;
|
|
197
204
|
resolveHealthSkipPolicy: typeof resolveHealthSkipPolicy;
|
|
198
205
|
resolveUnknownAuthorEventCount: (authorAttribution: HistoryAuthorAttributionScan) => number;
|
|
206
|
+
resolveVectorRefreshPolicy: typeof resolveVectorRefreshPolicy;
|
|
199
207
|
selectStaleItemDetail: typeof selectStaleItemDetail;
|
|
200
208
|
summarizeHealthCheckDetails: typeof summarizeHealthCheckDetails;
|
|
201
209
|
summarizeExtensionList: typeof summarizeExtensionList;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements the pm health command surface and its agent-facing runtime behavior.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="4efa3db2-6be7-5650-b1c7-d80e125694aa")}catch(e){}}();
|
|
8
8
|
import fs from "node:fs/promises";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
|
|
@@ -1549,7 +1549,6 @@ function validateSettingsValues(settings) {
|
|
|
1549
1549
|
}
|
|
1550
1550
|
function resolveVectorRefreshPolicy(options) {
|
|
1551
1551
|
const checkOnly = options.checkOnly === true;
|
|
1552
|
-
const noRefresh = options.noRefresh === true || checkOnly;
|
|
1553
1552
|
const refreshVectors = options.refreshVectors === true;
|
|
1554
1553
|
if (refreshVectors && checkOnly) {
|
|
1555
1554
|
throw new PmCliError("--check-only cannot be combined with --refresh-vectors", EXIT_CODE.USAGE);
|
|
@@ -1558,9 +1557,9 @@ function resolveVectorRefreshPolicy(options) {
|
|
|
1558
1557
|
throw new PmCliError("--no-refresh cannot be combined with --refresh-vectors", EXIT_CODE.USAGE);
|
|
1559
1558
|
}
|
|
1560
1559
|
return {
|
|
1561
|
-
enabled: refreshVectors
|
|
1560
|
+
enabled: refreshVectors,
|
|
1562
1561
|
checkOnly,
|
|
1563
|
-
noRefresh,
|
|
1562
|
+
noRefresh: !refreshVectors,
|
|
1564
1563
|
refreshVectors,
|
|
1565
1564
|
};
|
|
1566
1565
|
}
|
|
@@ -1955,6 +1954,7 @@ export const _testOnlyHealthCommand = {
|
|
|
1955
1954
|
resolveActionableUnknownAuthorEventCount,
|
|
1956
1955
|
resolveHealthSkipPolicy,
|
|
1957
1956
|
resolveUnknownAuthorEventCount,
|
|
1957
|
+
resolveVectorRefreshPolicy,
|
|
1958
1958
|
selectStaleItemDetail,
|
|
1959
1959
|
summarizeHealthCheckDetails,
|
|
1960
1960
|
summarizeExtensionList,
|
|
@@ -1964,4 +1964,4 @@ export const _testOnlyHealthCommand = {
|
|
|
1964
1964
|
warningCode,
|
|
1965
1965
|
};
|
|
1966
1966
|
//# sourceMappingURL=health.js.map
|
|
1967
|
-
//# debugId=
|
|
1967
|
+
//# debugId=4efa3db2-6be7-5650-b1c7-d80e125694aa
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/history-analytics
|
|
3
|
+
*
|
|
4
|
+
* Derives bounded provenance coverage and fleet outcome analytics from the
|
|
5
|
+
* immutable history event index without introducing telemetry-owned state.
|
|
6
|
+
*/
|
|
7
|
+
import { type HarnessSignalDescriptor } from "../core/shared/author.js";
|
|
8
|
+
import type { HistoryEntry, ItemMetadata } from "../types/index.js";
|
|
9
|
+
import { type AgentProvenanceDescriptorCoverage, type AgentProvenanceDimensionCoverage } from "./provenance.js";
|
|
10
|
+
/** Bounded immutable-history window controls shared by analytics surfaces. */
|
|
11
|
+
export interface HistoryAnalyticsWindowOptions {
|
|
12
|
+
/** Inclusive ISO timestamp or negative day/hour duration such as -30d. */
|
|
13
|
+
since?: string;
|
|
14
|
+
/** Maximum indexed events consumed across all pages. */
|
|
15
|
+
eventLimit?: number;
|
|
16
|
+
/** Minimum denominator required before a rate is reported. */
|
|
17
|
+
minimumSample?: number;
|
|
18
|
+
}
|
|
19
|
+
/** Read receipt proving how much immutable history contributed. */
|
|
20
|
+
export interface HistoryAnalyticsWindowReceipt {
|
|
21
|
+
/** Inclusive lower bound used for the scan. */
|
|
22
|
+
since: string;
|
|
23
|
+
/** Number of indexed immutable events inspected. */
|
|
24
|
+
events: number;
|
|
25
|
+
/** Whether the configured event ceiling omitted matching rows. */
|
|
26
|
+
truncated: boolean;
|
|
27
|
+
/** Cursor that resumes after the last inspected event when truncated. */
|
|
28
|
+
next_cursor?: string;
|
|
29
|
+
/** Derived read source. */
|
|
30
|
+
source: "history_event_index";
|
|
31
|
+
}
|
|
32
|
+
/** Live declared-versus-observed provenance report. */
|
|
33
|
+
export interface ProvenanceCoverageAnalytics {
|
|
34
|
+
/** Descriptor coverage for every declared dimension. */
|
|
35
|
+
descriptors: AgentProvenanceDescriptorCoverage[];
|
|
36
|
+
/** Per-harness availability over the bounded event window. */
|
|
37
|
+
observations: AgentProvenanceDimensionCoverage[];
|
|
38
|
+
/** Declared dimensions with enough explicit samples but no observations. */
|
|
39
|
+
inert: Array<{
|
|
40
|
+
harness: string;
|
|
41
|
+
dimension: string;
|
|
42
|
+
explicit_samples: number;
|
|
43
|
+
}>;
|
|
44
|
+
/** Dimensions no configured harness declares. */
|
|
45
|
+
undeclared: string[];
|
|
46
|
+
/** Stable warning codes suitable for health/gate adapters. */
|
|
47
|
+
warnings: string[];
|
|
48
|
+
/** Bounded source receipt. */
|
|
49
|
+
window: HistoryAnalyticsWindowReceipt;
|
|
50
|
+
}
|
|
51
|
+
/** One bounded attribution bucket with honest denominator states. */
|
|
52
|
+
export interface FleetAttributionRow {
|
|
53
|
+
/** Recorded grouping value. */
|
|
54
|
+
value: string;
|
|
55
|
+
/** Immutable events attributed to the bucket. */
|
|
56
|
+
events: number;
|
|
57
|
+
/** State-changing events attributed to the bucket. */
|
|
58
|
+
state_events: number;
|
|
59
|
+
/** Annotation/evidence events attributed to the bucket. */
|
|
60
|
+
annotation_events: number;
|
|
61
|
+
/** Terminal transitions attributed to the bucket. */
|
|
62
|
+
closes: number;
|
|
63
|
+
/** Active transitions after a terminal transition in the observed window. */
|
|
64
|
+
reopens: number;
|
|
65
|
+
/** Issue items linked discovered_from to work closed by this bucket. */
|
|
66
|
+
defect_escapes: number;
|
|
67
|
+
/** Terminal transitions per observed day, or null for insufficient samples. */
|
|
68
|
+
throughput_per_day: number | null;
|
|
69
|
+
/** Reopens divided by closes, or null for insufficient samples. */
|
|
70
|
+
rework_rate: number | null;
|
|
71
|
+
/** Defect escapes divided by closes, or null for insufficient samples. */
|
|
72
|
+
defect_escape_rate: number | null;
|
|
73
|
+
/** Denominator state preventing tiny samples from masquerading as rates. */
|
|
74
|
+
sample_status: "available" | "insufficient";
|
|
75
|
+
}
|
|
76
|
+
/** One supported fleet grouping dimension. */
|
|
77
|
+
export interface FleetAttributionDimension {
|
|
78
|
+
/** Stable dimension name. */
|
|
79
|
+
dimension: "harness" | "model" | "author_source";
|
|
80
|
+
/** Whether at least one event supplied this dimension. */
|
|
81
|
+
status: "available" | "unavailable";
|
|
82
|
+
/** Deterministically sorted bounded aggregate rows. */
|
|
83
|
+
rows: FleetAttributionRow[];
|
|
84
|
+
}
|
|
85
|
+
/** Observational fleet analytics derived only from immutable history. */
|
|
86
|
+
export interface FleetAttributionAnalytics {
|
|
87
|
+
/** Grouped analytics for every supported provenance dimension. */
|
|
88
|
+
dimensions: FleetAttributionDimension[];
|
|
89
|
+
/** Minimum close denominator required for rates. */
|
|
90
|
+
minimum_sample: number;
|
|
91
|
+
/** Safety statement retained in every transport. */
|
|
92
|
+
policy: "observational_only_not_for_authorization_or_routing";
|
|
93
|
+
/** Bounded source receipt. */
|
|
94
|
+
window: HistoryAnalyticsWindowReceipt;
|
|
95
|
+
}
|
|
96
|
+
/** One immutable history entry paired with its owning tracked item. */
|
|
97
|
+
export interface HistoryAnalyticsEvent {
|
|
98
|
+
/** Tracked item owning the immutable event. */
|
|
99
|
+
item_id: string;
|
|
100
|
+
/** Immutable history entry consumed by analytics. */
|
|
101
|
+
entry: HistoryEntry;
|
|
102
|
+
}
|
|
103
|
+
/** Reusable bounded history read shared across multiple analytics projections. */
|
|
104
|
+
export interface HistoryAnalyticsWindow {
|
|
105
|
+
/** Immutable events retained by the configured bound. */
|
|
106
|
+
events: HistoryAnalyticsEvent[];
|
|
107
|
+
/** Receipt describing the bounded source read. */
|
|
108
|
+
receipt: HistoryAnalyticsWindowReceipt;
|
|
109
|
+
}
|
|
110
|
+
declare function parseHistoryAnalyticsLimit(value: number | undefined): number;
|
|
111
|
+
declare function parseMinimumSample(value: number | undefined): number;
|
|
112
|
+
declare function resolveHistoryAnalyticsSince(value: string | undefined): string;
|
|
113
|
+
/** Read one reusable bounded immutable-history window. */
|
|
114
|
+
export declare function readHistoryAnalyticsWindow(pmRoot: string, options: HistoryAnalyticsWindowOptions): Promise<HistoryAnalyticsWindow>;
|
|
115
|
+
declare function provenanceValue(entry: HistoryEntry, dimension: FleetAttributionDimension["dimension"]): string | undefined;
|
|
116
|
+
declare function statusFromEntry(entry: HistoryEntry): string | undefined;
|
|
117
|
+
declare function annotationOperation(op: string): boolean;
|
|
118
|
+
declare function buildFleetDimension(dimension: FleetAttributionDimension["dimension"], events: readonly HistoryAnalyticsEvent[], items: readonly Pick<ItemMetadata, "id" | "type" | "dependencies">[], terminalStatuses: ReadonlySet<string>, minimumSample: number, windowDays: number): FleetAttributionDimension;
|
|
119
|
+
declare function resolveHistoryWindowDays(events: readonly HistoryAnalyticsEvent[], since: string): number;
|
|
120
|
+
/** Evaluate a negative-control-friendly declared-versus-observed coverage gate. */
|
|
121
|
+
export declare function evaluateProvenanceCoverage(entries: readonly HistoryEntry[], descriptors: readonly HarnessSignalDescriptor[], minimumSample: number): Omit<ProvenanceCoverageAnalytics, "window">;
|
|
122
|
+
/** Read live, bounded provenance coverage from authoritative history. */
|
|
123
|
+
export declare function runProvenanceCoverageAnalytics(pmRoot: string, descriptors?: readonly HarnessSignalDescriptor[], options?: HistoryAnalyticsWindowOptions): Promise<ProvenanceCoverageAnalytics>;
|
|
124
|
+
/** Project provenance coverage from an already-read immutable-history window. */
|
|
125
|
+
export declare function projectProvenanceCoverageAnalytics(window: HistoryAnalyticsWindow, descriptors?: readonly HarnessSignalDescriptor[], options?: Pick<HistoryAnalyticsWindowOptions, "minimumSample">): ProvenanceCoverageAnalytics;
|
|
126
|
+
/** Derive bounded fleet rates grouped by harness, model, and author source. */
|
|
127
|
+
export declare function runFleetAttributionAnalytics(pmRoot: string, items: readonly Pick<ItemMetadata, "id" | "type" | "dependencies">[], terminalStatuses: ReadonlySet<string>, options?: HistoryAnalyticsWindowOptions): Promise<FleetAttributionAnalytics>;
|
|
128
|
+
/** Project fleet attribution from an already-read immutable-history window. */
|
|
129
|
+
export declare function projectFleetAttributionAnalytics(window: HistoryAnalyticsWindow, items: readonly Pick<ItemMetadata, "id" | "type" | "dependencies">[], terminalStatuses: ReadonlySet<string>, options?: Pick<HistoryAnalyticsWindowOptions, "minimumSample">): FleetAttributionAnalytics;
|
|
130
|
+
/** Pure seams for deterministic analytics and negative-control tests. */
|
|
131
|
+
export declare const _testOnlyHistoryAnalytics: {
|
|
132
|
+
annotationOperation: typeof annotationOperation;
|
|
133
|
+
buildFleetDimension: typeof buildFleetDimension;
|
|
134
|
+
parseHistoryAnalyticsLimit: typeof parseHistoryAnalyticsLimit;
|
|
135
|
+
parseMinimumSample: typeof parseMinimumSample;
|
|
136
|
+
provenanceValue: typeof provenanceValue;
|
|
137
|
+
resolveHistoryAnalyticsSince: typeof resolveHistoryAnalyticsSince;
|
|
138
|
+
resolveHistoryWindowDays: typeof resolveHistoryWindowDays;
|
|
139
|
+
statusFromEntry: typeof statusFromEntry;
|
|
140
|
+
};
|
|
141
|
+
export {};
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/history-analytics
|
|
3
|
+
*
|
|
4
|
+
* Derives bounded provenance coverage and fleet outcome analytics from the
|
|
5
|
+
* immutable history event index without introducing telemetry-owned state.
|
|
6
|
+
*/
|
|
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]="f0e89b0b-ccd1-5dbb-afad-119d5a98590a")}catch(e){}}();
|
|
9
|
+
import { AGENT_PROVENANCE_DIMENSIONS, BUILTIN_HARNESS_SIGNAL_DESCRIPTORS, } from "../core/shared/author.js";
|
|
10
|
+
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
11
|
+
import { PmCliError } from "../core/shared/errors.js";
|
|
12
|
+
import { listMutationEvents } from "./mutation-events.js";
|
|
13
|
+
import { analyzeAgentProvenanceDescriptorCoverage, summarizeAgentProvenance, } from "./provenance.js";
|
|
14
|
+
const DEFAULT_HISTORY_ANALYTICS_LIMIT = 10_000;
|
|
15
|
+
const MAX_HISTORY_ANALYTICS_LIMIT = 100_000;
|
|
16
|
+
const HISTORY_EVENT_PAGE_LIMIT = 1_000;
|
|
17
|
+
const DEFAULT_HISTORY_WINDOW_DAYS = 30;
|
|
18
|
+
const ANNOTATION_OPERATION_PREFIXES = [
|
|
19
|
+
"append",
|
|
20
|
+
"comment",
|
|
21
|
+
"docs",
|
|
22
|
+
"file",
|
|
23
|
+
"learning",
|
|
24
|
+
"note",
|
|
25
|
+
"test_run",
|
|
26
|
+
];
|
|
27
|
+
function parseHistoryAnalyticsLimit(value) {
|
|
28
|
+
const limit = value ?? DEFAULT_HISTORY_ANALYTICS_LIMIT;
|
|
29
|
+
if (!Number.isSafeInteger(limit) ||
|
|
30
|
+
limit < 1 ||
|
|
31
|
+
limit > MAX_HISTORY_ANALYTICS_LIMIT) {
|
|
32
|
+
throw new PmCliError(`History analytics event limit must be an integer from 1 to ${MAX_HISTORY_ANALYTICS_LIMIT}.`, EXIT_CODE.USAGE, { code: "invalid_history_analytics_limit" });
|
|
33
|
+
}
|
|
34
|
+
return limit;
|
|
35
|
+
}
|
|
36
|
+
function parseMinimumSample(value) {
|
|
37
|
+
const minimum = value ?? 5;
|
|
38
|
+
if (!Number.isSafeInteger(minimum) || minimum < 1 || minimum > 10_000) {
|
|
39
|
+
throw new PmCliError("History analytics minimum sample must be an integer from 1 to 10000.", EXIT_CODE.USAGE, { code: "invalid_history_analytics_minimum_sample" });
|
|
40
|
+
}
|
|
41
|
+
return minimum;
|
|
42
|
+
}
|
|
43
|
+
function resolveHistoryAnalyticsSince(value) {
|
|
44
|
+
const raw = value?.trim();
|
|
45
|
+
if (!raw) {
|
|
46
|
+
return new Date(Date.now() - DEFAULT_HISTORY_WINDOW_DAYS * 86_400_000).toISOString();
|
|
47
|
+
}
|
|
48
|
+
const relative = /^-(\d+)([dh])$/u.exec(raw);
|
|
49
|
+
if (relative) {
|
|
50
|
+
const amount = Number(relative[1]);
|
|
51
|
+
const multiplier = relative[2] === "d" ? 86_400_000 : 3_600_000;
|
|
52
|
+
if (!Number.isSafeInteger(amount) || amount < 1) {
|
|
53
|
+
throw new PmCliError("History analytics --since duration must be positive.", EXIT_CODE.USAGE, {
|
|
54
|
+
code: "invalid_history_analytics_since",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return new Date(Date.now() - amount * multiplier).toISOString();
|
|
58
|
+
}
|
|
59
|
+
const milliseconds = Date.parse(raw);
|
|
60
|
+
if (!Number.isFinite(milliseconds)) {
|
|
61
|
+
throw new PmCliError("History analytics --since must be an ISO timestamp or negative duration such as -30d.", EXIT_CODE.USAGE, { code: "invalid_history_analytics_since" });
|
|
62
|
+
}
|
|
63
|
+
return new Date(milliseconds).toISOString();
|
|
64
|
+
}
|
|
65
|
+
/** Read one reusable bounded immutable-history window. */
|
|
66
|
+
export async function readHistoryAnalyticsWindow(pmRoot, options) {
|
|
67
|
+
const eventLimit = parseHistoryAnalyticsLimit(options.eventLimit);
|
|
68
|
+
const since = resolveHistoryAnalyticsSince(options.since);
|
|
69
|
+
const events = [];
|
|
70
|
+
let cursor = since;
|
|
71
|
+
let hasMore = false;
|
|
72
|
+
while (events.length < eventLimit) {
|
|
73
|
+
const page = await listMutationEvents({
|
|
74
|
+
pmRoot,
|
|
75
|
+
since: cursor,
|
|
76
|
+
limit: Math.min(HISTORY_EVENT_PAGE_LIMIT, eventLimit - events.length),
|
|
77
|
+
full: true,
|
|
78
|
+
});
|
|
79
|
+
const pageEvents = page.events.map((event) => ({
|
|
80
|
+
item_id: event.item_id,
|
|
81
|
+
entry: event.entry,
|
|
82
|
+
}));
|
|
83
|
+
events.push(...pageEvents);
|
|
84
|
+
hasMore = page.has_more;
|
|
85
|
+
cursor = page.next_cursor;
|
|
86
|
+
if (!page.has_more)
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
events,
|
|
91
|
+
receipt: {
|
|
92
|
+
since,
|
|
93
|
+
events: events.length,
|
|
94
|
+
truncated: hasMore,
|
|
95
|
+
...(hasMore ? { next_cursor: cursor } : {}),
|
|
96
|
+
source: "history_event_index",
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function provenanceValue(entry, dimension) {
|
|
101
|
+
if (dimension === "harness")
|
|
102
|
+
return entry.agent_harness;
|
|
103
|
+
if (dimension === "author_source")
|
|
104
|
+
return entry.author_source;
|
|
105
|
+
return entry.agent_model ?? entry.agent_provenance?.model?.value;
|
|
106
|
+
}
|
|
107
|
+
function statusFromEntry(entry) {
|
|
108
|
+
for (let index = entry.patch.length - 1; index >= 0; index -= 1) {
|
|
109
|
+
const operation = entry.patch[index];
|
|
110
|
+
if (operation.path === "/metadata/status" &&
|
|
111
|
+
"value" in operation &&
|
|
112
|
+
typeof operation.value === "string") {
|
|
113
|
+
return operation.value;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
function annotationOperation(op) {
|
|
119
|
+
return ANNOTATION_OPERATION_PREFIXES.some((prefix) => op.startsWith(prefix));
|
|
120
|
+
}
|
|
121
|
+
function bucketFor(buckets, value) {
|
|
122
|
+
const existing = buckets.get(value);
|
|
123
|
+
if (existing)
|
|
124
|
+
return existing;
|
|
125
|
+
const created = {
|
|
126
|
+
events: 0,
|
|
127
|
+
stateEvents: 0,
|
|
128
|
+
annotationEvents: 0,
|
|
129
|
+
closes: 0,
|
|
130
|
+
reopens: 0,
|
|
131
|
+
defectEscapes: 0,
|
|
132
|
+
};
|
|
133
|
+
buckets.set(value, created);
|
|
134
|
+
return created;
|
|
135
|
+
}
|
|
136
|
+
function accumulateFleetEvents(dimension, events, terminalStatuses) {
|
|
137
|
+
const buckets = new Map();
|
|
138
|
+
const streamTerminal = new Map();
|
|
139
|
+
const lastCloseValue = new Map();
|
|
140
|
+
for (const event of events) {
|
|
141
|
+
const value = provenanceValue(event.entry, dimension);
|
|
142
|
+
const status = statusFromEntry(event.entry);
|
|
143
|
+
const wasTerminal = streamTerminal.get(event.item_id) === true;
|
|
144
|
+
const isTerminal = status === undefined ? wasTerminal : terminalStatuses.has(status);
|
|
145
|
+
if (status !== undefined)
|
|
146
|
+
streamTerminal.set(event.item_id, isTerminal);
|
|
147
|
+
if (!value)
|
|
148
|
+
continue;
|
|
149
|
+
const bucket = bucketFor(buckets, value);
|
|
150
|
+
bucket.events += 1;
|
|
151
|
+
if (annotationOperation(event.entry.op))
|
|
152
|
+
bucket.annotationEvents += 1;
|
|
153
|
+
else
|
|
154
|
+
bucket.stateEvents += 1;
|
|
155
|
+
if (status !== undefined && !wasTerminal && isTerminal) {
|
|
156
|
+
bucket.closes += 1;
|
|
157
|
+
lastCloseValue.set(event.item_id, value);
|
|
158
|
+
}
|
|
159
|
+
else if (status !== undefined && wasTerminal && !isTerminal) {
|
|
160
|
+
bucket.reopens += 1;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return { buckets, lastCloseValue };
|
|
164
|
+
}
|
|
165
|
+
function attributeDefectEscapes(buckets, lastCloseValue, items) {
|
|
166
|
+
for (const item of items) {
|
|
167
|
+
if (item.type !== "Issue")
|
|
168
|
+
continue;
|
|
169
|
+
const sources = new Set((item.dependencies ?? [])
|
|
170
|
+
.filter((dependency) => dependency.kind === "discovered_from")
|
|
171
|
+
.map((dependency) => dependency.id));
|
|
172
|
+
for (const source of sources) {
|
|
173
|
+
const value = lastCloseValue.get(source);
|
|
174
|
+
if (value)
|
|
175
|
+
bucketFor(buckets, value).defectEscapes += 1;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function fleetRow(value, bucket, minimumSample, windowDays) {
|
|
180
|
+
const sampleStatus = bucket.closes >= minimumSample ? "available" : "insufficient";
|
|
181
|
+
return {
|
|
182
|
+
value,
|
|
183
|
+
events: bucket.events,
|
|
184
|
+
state_events: bucket.stateEvents,
|
|
185
|
+
annotation_events: bucket.annotationEvents,
|
|
186
|
+
closes: bucket.closes,
|
|
187
|
+
reopens: bucket.reopens,
|
|
188
|
+
defect_escapes: bucket.defectEscapes,
|
|
189
|
+
throughput_per_day: sampleStatus === "available" ? bucket.closes / windowDays : null,
|
|
190
|
+
rework_rate: sampleStatus === "available" ? bucket.reopens / bucket.closes : null,
|
|
191
|
+
defect_escape_rate: sampleStatus === "available"
|
|
192
|
+
? bucket.defectEscapes / bucket.closes
|
|
193
|
+
: null,
|
|
194
|
+
sample_status: sampleStatus,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
function buildFleetDimension(dimension, events, items, terminalStatuses, minimumSample, windowDays) {
|
|
198
|
+
const { buckets, lastCloseValue } = accumulateFleetEvents(dimension, events, terminalStatuses);
|
|
199
|
+
attributeDefectEscapes(buckets, lastCloseValue, items);
|
|
200
|
+
return {
|
|
201
|
+
dimension,
|
|
202
|
+
status: buckets.size === 0 ? "unavailable" : "available",
|
|
203
|
+
rows: [...buckets]
|
|
204
|
+
.map(([value, bucket]) => fleetRow(value, bucket, minimumSample, windowDays))
|
|
205
|
+
.sort((left, right) => right.events - left.events || left.value.localeCompare(right.value)),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function resolveHistoryWindowDays(events, since) {
|
|
209
|
+
const firstTimestamp = events[0]?.entry.ts ?? since;
|
|
210
|
+
const lastTimestamp = events[events.length - 1]?.entry.ts ?? firstTimestamp;
|
|
211
|
+
const firstMilliseconds = Date.parse(firstTimestamp);
|
|
212
|
+
const lastMilliseconds = Date.parse(lastTimestamp);
|
|
213
|
+
if (!Number.isFinite(firstMilliseconds) ||
|
|
214
|
+
!Number.isFinite(lastMilliseconds)) {
|
|
215
|
+
return 1;
|
|
216
|
+
}
|
|
217
|
+
return Math.max(1, (lastMilliseconds - firstMilliseconds) / 86_400_000);
|
|
218
|
+
}
|
|
219
|
+
/** Evaluate a negative-control-friendly declared-versus-observed coverage gate. */
|
|
220
|
+
export function evaluateProvenanceCoverage(entries, descriptors, minimumSample) {
|
|
221
|
+
const descriptorCoverage = analyzeAgentProvenanceDescriptorCoverage(descriptors);
|
|
222
|
+
const observations = summarizeAgentProvenance(entries, AGENT_PROVENANCE_DIMENSIONS, minimumSample);
|
|
223
|
+
const inert = observations
|
|
224
|
+
.filter((row) => row.inert)
|
|
225
|
+
.map((row) => ({
|
|
226
|
+
harness: row.harness,
|
|
227
|
+
dimension: row.dimension,
|
|
228
|
+
explicit_samples: row.observed + row.unavailable,
|
|
229
|
+
}));
|
|
230
|
+
const undeclared = descriptorCoverage
|
|
231
|
+
.filter((row) => !row.covered)
|
|
232
|
+
.map((row) => row.dimension);
|
|
233
|
+
return {
|
|
234
|
+
descriptors: descriptorCoverage,
|
|
235
|
+
observations,
|
|
236
|
+
inert,
|
|
237
|
+
undeclared,
|
|
238
|
+
warnings: [
|
|
239
|
+
...inert.map((row) => `provenance_dimension_inert:${row.harness}:${row.dimension}:${String(row.explicit_samples)}`),
|
|
240
|
+
...undeclared.map((dimension) => `provenance_dimension_undeclared:${dimension}`),
|
|
241
|
+
],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/** Read live, bounded provenance coverage from authoritative history. */
|
|
245
|
+
export async function runProvenanceCoverageAnalytics(pmRoot, descriptors = BUILTIN_HARNESS_SIGNAL_DESCRIPTORS, options = {}) {
|
|
246
|
+
return projectProvenanceCoverageAnalytics(await readHistoryAnalyticsWindow(pmRoot, options), descriptors, options);
|
|
247
|
+
}
|
|
248
|
+
/** Project provenance coverage from an already-read immutable-history window. */
|
|
249
|
+
export function projectProvenanceCoverageAnalytics(window, descriptors = BUILTIN_HARNESS_SIGNAL_DESCRIPTORS, options = {}) {
|
|
250
|
+
const minimumSample = parseMinimumSample(options.minimumSample);
|
|
251
|
+
return {
|
|
252
|
+
...evaluateProvenanceCoverage(window.events.map((event) => event.entry), descriptors, minimumSample),
|
|
253
|
+
window: window.receipt,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/** Derive bounded fleet rates grouped by harness, model, and author source. */
|
|
257
|
+
export async function runFleetAttributionAnalytics(pmRoot, items, terminalStatuses, options = {}) {
|
|
258
|
+
return projectFleetAttributionAnalytics(await readHistoryAnalyticsWindow(pmRoot, options), items, terminalStatuses, options);
|
|
259
|
+
}
|
|
260
|
+
/** Project fleet attribution from an already-read immutable-history window. */
|
|
261
|
+
export function projectFleetAttributionAnalytics(window, items, terminalStatuses, options = {}) {
|
|
262
|
+
const minimumSample = parseMinimumSample(options.minimumSample);
|
|
263
|
+
const windowDays = resolveHistoryWindowDays(window.events, window.receipt.since);
|
|
264
|
+
return {
|
|
265
|
+
dimensions: ["harness", "model", "author_source"].map((dimension) => buildFleetDimension(dimension, window.events, items, terminalStatuses, minimumSample, windowDays)),
|
|
266
|
+
minimum_sample: minimumSample,
|
|
267
|
+
policy: "observational_only_not_for_authorization_or_routing",
|
|
268
|
+
window: window.receipt,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/** Pure seams for deterministic analytics and negative-control tests. */
|
|
272
|
+
export const _testOnlyHistoryAnalytics = {
|
|
273
|
+
annotationOperation,
|
|
274
|
+
buildFleetDimension,
|
|
275
|
+
parseHistoryAnalyticsLimit,
|
|
276
|
+
parseMinimumSample,
|
|
277
|
+
provenanceValue,
|
|
278
|
+
resolveHistoryAnalyticsSince,
|
|
279
|
+
resolveHistoryWindowDays,
|
|
280
|
+
statusFromEntry,
|
|
281
|
+
};
|
|
282
|
+
//# sourceMappingURL=history-analytics.js.map
|
|
283
|
+
//# debugId=f0e89b0b-ccd1-5dbb-afad-119d5a98590a
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/improvement-ledger-validation
|
|
3
|
+
*
|
|
4
|
+
* Validates the persisted improvement-ledger envelope and observations at the
|
|
5
|
+
* storage boundary so malformed workspace state never reaches analytics.
|
|
6
|
+
*/
|
|
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]="939d5f93-d287-5c1c-bc78-d013f76735f2")}catch(e){}}();
|
|
9
|
+
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
10
|
+
import { PmCliError } from "../core/shared/errors.js";
|
|
11
|
+
const IMPROVEMENT_LEDGER_FORMAT_VERSION = 1;
|
|
12
|
+
function isValidLedgerObservation(observation) {
|
|
13
|
+
if (typeof observation !== "object" || observation === null)
|
|
14
|
+
return false;
|
|
15
|
+
const candidate = observation;
|
|
16
|
+
const hasRequiredFields = typeof candidate.id === "string" &&
|
|
17
|
+
typeof candidate.metric === "string" &&
|
|
18
|
+
typeof candidate.value === "number" &&
|
|
19
|
+
Number.isFinite(candidate.value) &&
|
|
20
|
+
["higher", "lower", "target"].includes(String(candidate.direction)) &&
|
|
21
|
+
typeof candidate.observed_at === "string" &&
|
|
22
|
+
typeof candidate.revision === "string" &&
|
|
23
|
+
["caller", "git", "unversioned"].includes(String(candidate.revision_source)) &&
|
|
24
|
+
typeof candidate.author === "string";
|
|
25
|
+
if (!hasRequiredFields)
|
|
26
|
+
return false;
|
|
27
|
+
return (candidate.direction !== "target" ||
|
|
28
|
+
(typeof candidate.threshold === "number" &&
|
|
29
|
+
Number.isFinite(candidate.threshold)));
|
|
30
|
+
}
|
|
31
|
+
/** Parse and validate a serialized improvement-ledger singleton. */
|
|
32
|
+
export function parseImprovementLedgerDocument(raw) {
|
|
33
|
+
if (raw === null) {
|
|
34
|
+
return {
|
|
35
|
+
format_version: IMPROVEMENT_LEDGER_FORMAT_VERSION,
|
|
36
|
+
observations: [],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
let parsed;
|
|
40
|
+
try {
|
|
41
|
+
parsed = JSON.parse(raw);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new PmCliError("Improvement ledger contains invalid JSON.", EXIT_CODE.GENERIC_FAILURE, { code: "invalid_improvement_ledger" });
|
|
45
|
+
}
|
|
46
|
+
if (typeof parsed !== "object" ||
|
|
47
|
+
parsed === null ||
|
|
48
|
+
Array.isArray(parsed) ||
|
|
49
|
+
parsed.format_version !==
|
|
50
|
+
IMPROVEMENT_LEDGER_FORMAT_VERSION ||
|
|
51
|
+
!Array.isArray(parsed.observations)) {
|
|
52
|
+
throw new PmCliError("Improvement ledger has an unsupported shape or format version.", EXIT_CODE.GENERIC_FAILURE, { code: "invalid_improvement_ledger" });
|
|
53
|
+
}
|
|
54
|
+
const observations = parsed.observations;
|
|
55
|
+
for (const observation of observations) {
|
|
56
|
+
if (!isValidLedgerObservation(observation)) {
|
|
57
|
+
throw new PmCliError("Improvement ledger contains an invalid observation.", EXIT_CODE.GENERIC_FAILURE, { code: "invalid_improvement_ledger" });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return parsed;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=improvement-ledger-validation.js.map
|
|
63
|
+
//# debugId=939d5f93-d287-5c1c-bc78-d013f76735f2
|