@unbrained/pm-cli 2026.9.1 → 2026.9.3
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 +27 -0
- package/dist/cli/after-command-context-usage.js +16 -3
- package/dist/cli-bundle/bundle-manifest.json +153 -153
- package/dist/cli-bundle/chunks/{chunk-6XIIGE7U.js → chunk-34HASX3S.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-AY324UJ5.js +9 -0
- package/dist/cli-bundle/chunks/{chunk-TAG4VC22.js → chunk-DKGP3QLE.js} +27 -27
- package/dist/cli-bundle/chunks/chunk-E5RBBCXO.js +230 -0
- package/dist/cli-bundle/chunks/{chunk-DTGWEL23.js → chunk-EDPIS7EB.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-X4RCGLTX.js → chunk-IEHHE6GA.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-U45JXJCC.js → chunk-L7B7343B.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-2MC2LCXZ.js → chunk-LENC656S.js} +41 -41
- package/dist/cli-bundle/chunks/chunk-LISESA7W.js +35 -0
- package/dist/cli-bundle/chunks/{chunk-3WICXLVT.js → chunk-UPPM2FOZ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-Y7VOMSZT.js → chunk-Y4PJ6HPK.js} +2 -2
- package/dist/cli-bundle/chunks/{register-list-query-XYNX4ASQ.js → register-list-query-W2ZTOMKP.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-2MVLRS3J.js → register-mutation-RVND5NCG.js} +2 -2
- package/dist/cli-bundle/chunks/{register-operations-WCIDXBU3.js → register-operations-TTROIVC4.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-KVNC5KPL.js → register-setup-D3ZFHY3L.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-3ZBI35HU.js +176 -0
- package/dist/cli-bundle/focused-chunks/{chunk-SVXJYD6G.js → chunk-4HJFY4MB.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-4RRHC3S4.js +6 -0
- package/dist/cli-bundle/focused-chunks/chunk-4WR46RMG.js +9 -0
- package/dist/cli-bundle/focused-chunks/chunk-5RFXUPN5.js +3 -0
- package/dist/cli-bundle/focused-chunks/chunk-BWKHEIVF.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-4O4CJAR6.js → chunk-D7KXFBXV.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-MKHG3T76.js → chunk-GHCZ3YFR.js} +3 -3
- package/dist/cli-bundle/focused-chunks/{chunk-KB5OFSFD.js → chunk-GT7MXDLW.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-KBLZRU62.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-KZ2NB3ET.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-M5M6SVHS.js +3 -0
- package/dist/cli-bundle/focused-chunks/{chunk-BEVHCEWG.js → chunk-OL5EH6I3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-MEASX544.js → chunk-Q45NHPF2.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-Y6JJIX6I.js → chunk-QKHCSUGJ.js} +48 -48
- package/dist/cli-bundle/focused-chunks/chunk-S27XMBIN.js +8 -0
- package/dist/cli-bundle/focused-chunks/chunk-TXE4TSHM.js +12 -0
- package/dist/cli-bundle/focused-chunks/chunk-UCLO3XDU.js +2 -0
- package/dist/cli-bundle/main.js +15 -15
- 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 +28 -28
- 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 +35 -33
- 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 +9 -9
- package/dist/core/diagnostics/remediation.js +9 -4
- package/dist/core/history/event-classification.d.ts +21 -0
- package/dist/core/history/event-classification.js +109 -0
- package/dist/core/history/event-index.d.ts +14 -3
- package/dist/core/history/event-index.js +543 -88
- package/dist/core/history/history.js +47 -18
- package/dist/core/history/workspace-history.js +7 -6
- package/dist/core/lock/lock.d.ts +22 -2
- package/dist/core/lock/lock.js +121 -19
- package/dist/core/output/output.js +31 -7
- package/dist/core/shared/time.d.ts +2 -0
- package/dist/core/shared/time.js +8 -2
- package/dist/core/store/item-metadata-query-index.js +5 -5
- package/dist/sdk/context/recency.d.ts +9 -0
- package/dist/sdk/context/recency.js +34 -0
- package/dist/sdk/context/usage-egress.d.ts +9 -0
- package/dist/sdk/context/usage-egress.js +30 -0
- package/dist/sdk/context-intent-contracts.js +7 -3
- package/dist/sdk/context-relevance.d.ts +23 -0
- package/dist/sdk/context-relevance.js +94 -23
- package/dist/sdk/context-signal-store.d.ts +7 -3
- package/dist/sdk/context-signal-store.js +155 -42
- package/dist/sdk/context-usage.d.ts +54 -0
- package/dist/sdk/context-usage.js +245 -16
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +26 -14
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +14 -2
- package/dist/sdk/governance/health.js +77 -11
- package/dist/sdk/governance/validate.js +4 -2
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.js +4 -2
- package/dist/sdk/init.d.ts +2 -0
- package/dist/sdk/init.js +18 -9
- package/dist/sdk/merge/index.d.ts +1 -1
- package/dist/sdk/merge/index.js +2 -2
- package/dist/sdk/merge/receipts.d.ts +24 -0
- package/dist/sdk/merge/receipts.js +122 -30
- package/dist/sdk/query/context.d.ts +3 -1
- package/dist/sdk/query/context.js +21 -9
- package/dist/sdk/query/next.js +18 -9
- package/dist/sdk/runtime-input.d.ts +2 -0
- package/dist/sdk/runtime-input.js +25 -2
- package/dist/sdk/runtime.d.ts +1 -0
- package/dist/sdk/runtime.js +17 -26
- package/dist/types.d.ts +2 -0
- package/dist/types.js +2 -2
- package/docs/CONTEXT_RECOVERY_PRIMITIVES.md +11 -2
- package/docs/CONTEXT_RELEVANCE.md +44 -1
- package/docs/MERGE_SAFETY.md +16 -2
- package/docs/PERFORMANCE.md +6 -3
- package/docs/READ_OUTPUT_CONTRACTS.md +9 -1
- package/docs/SDK.md +11 -8
- package/docs/SDK_CONTEXT.md +7 -0
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +5 -3
- package/marketplace.json +2 -2
- package/package.json +4 -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 +268 -28
- package/dist/cli-bundle/chunks/chunk-ALKKAUFN.js +0 -35
- package/dist/cli-bundle/chunks/chunk-GOACULJW.js +0 -13
- package/dist/cli-bundle/chunks/chunk-NOPL37X4.js +0 -205
- package/dist/cli-bundle/focused-chunks/chunk-2FEZ5SKM.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-6GCRSLPG.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-7VATS5QY.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-FWPLDEXF.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-JEFKLWMM.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-PF3E6Q36.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-QDFJIRKN.js +0 -4
- package/dist/cli-bundle/focused-chunks/chunk-RMRCQPWU.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-S4U5CN5Q.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-T2LXXSOD.js +0 -158
- package/dist/cli-bundle/focused-chunks/chunk-Z2USIBR2.js +0 -5
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Maintains a rebuildable SQLite projection for bounded metadata queries.
|
|
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]="97cfeab2-8e3f-5b70-9f64-10494158d141")}catch(e){}}();
|
|
8
8
|
import fs from "node:fs/promises";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
@@ -185,13 +185,13 @@ function readIndexMetadata(database) {
|
|
|
185
185
|
* callers can remove and lazily rebuild this optional projection.
|
|
186
186
|
*/
|
|
187
187
|
export async function updateItemMetadataQueryIndex(options) {
|
|
188
|
+
const Database = resolveDatabaseSync();
|
|
189
|
+
if (!Database)
|
|
190
|
+
return false;
|
|
188
191
|
const indexPath = queryIndexPath(options.pmRoot);
|
|
189
192
|
let database;
|
|
190
193
|
try {
|
|
191
194
|
await fs.access(indexPath);
|
|
192
|
-
const Database = resolveDatabaseSync();
|
|
193
|
-
if (!Database)
|
|
194
|
-
return false;
|
|
195
195
|
database = new Database(indexPath);
|
|
196
196
|
database.exec("PRAGMA foreign_keys = ON");
|
|
197
197
|
const metadata = readIndexMetadata(database);
|
|
@@ -470,4 +470,4 @@ export const _testOnly = {
|
|
|
470
470
|
},
|
|
471
471
|
};
|
|
472
472
|
//# sourceMappingURL=item-metadata-query-index.js.map
|
|
473
|
-
//# debugId=
|
|
473
|
+
//# debugId=97cfeab2-8e3f-5b70-9f64-10494158d141
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Deterministic oldest coordinate used when legacy creation metadata is invalid. */
|
|
2
|
+
export declare const CONTEXT_RECENCY_EPOCH = "1970-01-01T00:00:00.000Z";
|
|
3
|
+
/**
|
|
4
|
+
* Canonicalize a calendar-valid RFC 3339 instant or dashed legacy date-only
|
|
5
|
+
* value. Compact dates, sub-millisecond instants, and host-local date-times are
|
|
6
|
+
* rejected because they cannot round-trip through the strict timestamp contract
|
|
7
|
+
* losslessly and deterministically.
|
|
8
|
+
*/
|
|
9
|
+
export declare function canonicalizeContextRecencyCoordinate(value: unknown): string | null;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/context/recency
|
|
3
|
+
*
|
|
4
|
+
* Canonicalizes the absolute timestamps used as durable context-recency
|
|
5
|
+
* coordinates without accepting relative or host-local date-time values.
|
|
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]="377499d7-13b3-55f0-9d44-425bfcaf7964")}catch(e){}}();
|
|
9
|
+
import { isMillisecondPrecisionRfc3339DateTime, resolveIsoOrRelative, } from "../../core/shared/time.js";
|
|
10
|
+
/** Deterministic oldest coordinate used when legacy creation metadata is invalid. */
|
|
11
|
+
export const CONTEXT_RECENCY_EPOCH = "1970-01-01T00:00:00.000Z";
|
|
12
|
+
/**
|
|
13
|
+
* Canonicalize a calendar-valid RFC 3339 instant or dashed legacy date-only
|
|
14
|
+
* value. Compact dates, sub-millisecond instants, and host-local date-times are
|
|
15
|
+
* rejected because they cannot round-trip through the strict timestamp contract
|
|
16
|
+
* losslessly and deterministically.
|
|
17
|
+
*/
|
|
18
|
+
export function canonicalizeContextRecencyCoordinate(value) {
|
|
19
|
+
if (typeof value !== "string")
|
|
20
|
+
return null;
|
|
21
|
+
const trimmed = value.trim();
|
|
22
|
+
if (!isMillisecondPrecisionRfc3339DateTime(trimmed) &&
|
|
23
|
+
!/^\d{4}-\d{2}-\d{2}$/u.test(trimmed)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
return resolveIsoOrRelative(trimmed, new Date(Number.NaN), "context signal recency coordinate");
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=recency.js.map
|
|
34
|
+
//# debugId=377499d7-13b3-55f0-9d44-425bfcaf7964
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/context/usage-egress
|
|
3
|
+
*
|
|
4
|
+
* Keeps post-projection context feedback best-effort without weakening the
|
|
5
|
+
* response contract returned by embedded SDK and MCP hosts.
|
|
6
|
+
*/
|
|
7
|
+
import { finalizeContextUsageDelivery } from "../context-usage.js";
|
|
8
|
+
/** Finalize derived usage feedback and attach a stable warning on failure. */
|
|
9
|
+
export declare function finalizeContextUsageEgress(pmRoot: string, projected: unknown, finalize?: typeof finalizeContextUsageDelivery): Promise<void>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/context/usage-egress
|
|
3
|
+
*
|
|
4
|
+
* Keeps post-projection context feedback best-effort without weakening the
|
|
5
|
+
* response contract returned by embedded SDK and MCP hosts.
|
|
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]="c5a14f99-ce5b-5da7-8b17-6b6a56f0644a")}catch(e){}}();
|
|
9
|
+
import { finalizeContextUsageDelivery } from "../context-usage.js";
|
|
10
|
+
/** Finalize derived usage feedback and attach a stable warning on failure. */
|
|
11
|
+
export async function finalizeContextUsageEgress(pmRoot, projected, finalize = finalizeContextUsageDelivery) {
|
|
12
|
+
try {
|
|
13
|
+
await finalize({ pmRoot, result: projected });
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
if (typeof projected === "object" &&
|
|
17
|
+
projected !== null &&
|
|
18
|
+
!Array.isArray(projected)) {
|
|
19
|
+
const record = projected;
|
|
20
|
+
const warnings = Array.isArray(record.warnings)
|
|
21
|
+
? record.warnings.filter((warning) => typeof warning === "string")
|
|
22
|
+
: [];
|
|
23
|
+
record.warnings = [
|
|
24
|
+
...new Set([...warnings, "context_usage_feedback_write_failed"]),
|
|
25
|
+
].sort();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=usage-egress.js.map
|
|
30
|
+
//# debugId=c5a14f99-ce5b-5da7-8b17-6b6a56f0644a
|
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
* workspace configuration, and packages.
|
|
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]="5dc9c6e4-6db8-560f-a87f-368132e2ffb3")}catch(e){}}();
|
|
9
9
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
10
10
|
import { renderPmCommand } from "./command-line.js";
|
|
11
11
|
import { attachOutputOmissionReceipt } from "./output-projection.js";
|
|
12
12
|
import { encodeQueryCursor } from "./pagination.js";
|
|
13
13
|
import { applyReadOutputDimensions, stabilizeReadOutputReceiptEstimates, } from "./read-output-contracts.js";
|
|
14
|
+
import { propagateContextUsageServingReceipt } from "./context-usage.js";
|
|
14
15
|
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
15
16
|
import { PmCliError } from "../core/shared/errors.js";
|
|
16
17
|
/** Built-in intent projections shared by CLI, SDK, MCP, and package authors. */
|
|
@@ -692,6 +693,7 @@ export function attachReadOutputContracts(command, options, result) {
|
|
|
692
693
|
!Array.isArray(disclosedResult)
|
|
693
694
|
? applyReadOutputDimensions(command ?? "", options, collapseContinuationMetadata(options, attachContextIntentReceipt(command ?? "", options, disclosedResult)))
|
|
694
695
|
: disclosedResult;
|
|
696
|
+
propagateContextUsageServingReceipt(result, projected);
|
|
695
697
|
if (options.outputRowContract === true ||
|
|
696
698
|
options.output_row_contract === true ||
|
|
697
699
|
typeof projected !== "object" ||
|
|
@@ -700,7 +702,9 @@ export function attachReadOutputContracts(command, options, result) {
|
|
|
700
702
|
!Object.hasOwn(projected, "row_contract")) {
|
|
701
703
|
return projected;
|
|
702
704
|
}
|
|
703
|
-
|
|
705
|
+
const suppressed = stabilizeSuppressedRowContractReceipts(Object.fromEntries(Object.entries(projected).filter(([key]) => key !== "row_contract")), options);
|
|
706
|
+
propagateContextUsageServingReceipt(projected, suppressed);
|
|
707
|
+
return suppressed;
|
|
704
708
|
}
|
|
705
709
|
//# sourceMappingURL=context-intent-contracts.js.map
|
|
706
|
-
//# debugId=
|
|
710
|
+
//# debugId=5dc9c6e4-6db8-560f-a87f-368132e2ffb3
|
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
import type { RuntimeStatusRegistry } from "../core/schema/runtime-schema.js";
|
|
2
2
|
import type { ItemMetadata } from "../types/index.js";
|
|
3
|
+
import type { HistoryEventClass } from "../core/history/event-classification.js";
|
|
3
4
|
/** Canonical signal keys understood by the built-in relevance model. */
|
|
4
5
|
export declare const CONTEXT_RELEVANCE_SIGNAL_NAMES: readonly ["structural", "recency", "activity_density", "graph_proximity", "claim_focus", "priority_pressure", "risk_pressure", "deadline_pressure", "knowledge_density", "author_affinity", "usage_affinity", "semantic_similarity"];
|
|
5
6
|
/** A normalized signal consumed by the built-in context relevance scorer. */
|
|
6
7
|
export type ContextRelevanceSignalName = (typeof CONTEXT_RELEVANCE_SIGNAL_NAMES)[number];
|
|
7
8
|
/** Normalized candidate features; omitted signals are excluded from weighting. */
|
|
8
9
|
export type ContextRelevanceSignals = Partial<Record<Exclude<ContextRelevanceSignalName, "structural">, number>>;
|
|
10
|
+
/** Authoritative coordinate and fallback that produced an item's recency. */
|
|
11
|
+
export interface ContextRecencyEvidence {
|
|
12
|
+
/** Source selected by the canonical fallback ladder. */
|
|
13
|
+
source: "substantive_history" | "release_cohort" | "created_at";
|
|
14
|
+
/** ISO coordinate used for deterministic recency ordering. */
|
|
15
|
+
coordinate: string;
|
|
16
|
+
/** Immutable operation selected from history when source is substantive_history. */
|
|
17
|
+
history_op?: string;
|
|
18
|
+
/** Declared class selected from history when source is substantive_history. */
|
|
19
|
+
event_class?: HistoryEventClass;
|
|
20
|
+
}
|
|
21
|
+
/** Per-signal provenance exposed by explained relevance results. */
|
|
22
|
+
export interface ContextSignalProvenance {
|
|
23
|
+
/** Evidence for the canonical temporal component. */
|
|
24
|
+
recency: ContextRecencyEvidence;
|
|
25
|
+
}
|
|
9
26
|
/** A project-management object and its derived relevance signals. */
|
|
10
27
|
export interface ContextRelevanceCandidate<TItem> {
|
|
11
28
|
/** Stable identifier used to reference this record across commands and storage. */
|
|
@@ -14,11 +31,15 @@ export interface ContextRelevanceCandidate<TItem> {
|
|
|
14
31
|
item: TItem;
|
|
15
32
|
/** Value that configures or reports signals for this contract. */
|
|
16
33
|
signals?: ContextRelevanceSignals;
|
|
34
|
+
/** Authoritative source details for explainable derived signals. */
|
|
35
|
+
signal_provenance?: ContextSignalProvenance;
|
|
17
36
|
}
|
|
18
37
|
/** Item candidate whose built-in metadata derivation always supplies signals. */
|
|
19
38
|
export interface ItemContextRelevanceCandidate extends ContextRelevanceCandidate<ItemMetadata> {
|
|
20
39
|
/** Complete built-in derivation result, with unavailable signals omitted by value. */
|
|
21
40
|
signals: ContextRelevanceSignals;
|
|
41
|
+
/** Built-in recency derivation always discloses its source. */
|
|
42
|
+
signal_provenance: ContextSignalProvenance;
|
|
22
43
|
}
|
|
23
44
|
/** Inputs that make item-signal derivation deterministic and host-configurable. */
|
|
24
45
|
export interface BuildItemContextRelevanceCandidatesOptions {
|
|
@@ -42,6 +63,8 @@ export interface BuildItemContextRelevanceCandidatesOptions {
|
|
|
42
63
|
knowledgeDensity?: Readonly<Record<string, number>>;
|
|
43
64
|
/** Optional history-derived author affinity by item id. */
|
|
44
65
|
authorAffinity?: Readonly<Record<string, number>>;
|
|
66
|
+
/** Latest substantive history evidence keyed by item id. */
|
|
67
|
+
recencyEvidence?: Readonly<Record<string, ContextRecencyEvidence>>;
|
|
45
68
|
}
|
|
46
69
|
/**
|
|
47
70
|
* Derive the canonical metadata signals consumed by `pm context` and `pm next`.
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
* with core, extension, or project-specific feature stores.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
!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]="
|
|
9
|
+
!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]="80a03884-711e-5170-a3c1-f05ccb065702")}catch(e){}}();
|
|
10
10
|
import { runActiveServiceOverride } from "../core/extensions/index.js";
|
|
11
11
|
import { normalizeStatusForRegistry, normalizeStatusInput, } from "../core/item/status.js";
|
|
12
|
-
import { compareTimestampStrings
|
|
12
|
+
import { compareTimestampStrings } from "../core/shared/time.js";
|
|
13
|
+
import { canonicalizeContextRecencyCoordinate, CONTEXT_RECENCY_EPOCH, } from "./context/recency.js";
|
|
13
14
|
/** Canonical signal keys understood by the built-in relevance model. */
|
|
14
15
|
export const CONTEXT_RELEVANCE_SIGNAL_NAMES = [
|
|
15
16
|
"structural",
|
|
@@ -33,12 +34,67 @@ function normalizeContextActor(value, missingValue) {
|
|
|
33
34
|
const normalized = value.trim().toLowerCase();
|
|
34
35
|
return normalized.length > 0 ? normalized : missingValue;
|
|
35
36
|
}
|
|
37
|
+
function releaseCohortCoordinate(value) {
|
|
38
|
+
if (typeof value !== "string")
|
|
39
|
+
return undefined;
|
|
40
|
+
const match = /^v?(\d{4})\.(\d{1,2})\.(\d{1,2})(?:$|[-+])/u.exec(value.trim());
|
|
41
|
+
if (!match)
|
|
42
|
+
return undefined;
|
|
43
|
+
const year = Number(match[1]);
|
|
44
|
+
const month = Number(match[2]);
|
|
45
|
+
const day = Number(match[3]);
|
|
46
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
47
|
+
return date.getUTCFullYear() === year &&
|
|
48
|
+
date.getUTCMonth() === month - 1 &&
|
|
49
|
+
date.getUTCDate() === day
|
|
50
|
+
? date.toISOString()
|
|
51
|
+
: undefined;
|
|
52
|
+
}
|
|
53
|
+
function fallbackRecencyEvidence(item) {
|
|
54
|
+
const releaseCoordinate = releaseCohortCoordinate(item.release);
|
|
55
|
+
if (releaseCoordinate !== undefined) {
|
|
56
|
+
return { source: "release_cohort", coordinate: releaseCoordinate };
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
source: "created_at",
|
|
60
|
+
coordinate: canonicalizeContextRecencyCoordinate(item.created_at) ??
|
|
61
|
+
CONTEXT_RECENCY_EPOCH,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function canonicalizeRecencyEvidence(evidence) {
|
|
65
|
+
if (!["substantive_history", "release_cohort", "created_at"].includes(evidence.source) ||
|
|
66
|
+
(evidence.source === "substantive_history"
|
|
67
|
+
? (evidence.history_op !== undefined &&
|
|
68
|
+
typeof evidence.history_op !== "string") ||
|
|
69
|
+
(evidence.event_class !== undefined &&
|
|
70
|
+
evidence.event_class !== "substantive")
|
|
71
|
+
: evidence.history_op !== undefined || evidence.event_class !== undefined)) {
|
|
72
|
+
throw new TypeError("Context signal recency provenance must match its source");
|
|
73
|
+
}
|
|
74
|
+
const coordinate = canonicalizeContextRecencyCoordinate(evidence.coordinate);
|
|
75
|
+
if (coordinate === null) {
|
|
76
|
+
throw new TypeError("Context signal recency coordinate must be a valid absolute timestamp with millisecond precision");
|
|
77
|
+
}
|
|
78
|
+
return { ...evidence, coordinate };
|
|
79
|
+
}
|
|
36
80
|
function normalizedPressure(value, maximum) {
|
|
37
|
-
const parsed = typeof value === "number"
|
|
38
|
-
|
|
81
|
+
const parsed = typeof value === "number"
|
|
82
|
+
? value
|
|
83
|
+
: typeof value === "string"
|
|
84
|
+
? Number.parseFloat(value)
|
|
85
|
+
: Number.NaN;
|
|
86
|
+
return Number.isFinite(parsed)
|
|
87
|
+
? 1 - Math.min(Math.max(parsed, 0), maximum) / maximum
|
|
88
|
+
: 0;
|
|
39
89
|
}
|
|
40
90
|
function deadlinePressure(deadline, nowMs) {
|
|
41
|
-
const deadlineMs = typeof deadline === "string"
|
|
91
|
+
const deadlineMs = typeof deadline === "string"
|
|
92
|
+
? Date.parse(deadline)
|
|
93
|
+
: deadline instanceof Date
|
|
94
|
+
? deadline.getTime()
|
|
95
|
+
: typeof deadline === "number"
|
|
96
|
+
? deadline
|
|
97
|
+
: Number.NaN;
|
|
42
98
|
if (!Number.isFinite(deadlineMs) || !Number.isFinite(nowMs))
|
|
43
99
|
return 0;
|
|
44
100
|
const days = (deadlineMs - nowMs) / 86_400_000;
|
|
@@ -61,20 +117,22 @@ function derivedSignalOrFallback(values, id, fallback) {
|
|
|
61
117
|
* to reproduce built-in ranking without private imports or subprocesses.
|
|
62
118
|
*/
|
|
63
119
|
export function buildItemContextRelevanceCandidates(items, options) {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
};
|
|
120
|
+
const recencyEvidence = new Map(items.map((item) => {
|
|
121
|
+
const suppliedEvidence = options.recencyEvidence?.[item.id];
|
|
122
|
+
return [
|
|
123
|
+
item.id,
|
|
124
|
+
suppliedEvidence === undefined
|
|
125
|
+
? fallbackRecencyEvidence(item)
|
|
126
|
+
: canonicalizeRecencyEvidence(suppliedEvidence),
|
|
127
|
+
];
|
|
128
|
+
}));
|
|
74
129
|
const recencyOrder = [...items].sort((left, right) => {
|
|
75
|
-
const leftTime =
|
|
76
|
-
|
|
77
|
-
|
|
130
|
+
const leftTime = recencyEvidence.get(left.id)
|
|
131
|
+
.coordinate;
|
|
132
|
+
const rightTime = recencyEvidence.get(right.id)
|
|
133
|
+
.coordinate;
|
|
134
|
+
return (compareTimestampStrings(rightTime, leftTime) ||
|
|
135
|
+
left.id.localeCompare(right.id));
|
|
78
136
|
});
|
|
79
137
|
const recencyRank = new Map(recencyOrder.map((item, index) => [item.id, index]));
|
|
80
138
|
const denominator = Math.max(items.length - 1, 1);
|
|
@@ -82,16 +140,29 @@ export function buildItemContextRelevanceCandidates(items, options) {
|
|
|
82
140
|
const inProgressStatus = normalizeStatusInput("in_progress", options.statusRegistry);
|
|
83
141
|
const nowMs = Date.parse(options.now);
|
|
84
142
|
return items.map((item) => {
|
|
85
|
-
const assigned = normalizeContextActor(item.assignee, NO_ITEM_ASSIGNEE) ===
|
|
86
|
-
|
|
143
|
+
const assigned = normalizeContextActor(item.assignee, NO_ITEM_ASSIGNEE) ===
|
|
144
|
+
normalizedAuthor;
|
|
145
|
+
const knowledgeEntries = (item.comments?.length ?? 0) +
|
|
146
|
+
(item.notes?.length ?? 0) +
|
|
147
|
+
(item.learnings?.length ?? 0);
|
|
87
148
|
return {
|
|
88
149
|
id: item.id,
|
|
89
150
|
item,
|
|
151
|
+
signal_provenance: {
|
|
152
|
+
recency: recencyEvidence.get(item.id),
|
|
153
|
+
},
|
|
90
154
|
signals: {
|
|
91
|
-
recency: items.length === 1
|
|
155
|
+
recency: items.length === 1
|
|
156
|
+
? 1
|
|
157
|
+
: 1 - recencyRank.get(item.id) / denominator,
|
|
92
158
|
activity_density: options.activityDensity?.[item.id],
|
|
93
159
|
graph_proximity: derivedSignalOrFallback(options.graphProximity, item.id, item.parent ? 0.3 : 0),
|
|
94
|
-
claim_focus: derivedSignalOrFallback(options.claimFocus, item.id, normalizeStatusForRegistry(item.status, options.statusRegistry) ===
|
|
160
|
+
claim_focus: derivedSignalOrFallback(options.claimFocus, item.id, normalizeStatusForRegistry(item.status, options.statusRegistry) ===
|
|
161
|
+
inProgressStatus
|
|
162
|
+
? 1
|
|
163
|
+
: assigned
|
|
164
|
+
? 0.75
|
|
165
|
+
: 0),
|
|
95
166
|
priority_pressure: normalizedPressure(item.priority, 4),
|
|
96
167
|
risk_pressure: riskPressure(item.risk),
|
|
97
168
|
deadline_pressure: deadlinePressure(item.deadline, nowMs),
|
|
@@ -430,4 +501,4 @@ export async function runContextEvaluationCorpus(scenarios, reader, thresholds)
|
|
|
430
501
|
return summarizeContextEvaluationReports(reports, thresholds);
|
|
431
502
|
}
|
|
432
503
|
//# sourceMappingURL=context-relevance.js.map
|
|
433
|
-
//# debugId=
|
|
504
|
+
//# debugId=80a03884-711e-5170-a3c1-f05ccb065702
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type BuildItemContextRelevanceCandidatesOptions, type ContextRelevanceCandidate, type ContextRelevanceSignals } from "./context-relevance.js";
|
|
1
|
+
import { type BuildItemContextRelevanceCandidatesOptions, type ContextRelevanceCandidate, type ContextRelevanceSignals, type ContextSignalProvenance } from "./context-relevance.js";
|
|
2
2
|
import type { ItemMetadata } from "../types/index.js";
|
|
3
3
|
/** Current serialized feature-store envelope version. */
|
|
4
|
-
export declare const CONTEXT_SIGNAL_STORE_FORMAT_VERSION =
|
|
4
|
+
export declare const CONTEXT_SIGNAL_STORE_FORMAT_VERSION = 3;
|
|
5
5
|
/** Current canonical signal-vector version. */
|
|
6
|
-
export declare const CONTEXT_SIGNAL_SET_VERSION =
|
|
6
|
+
export declare const CONTEXT_SIGNAL_SET_VERSION = 2;
|
|
7
7
|
/** Authoritative substrate used to derive one snapshot. */
|
|
8
8
|
export type ContextSignalSnapshotSource = "derived_index" | "scan_fallback";
|
|
9
9
|
/** One immutable item signal row. */
|
|
@@ -12,6 +12,8 @@ export interface ContextSignalSnapshotItem {
|
|
|
12
12
|
id: string;
|
|
13
13
|
/** Canonical normalized signal vector. */
|
|
14
14
|
signals: ContextRelevanceSignals;
|
|
15
|
+
/** Authoritative temporal source retained for explained ranking. */
|
|
16
|
+
signal_provenance: ContextSignalProvenance;
|
|
15
17
|
}
|
|
16
18
|
/** Rebuildable, deterministic context-signal snapshot. */
|
|
17
19
|
export interface ContextSignalSnapshot {
|
|
@@ -21,6 +23,8 @@ export interface ContextSignalSnapshot {
|
|
|
21
23
|
signal_set_version: number;
|
|
22
24
|
/** Authoritative history or derived-index cursor folded into this snapshot. */
|
|
23
25
|
source_cursor: string;
|
|
26
|
+
/** Deterministic digest of substantive recency provenance used by the fold. */
|
|
27
|
+
recency_evidence_fingerprint: string;
|
|
24
28
|
/** Stable clock supplied by the caller. */
|
|
25
29
|
generated_at: string;
|
|
26
30
|
/** Read substrate used for the fold. */
|