@unbrained/pm-cli 2026.9.4 → 2026.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/HARNESS_COMPATIBILITY.md +1 -1
- package/.agents/skills/README.md +2 -2
- package/.agents/skills/pm-developer/SKILL.md +4 -1
- package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +10 -0
- package/.agents/skills/pm-developer/references/GRAPH_AND_RELATIONSHIPS.md +3 -1
- package/.agents/skills/pm-extensions/SKILL.md +2 -2
- package/.agents/skills/pm-extensions/references/LIFECYCLE.md +3 -3
- package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +3 -3
- package/.agents/skills/pm-user/SKILL.md +2 -0
- package/.agents/skills/pm-user/references/BACKLOG_SHAPING.md +5 -0
- package/.agents/skills/pm-user/references/WORKFLOWS.md +20 -5
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +58 -3
- package/dist/cli/commander-usage.d.ts +2 -0
- package/dist/cli/commander-usage.js +15 -12
- package/dist/cli/help-json-payload.js +12 -7
- package/dist/cli/main.js +22 -11
- package/dist/cli/register-list-query.js +4 -2
- package/dist/cli/register-mutation.js +4 -2
- package/dist/cli/register-operations.js +17 -8
- package/dist/cli-bundle/bundle-manifest.json +153 -161
- package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +9 -0
- package/dist/cli-bundle/chunks/{chunk-V72UV7QS.js → chunk-BAX2BYUW.js} +73 -73
- package/dist/cli-bundle/chunks/{chunk-HI6BHPCU.js → chunk-CKOL5U7J.js} +51 -51
- package/dist/cli-bundle/chunks/{chunk-A24WAVE6.js → chunk-JT6XF6GE.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-I2AS367G.js → chunk-JX4DH4WC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-YW4QK2G7.js → chunk-NPN5I67J.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +5 -0
- package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +232 -0
- package/dist/cli-bundle/chunks/{chunk-RI4XNOYS.js → chunk-RWWBOWJ5.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +40 -0
- package/dist/cli-bundle/chunks/{chunk-X6CMGV6L.js → chunk-WI2AYPA7.js} +2 -2
- package/dist/cli-bundle/chunks/{register-list-query-Z5YYSJJG.js → register-list-query-5JL52D33.js} +3 -3
- package/dist/cli-bundle/chunks/{register-mutation-ELSP6I4I.js → register-mutation-ZPG7KMVP.js} +4 -4
- package/dist/cli-bundle/chunks/register-operations-I5W3KMGB.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-E2AE72QG.js → register-setup-H4SVAVX7.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-3646BZ4W.js → chunk-3BZEOXLT.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +6 -0
- package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +20 -0
- package/dist/cli-bundle/focused-chunks/{chunk-NBMJD6MK.js → chunk-EZR3GHFE.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +56 -0
- package/dist/cli-bundle/focused-chunks/{chunk-53IHPICX.js → chunk-LIJIA4TY.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-25UJBH4M.js → chunk-M6PBRFSH.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-AJR3OP2E.js → chunk-NTPY5GSO.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +177 -0
- package/dist/cli-bundle/focused-chunks/{chunk-MHKUIPJW.js → chunk-PEFABF7E.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-6PWPQKDN.js → chunk-QTVCLMSZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-7N2TV7WZ.js → chunk-QTZRBUYA.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +12 -0
- package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +10 -0
- package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +2 -0
- package/dist/cli-bundle/main.js +22 -15
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +37 -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 +42 -39
- 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/extensions/extension-types.d.ts +2 -0
- package/dist/core/extensions/extension-types.js +2 -2
- package/dist/core/extensions/module-graph-snapshot.js +5 -4
- package/dist/core/fs/host-environment-errors.d.ts +27 -0
- package/dist/core/fs/host-environment-errors.js +142 -0
- package/dist/core/history/drift-scan.d.ts +5 -0
- package/dist/core/history/drift-scan.js +16 -6
- package/dist/core/history/event-classification.d.ts +1 -1
- package/dist/core/history/event-classification.js +3 -2
- package/dist/core/history/history.js +37 -5
- package/dist/core/history/identity.d.ts +15 -0
- package/dist/core/history/identity.js +31 -0
- package/dist/core/history/projection.js +50 -17
- package/dist/core/history/read.js +6 -3
- package/dist/core/history/replay.d.ts +1 -2
- package/dist/core/history/replay.js +4 -4
- package/dist/core/history/version-address.d.ts +13 -0
- package/dist/core/history/version-address.js +33 -0
- package/dist/core/item/actionability.d.ts +21 -1
- package/dist/core/item/actionability.js +45 -10
- package/dist/core/item/id.js +8 -4
- package/dist/core/item/item-type-definition.d.ts +2 -0
- package/dist/core/item/item-type-definition.js +9 -2
- package/dist/core/item/type-registry.d.ts +5 -1
- package/dist/core/item/type-registry.js +9 -4
- package/dist/core/output/mutation-projection.js +12 -5
- package/dist/core/shared/errors.d.ts +8 -0
- package/dist/core/shared/errors.js +2 -2
- package/dist/core/store/item-metadata-query-index.js +13 -10
- package/dist/core/store/item-metadata-read-work.d.ts +19 -0
- package/dist/core/store/item-metadata-read-work.js +44 -0
- package/dist/core/store/item-store.d.ts +14 -0
- package/dist/core/store/item-store.js +52 -10
- package/dist/core/store/settings-validator.js +3 -2
- package/dist/core/validate/fix-planning.d.ts +1 -1
- package/dist/core/validate/fix-planning.js +2 -2
- package/dist/core/validate/missing-link-owners.d.ts +1 -1
- package/dist/core/validate/missing-link-owners.js +5 -3
- package/dist/core/validate/stale-file-classification.d.ts +6 -4
- package/dist/core/validate/stale-file-classification.js +20 -5
- package/dist/mcp/server.js +12 -5
- package/dist/sdk/actionability.d.ts +1 -1
- package/dist/sdk/actionability.js +3 -3
- package/dist/sdk/cli-contracts/command-aliases.js +11 -2
- package/dist/sdk/cli-contracts/completeness.js +4 -3
- package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
- package/dist/sdk/cli-contracts/flag-contracts.js +31 -5
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +21 -13
- package/dist/sdk/cli-contracts/grammar-contracts.js +11 -2
- package/dist/sdk/cli-contracts/runtime-contracts.js +5 -2
- package/dist/sdk/cli-contracts/schemas/assurance-definition.d.ts +254 -5
- package/dist/sdk/cli-contracts/schemas/assurance-definition.js +52 -2
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +30 -6
- package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
- package/dist/sdk/cli-contracts/tool-schema.js +32 -7
- package/dist/sdk/context/usage-ledger.d.ts +41 -0
- package/dist/sdk/context/usage-ledger.js +186 -0
- package/dist/sdk/context-intent-contracts.js +3 -3
- package/dist/sdk/context-usage.d.ts +18 -9
- package/dist/sdk/context-usage.js +44 -121
- package/dist/sdk/define.d.ts +1 -1
- package/dist/sdk/define.js +2 -2
- package/dist/sdk/dependency-provenance.d.ts +7 -0
- package/dist/sdk/dependency-provenance.js +14 -4
- package/dist/sdk/duplicates.d.ts +2 -0
- package/dist/sdk/duplicates.js +3 -2
- package/dist/sdk/environment/host-environment-errors.d.ts +5 -27
- package/dist/sdk/environment/host-environment-errors.js +4 -137
- package/dist/sdk/extension/install-runtime.js +9 -6
- package/dist/sdk/extension/install-snapshot.js +7 -6
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +104 -56
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +50 -2
- package/dist/sdk/governance/assurance-action.d.ts +3 -2
- package/dist/sdk/governance/assurance-action.js +23 -11
- package/dist/sdk/governance/assurance-runtime.d.ts +2 -0
- package/dist/sdk/governance/assurance-runtime.js +6 -3
- package/dist/sdk/governance/defect-recurrence-coverage.d.ts +93 -0
- package/dist/sdk/governance/defect-recurrence-coverage.js +189 -0
- package/dist/sdk/governance/defect-recurrence-graph.d.ts +33 -0
- package/dist/sdk/governance/defect-recurrence-graph.js +121 -0
- package/dist/sdk/governance/defect-recurrence.d.ts +8 -0
- package/dist/sdk/governance/defect-recurrence.js +118 -17
- package/dist/sdk/governance/health.d.ts +17 -2
- package/dist/sdk/governance/health.js +31 -10
- package/dist/sdk/governance/linked-file-report.d.ts +41 -0
- package/dist/sdk/governance/linked-file-report.js +72 -0
- package/dist/sdk/governance/validate-history-drift.js +16 -5
- package/dist/sdk/governance/validate.d.ts +5 -2
- package/dist/sdk/governance/validate.js +21 -37
- package/dist/sdk/governance.d.ts +2 -0
- package/dist/sdk/governance.js +4 -2
- package/dist/sdk/guide-topics.js +116 -2
- package/dist/sdk/history/salvage.d.ts +35 -0
- package/dist/sdk/history/salvage.js +248 -0
- package/dist/sdk/history-compact.js +32 -37
- package/dist/sdk/history-read.d.ts +3 -2
- package/dist/sdk/history-read.js +6 -3
- package/dist/sdk/history-repair.d.ts +12 -0
- package/dist/sdk/history-repair.js +60 -13
- package/dist/sdk/lifecycle/claim.d.ts +4 -0
- package/dist/sdk/lifecycle/claim.js +9 -3
- package/dist/sdk/lifecycle/close.d.ts +8 -0
- package/dist/sdk/lifecycle/close.js +16 -8
- package/dist/sdk/lifecycle/create.js +9 -12
- package/dist/sdk/lifecycle/restore.d.ts +1 -0
- package/dist/sdk/lifecycle/restore.js +19 -7
- package/dist/sdk/lifecycle/update.js +12 -12
- package/dist/sdk/lifecycle-policy.d.ts +3 -0
- package/dist/sdk/lifecycle-policy.js +2 -2
- package/dist/sdk/merge/abandoned-receipts.d.ts +15 -0
- package/dist/sdk/merge/abandoned-receipts.js +47 -0
- package/dist/sdk/merge/driver.js +4 -2
- package/dist/sdk/merge/index.d.ts +1 -0
- package/dist/sdk/merge/index.js +2 -2
- package/dist/sdk/merge/receipt-operation.d.ts +15 -0
- package/dist/sdk/merge/receipt-operation.js +97 -0
- package/dist/sdk/merge/receipt-schema.d.ts +20 -0
- package/dist/sdk/merge/receipt-schema.js +398 -0
- package/dist/sdk/merge/receipts.d.ts +16 -7
- package/dist/sdk/merge/receipts.js +54 -340
- package/dist/sdk/merge/reconcile.d.ts +2 -0
- package/dist/sdk/merge/reconcile.js +11 -4
- package/dist/sdk/output-projection.d.ts +3 -1
- package/dist/sdk/output-projection.js +11 -3
- package/dist/sdk/public-surface.json +1 -0
- package/dist/sdk/query/context.d.ts +9 -0
- package/dist/sdk/query/context.js +33 -21
- package/dist/sdk/query/duplicate-candidates.d.ts +7 -0
- package/dist/sdk/query/duplicate-candidates.js +71 -0
- package/dist/sdk/query/get.d.ts +2 -2
- package/dist/sdk/query/get.js +9 -8
- package/dist/sdk/query/history.d.ts +11 -0
- package/dist/sdk/query/history.js +34 -10
- package/dist/sdk/query/next.d.ts +15 -1
- package/dist/sdk/query/next.js +43 -20
- package/dist/sdk/query.d.ts +3 -0
- package/dist/sdk/query.js +5 -2
- package/dist/sdk/read-output-session.js +5 -3
- package/dist/sdk/runtime-primitives.d.ts +1 -1
- package/dist/sdk/runtime-primitives.js +3 -3
- package/dist/sdk/runtime.js +4 -2
- package/dist/sdk/similarity.d.ts +24 -3
- package/dist/sdk/similarity.js +50 -55
- package/dist/types.d.ts +2 -0
- package/dist/types.js +2 -2
- package/docs/AGENT_GUIDE.md +58 -1
- package/docs/BOUNDED_CONTEXT_READS.md +185 -0
- package/docs/CLOSE_EVIDENCE_RECOVERY.md +35 -0
- package/docs/COMMANDS.md +30 -8
- package/docs/CONTEXT_RELEVANCE.md +16 -4
- package/docs/DEFECT_RECURRENCE.md +80 -6
- package/docs/EXTENSIONS.md +18 -19
- package/docs/HISTORY_RECOVERY.md +146 -0
- package/docs/MERGE_SAFETY.md +50 -0
- package/docs/OUTPUT_PROJECTION_CONTRACTS.md +66 -0
- package/docs/PR_REVIEW_LOOP.md +18 -3
- package/docs/README.md +19 -1
- package/docs/RELEASING.md +31 -13
- package/docs/SDK_CONTEXT_TRUTH_CONTRACTS.md +24 -1
- package/docs/SDK_EXECUTION_CONTRACTS.md +105 -0
- package/docs/SDK_LIFECYCLE.md +27 -0
- package/docs/SDK_RUNTIME_BOUNDARIES.md +11 -0
- package/docs/TESTING.md +5 -0
- package/docs/agent-task-token-baseline.json +17 -17
- package/docs/agent-task-transcripts.json +2 -1
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +11 -11
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +11 -3
- package/marketplace.json +2 -2
- package/package.json +8 -6
- 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/README.md +10 -1
- package/packages/pm-governance-audit/extensions/governance-audit/dedupe-audit.ts +50 -65
- package/packages/pm-governance-audit/extensions/governance-audit/index.ts +2 -2
- package/packages/pm-governance-audit/extensions/governance-audit/sdk.ts +1 -0
- 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-claude/skills/pm-audit/SKILL.md +2 -2
- package/plugins/pm-claude/skills/pm-developer/SKILL.md +2 -2
- package/plugins/pm-claude/skills/pm-planner/SKILL.md +2 -2
- package/plugins/pm-claude/skills/pm-release/SKILL.md +2 -2
- package/plugins/pm-claude/skills/pm-workflow/SKILL.md +3 -3
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/pm-codex/skills/pm-auditor/SKILL.md +2 -2
- package/plugins/pm-codex/skills/pm-native/SKILL.md +3 -4
- package/plugins/pm-codex/skills/pm-release/SKILL.md +2 -2
- package/scripts/finalize-build.mjs +13 -1
- package/dist/cli-bundle/chunks/chunk-6XSKPNCF.js +0 -230
- package/dist/cli-bundle/chunks/chunk-OGBVU67G.js +0 -5
- package/dist/cli-bundle/chunks/chunk-TXW6VL33.js +0 -38
- package/dist/cli-bundle/chunks/chunk-VGLHECAP.js +0 -9
- package/dist/cli-bundle/chunks/register-operations-OH7R3ZT4.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-4YRAVI43.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-5P4HVOWG.js +0 -176
- package/dist/cli-bundle/focused-chunks/chunk-636VVQ7F.js +0 -54
- package/dist/cli-bundle/focused-chunks/chunk-B3A6MJYE.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-BFDDJ2T2.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-BHUIRZWQ.js +0 -9
- package/dist/cli-bundle/focused-chunks/chunk-JADHHPY6.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-NSKBLHVI.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-P2GOAOQN.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-YARWJM2B.js +0 -2
- package/sdk/public-surface.json +0 -33034
|
@@ -4,18 +4,16 @@
|
|
|
4
4
|
* Privacy-minimal, derived context-usage feedback primitives. The JSONL ledger
|
|
5
5
|
* contains only item ids, timestamps, authors, ranks, profiles, and command
|
|
6
6
|
* intents; it never enters item history and is safe to delete or rebuild.
|
|
7
|
+
* Persistence requires trusted, stable workspace directory entries and
|
|
8
|
+
* ancestors. For a workspace writable by an untrusted concurrent actor, set
|
|
9
|
+
* PM_CONTEXT_USAGE_DISABLED=1 or use an isolated copy owned by the caller.
|
|
7
10
|
*/
|
|
8
11
|
|
|
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]="
|
|
12
|
+
!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]="b1b1aa19-b1de-5140-8aea-ee1994ee9ecd")}catch(e){}}();
|
|
10
13
|
import { randomUUID } from "node:crypto";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
import { acquireLock } from "../core/lock/lock.js";
|
|
14
|
-
const DEFAULT_MAX_EVENTS = 2_048;
|
|
15
|
-
const DEFAULT_RETENTION_DAYS = 30;
|
|
14
|
+
import { appendEvents, readEvents, resolveNow, ContextUsageValidationError, CONTEXT_USAGE_LIMITS, } from "./context/usage-ledger.js";
|
|
15
|
+
export { ContextUsageValidationError, CONTEXT_USAGE_LIMITS } from "./context/usage-ledger.js";
|
|
16
16
|
const DAY_MS = 86_400_000;
|
|
17
|
-
const DEFAULT_COMPACTION_BYTES = 262_144;
|
|
18
|
-
const CONTEXT_USAGE_LOCK_ID = "context-usage-ledger";
|
|
19
17
|
const CONTEXT_USAGE_SERVING_RECEIPT = Symbol.for("@unbrained/pm-cli/context-usage-serving-receipt");
|
|
20
18
|
function asObjectRecord(value) {
|
|
21
19
|
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
@@ -69,15 +67,13 @@ function addContextUsageIdList(ids, value) {
|
|
|
69
67
|
addContextUsageId(ids, itemId);
|
|
70
68
|
}
|
|
71
69
|
function collectNextResultItemIds(record, ids) {
|
|
72
|
-
const rows =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
...(Array.isArray(record.held_by_others) ? record.held_by_others : []),
|
|
80
|
-
];
|
|
70
|
+
const rows = asObjectRecord(record.recommended) === null
|
|
71
|
+
? []
|
|
72
|
+
: [record.recommended];
|
|
73
|
+
for (const key of ["ready", "decision_needed", "gate_needed", "containers", "blocked", "held_by_others"]) {
|
|
74
|
+
if (Array.isArray(record[key]))
|
|
75
|
+
rows.push(...record[key]);
|
|
76
|
+
}
|
|
81
77
|
for (const value of rows) {
|
|
82
78
|
const row = asObjectRecord(value);
|
|
83
79
|
addContextUsageId(ids, row?.id);
|
|
@@ -164,86 +160,7 @@ export async function finalizeContextUsageDelivery(options) {
|
|
|
164
160
|
});
|
|
165
161
|
return true;
|
|
166
162
|
}
|
|
167
|
-
/**
|
|
168
|
-
export class ContextUsageValidationError extends TypeError {
|
|
169
|
-
/** Stable machine-readable error code for package and CLI hosts. */
|
|
170
|
-
code = "context_usage_validation_failed";
|
|
171
|
-
/** Creates a typed validation error without exposing derived ledger contents. */
|
|
172
|
-
constructor(message) {
|
|
173
|
-
super(message);
|
|
174
|
-
this.name = "ContextUsageValidationError";
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
function ledgerPath(pmRoot) {
|
|
178
|
-
return path.join(pmRoot, "runtime", "context-usage.jsonl");
|
|
179
|
-
}
|
|
180
|
-
function resolveNow(options) {
|
|
181
|
-
const iso = options.now ?? new Date().toISOString();
|
|
182
|
-
const ms = Date.parse(iso);
|
|
183
|
-
if (!Number.isFinite(ms))
|
|
184
|
-
throw new ContextUsageValidationError("Context usage now must be a valid timestamp");
|
|
185
|
-
return { iso: new Date(ms).toISOString(), ms };
|
|
186
|
-
}
|
|
187
|
-
async function readEvents(options) {
|
|
188
|
-
try {
|
|
189
|
-
const text = await readFile(ledgerPath(options.pmRoot), "utf8");
|
|
190
|
-
const events = text
|
|
191
|
-
.split("\n")
|
|
192
|
-
.filter(Boolean)
|
|
193
|
-
.flatMap((line) => {
|
|
194
|
-
try {
|
|
195
|
-
return [JSON.parse(line)];
|
|
196
|
-
}
|
|
197
|
-
catch {
|
|
198
|
-
return [];
|
|
199
|
-
}
|
|
200
|
-
});
|
|
201
|
-
const maxEvents = options.maxEvents ?? DEFAULT_MAX_EVENTS;
|
|
202
|
-
const retentionDays = options.retentionDays ?? DEFAULT_RETENTION_DAYS;
|
|
203
|
-
const cutoff = resolveNow(options).ms - retentionDays * DAY_MS;
|
|
204
|
-
return events
|
|
205
|
-
.filter((entry) => Date.parse(entry.at) >= cutoff)
|
|
206
|
-
.slice(-maxEvents);
|
|
207
|
-
}
|
|
208
|
-
catch {
|
|
209
|
-
return [];
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
async function appendEvents(options, events, deliveryServeId) {
|
|
213
|
-
const maxEvents = options.maxEvents ?? DEFAULT_MAX_EVENTS;
|
|
214
|
-
const retentionDays = options.retentionDays ?? DEFAULT_RETENTION_DAYS;
|
|
215
|
-
if (!Number.isInteger(maxEvents) ||
|
|
216
|
-
maxEvents < 1 ||
|
|
217
|
-
!Number.isFinite(retentionDays) ||
|
|
218
|
-
retentionDays <= 0) {
|
|
219
|
-
throw new ContextUsageValidationError("Context usage retention requires positive maxEvents and retentionDays");
|
|
220
|
-
}
|
|
221
|
-
const target = ledgerPath(options.pmRoot);
|
|
222
|
-
const runtimeDirectory = path.dirname(target);
|
|
223
|
-
const releaseLock = await acquireLock(options.pmRoot, CONTEXT_USAGE_LOCK_ID, 30, `context-usage:${process.pid}`, false, false, 3_000);
|
|
224
|
-
try {
|
|
225
|
-
await mkdir(runtimeDirectory, { recursive: true });
|
|
226
|
-
if (deliveryServeId !== undefined &&
|
|
227
|
-
(await readEvents(options)).some((event) => event.kind === "delivery" && event.serve_id === deliveryServeId)) {
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
await appendFile(target, events.map((event) => `${JSON.stringify(event)}\n`).join(""), "utf8");
|
|
231
|
-
const customBounds = options.maxEvents !== undefined || options.retentionDays !== undefined;
|
|
232
|
-
if (!customBounds && (await stat(target)).size <= DEFAULT_COMPACTION_BYTES)
|
|
233
|
-
return;
|
|
234
|
-
const retained = await readEvents(options);
|
|
235
|
-
const temporary = `${target}.${process.pid}.${randomUUID()}.tmp`;
|
|
236
|
-
await writeFile(temporary, `${retained.map((entry) => JSON.stringify(entry)).join("\n")}\n`, "utf8");
|
|
237
|
-
await rename(temporary, target);
|
|
238
|
-
}
|
|
239
|
-
finally {
|
|
240
|
-
await releaseLock();
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
async function appendEvent(options, event) {
|
|
244
|
-
await appendEvents(options, [event]);
|
|
245
|
-
}
|
|
246
|
-
/** Records a propensity-complete context/next serving event. */
|
|
163
|
+
/** Records a bounded prefix of ranked context candidates with explicit sampling counts. */
|
|
247
164
|
export async function recordContextUsageServing(options) {
|
|
248
165
|
if ([
|
|
249
166
|
process.env.PM_CONTEXT_USAGE_DISABLED === "1",
|
|
@@ -255,32 +172,37 @@ export async function recordContextUsageServing(options) {
|
|
|
255
172
|
throw new ContextUsageValidationError("Context usage serving requires an author and valid ranked rows");
|
|
256
173
|
}
|
|
257
174
|
const normalizedRows = options.rows.map((row) => ({
|
|
258
|
-
...row,
|
|
259
175
|
id: row.id.trim(),
|
|
176
|
+
rank: row.rank,
|
|
177
|
+
included: row.included,
|
|
260
178
|
}));
|
|
261
179
|
if (new Set(normalizedRows.map((row) => row.id)).size !== normalizedRows.length) {
|
|
262
180
|
throw new ContextUsageValidationError("Context usage serving requires unique normalized row ids");
|
|
263
181
|
}
|
|
182
|
+
const recordedRows = normalizedRows.slice(0, CONTEXT_USAGE_LIMITS.max_serving_rows);
|
|
264
183
|
const receipt = {
|
|
265
184
|
serve_id: randomUUID(),
|
|
266
185
|
author: options.author.trim(),
|
|
267
186
|
surface: options.surface,
|
|
268
187
|
rows: normalizedRows,
|
|
188
|
+
recorded_item_ids: recordedRows.map((row) => row.id),
|
|
269
189
|
};
|
|
270
|
-
await
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
190
|
+
receipt.storage = await appendEvents(options, [{
|
|
191
|
+
kind: "serve",
|
|
192
|
+
schema_version: 2,
|
|
193
|
+
serve_id: receipt.serve_id,
|
|
194
|
+
at: resolveNow(options).iso,
|
|
195
|
+
author: options.author.trim(),
|
|
196
|
+
surface: options.surface,
|
|
197
|
+
profile: options.profile.trim() || "balanced",
|
|
198
|
+
rows: recordedRows,
|
|
199
|
+
candidate_count: normalizedRows.length,
|
|
200
|
+
omitted_row_count: normalizedRows.length - recordedRows.length,
|
|
201
|
+
result_omitted: false,
|
|
202
|
+
packed_item_ids: recordedRows
|
|
203
|
+
.filter((row) => row.included)
|
|
204
|
+
.map((row) => row.id),
|
|
205
|
+
}]);
|
|
284
206
|
return receipt;
|
|
285
207
|
}
|
|
286
208
|
/** Append the exact post-egress delivery decision for one serving receipt. */
|
|
@@ -298,6 +220,7 @@ export async function recordContextUsageDelivery(options) {
|
|
|
298
220
|
(options.resultOmitted && deliveredItemIds.length > 0)) {
|
|
299
221
|
throw new ContextUsageValidationError("Context usage delivery requires emitted ranked ids and zero ids for an omitted result");
|
|
300
222
|
}
|
|
223
|
+
const recordedIds = new Set(options.receipt.recorded_item_ids ?? options.receipt.rows.map((row) => row.id));
|
|
301
224
|
const delivery = {
|
|
302
225
|
kind: "delivery",
|
|
303
226
|
schema_version: 2,
|
|
@@ -306,7 +229,7 @@ export async function recordContextUsageDelivery(options) {
|
|
|
306
229
|
author: options.receipt.author,
|
|
307
230
|
surface: options.receipt.surface,
|
|
308
231
|
result_omitted: options.resultOmitted,
|
|
309
|
-
delivered_item_ids: deliveredItemIds,
|
|
232
|
+
delivered_item_ids: deliveredItemIds.filter((id) => recordedIds.has(id)),
|
|
310
233
|
};
|
|
311
234
|
await appendEvents(options, [delivery], delivery.serve_id);
|
|
312
235
|
}
|
|
@@ -320,13 +243,13 @@ export async function recordContextUsageTouch(options) {
|
|
|
320
243
|
!options.intent.trim()) {
|
|
321
244
|
throw new ContextUsageValidationError("Context usage touch requires author, itemId, and intent");
|
|
322
245
|
}
|
|
323
|
-
await
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
246
|
+
await appendEvents(options, [{
|
|
247
|
+
kind: "touch",
|
|
248
|
+
at: resolveNow(options).iso,
|
|
249
|
+
author: options.author.trim(),
|
|
250
|
+
item_id: options.itemId.trim(),
|
|
251
|
+
intent: options.intent.trim(),
|
|
252
|
+
}]);
|
|
330
253
|
}
|
|
331
254
|
/**
|
|
332
255
|
* Records mutation outcomes as one append and one optional compaction pass.
|
|
@@ -442,4 +365,4 @@ export async function readContextUsageAffinity(options) {
|
|
|
442
365
|
};
|
|
443
366
|
}
|
|
444
367
|
//# sourceMappingURL=context-usage.js.map
|
|
445
|
-
//# debugId=
|
|
368
|
+
//# debugId=b1b1aa19-b1de-5140-8aea-ee1994ee9ecd
|
package/dist/sdk/define.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ import type { ProjectProfileDefinition } from "../core/profile/profile-presets.j
|
|
|
37
37
|
type ExactDefinition<TDefinition, TContract> = TDefinition & Record<Exclude<keyof TDefinition, keyof TContract>, never>;
|
|
38
38
|
type FlagAuthoringDefinition = Pick<FlagDefinition, "long" | "short" | "value_name" | "description" | "required" | "enabled" | "visible" | "value_type" | "type" | "list" | "default">;
|
|
39
39
|
type ItemFieldAuthoringDefinition = Pick<SchemaFieldDefinition, "name" | "type" | "optional" | "default" | "values">;
|
|
40
|
-
type ItemTypeAuthoringDefinition = Pick<SchemaItemTypeDefinition, "name" | "folder" | "aliases" | "required_create_fields" | "required_create_repeatables" | "command_option_policies" | "options" | "description" | "default_status">;
|
|
40
|
+
type ItemTypeAuthoringDefinition = Pick<SchemaItemTypeDefinition, "name" | "folder" | "aliases" | "required_create_fields" | "required_create_repeatables" | "command_option_policies" | "options" | "description" | "default_status" | "execution_role">;
|
|
41
41
|
type MigrationAuthoringDefinition = Pick<SchemaMigrationDefinition, "id" | "description" | "status" | "mandatory" | "run">;
|
|
42
42
|
type SearchProviderAuthoringDefinition = Pick<SearchProviderDefinition, "name" | "query" | "queryExpansion" | "query_expansion" | "rerank" | "embedBatch" | "embed_batch" | "embed">;
|
|
43
43
|
type VectorStoreAdapterAuthoringDefinition = Pick<VectorStoreAdapterDefinition, "name" | "query" | "upsert" | "delete">;
|
package/dist/sdk/define.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* to keep `capabilities` matched to the surfaces the extension actually registers.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
!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]="
|
|
12
|
+
!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]="e37a2da9-966f-5044-bc5e-d27ddb07e65b")}catch(e){}}();
|
|
13
13
|
export function defineExtensionManifest(manifest) {
|
|
14
14
|
return manifest;
|
|
15
15
|
}
|
|
@@ -218,4 +218,4 @@ export function defineOnIndexHook(hook) {
|
|
|
218
218
|
return hook;
|
|
219
219
|
}
|
|
220
220
|
//# sourceMappingURL=define.js.map
|
|
221
|
-
//# debugId=
|
|
221
|
+
//# debugId=e37a2da9-966f-5044-bc5e-d27ddb07e65b
|
|
@@ -61,3 +61,10 @@ export declare function normalizeDependencySourceKind(sourceKind: string | undef
|
|
|
61
61
|
* global seeds preserve the caller-provided id verbatim (apart from trimming).
|
|
62
62
|
*/
|
|
63
63
|
export declare function normalizeDependencySeedId(id: string, prefix: string, sourceKind: string | undefined): string;
|
|
64
|
+
/**
|
|
65
|
+
* Canonicalize a local relationship target using the workspace prefix. Explicit
|
|
66
|
+
* provider locators and externally sourced identities retain case and spelling;
|
|
67
|
+
* only surrounding whitespace is removed. Resolution and parent policy remain
|
|
68
|
+
* the caller's responsibility, so dangling local ids are never guessed remote.
|
|
69
|
+
*/
|
|
70
|
+
export declare function normalizeItemReference(reference: string, prefix: string, sourceKind?: string): string;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* items outside the current workspace.
|
|
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]="ee17fdea-aeac-55b0-8302-a8740ba8428e")}catch(e){}}();
|
|
9
9
|
import { normalizeItemId } from "../core/item/id.js";
|
|
10
10
|
import { isExternalDependencyReference, isExternalDependencySourceKind, } from "../core/item/dependency-reference.js";
|
|
11
11
|
export { isExternalDependencyReference, isExternalDependencySourceKind, } from "../core/item/dependency-reference.js";
|
|
@@ -117,10 +117,20 @@ export function normalizeDependencySourceKind(sourceKind) {
|
|
|
117
117
|
* global seeds preserve the caller-provided id verbatim (apart from trimming).
|
|
118
118
|
*/
|
|
119
119
|
export function normalizeDependencySeedId(id, prefix, sourceKind) {
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
return normalizeItemReference(id, prefix, sourceKind);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Canonicalize a local relationship target using the workspace prefix. Explicit
|
|
124
|
+
* provider locators and externally sourced identities retain case and spelling;
|
|
125
|
+
* only surrounding whitespace is removed. Resolution and parent policy remain
|
|
126
|
+
* the caller's responsibility, so dangling local ids are never guessed remote.
|
|
127
|
+
*/
|
|
128
|
+
export function normalizeItemReference(reference, prefix, sourceKind) {
|
|
129
|
+
const trimmed = reference.trim();
|
|
130
|
+
return isExternalDependencySourceKind(sourceKind) ||
|
|
131
|
+
isExternalDependencyReference(trimmed)
|
|
122
132
|
? trimmed
|
|
123
133
|
: normalizeItemId(trimmed, prefix);
|
|
124
134
|
}
|
|
125
135
|
//# sourceMappingURL=dependency-provenance.js.map
|
|
126
|
-
//# debugId=
|
|
136
|
+
//# debugId=ee17fdea-aeac-55b0-8302-a8740ba8428e
|
package/dist/sdk/duplicates.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ import type { GlobalOptions } from "../core/shared/command-types.js";
|
|
|
8
8
|
import { type DuplicateCluster, type DuplicateClustersResult } from "./similarity.js";
|
|
9
9
|
/** Options shared by the `pm duplicates` command and SDK action. */
|
|
10
10
|
export interface DuplicatesCommandOptions {
|
|
11
|
+
/** Compare all pairs instead of using lossless prefix filtering. */
|
|
12
|
+
exhaustive?: boolean;
|
|
11
13
|
/** Lifecycle statuses to include; omitted means every status. */
|
|
12
14
|
status?: readonly string[];
|
|
13
15
|
/** Inclusive creation timestamp lower bound. */
|
package/dist/sdk/duplicates.js
CHANGED
|
@@ -1,11 +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]="51a84d98-6b3c-55ad-81f8-81928aa6e537")}catch(e){}}();
|
|
3
3
|
import { resolvePmRoot } from "../core/store/paths.js";
|
|
4
4
|
import { findDuplicateClusters, } from "./similarity.js";
|
|
5
5
|
/** Discover existing duplicate clusters without creating or mutating an item. */
|
|
6
6
|
export async function runDuplicates(global, options = {}) {
|
|
7
7
|
const result = await findDuplicateClusters({
|
|
8
8
|
pmRoot: resolvePmRoot(process.cwd(), global.path),
|
|
9
|
+
exhaustive: options.exhaustive,
|
|
9
10
|
...(options.status === undefined
|
|
10
11
|
? {}
|
|
11
12
|
: {
|
|
@@ -37,4 +38,4 @@ export async function runDuplicates(global, options = {}) {
|
|
|
37
38
|
};
|
|
38
39
|
}
|
|
39
40
|
//# sourceMappingURL=duplicates.js.map
|
|
40
|
-
//# debugId=
|
|
41
|
+
//# debugId=51a84d98-6b3c-55ad-81f8-81928aa6e537
|
|
@@ -1,27 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/** Code used for access policy and read-only filesystems. */
|
|
7
|
-
permission?: string;
|
|
8
|
-
/** Code used for file-descriptor and memory exhaustion. */
|
|
9
|
-
resource?: string;
|
|
10
|
-
}
|
|
11
|
-
/** Context and compatibility controls for a host-environment boundary. */
|
|
12
|
-
export interface HostEnvironmentBoundaryOptions {
|
|
13
|
-
/** Existing surface-specific codes that must remain compatible. */
|
|
14
|
-
codes?: HostEnvironmentFaultCodeOverrides;
|
|
15
|
-
/** Human explanation of why the operation needs host resources. */
|
|
16
|
-
why?: string;
|
|
17
|
-
/** Additional ordered recovery guidance. */
|
|
18
|
-
nextSteps?: readonly string[];
|
|
19
|
-
/** Copyable retry command when one is safe. */
|
|
20
|
-
suggestedRetry?: string;
|
|
21
|
-
}
|
|
22
|
-
/** Return a declared host errno only when it represents recoverable environment state. */
|
|
23
|
-
export declare function classifyHostEnvironmentFault(error: unknown): string | null;
|
|
24
|
-
/** Translate one known host fault into a stable path-redacted SDK refusal. */
|
|
25
|
-
export declare function translateHostEnvironmentFault(error: unknown, operation: string, options?: HostEnvironmentBoundaryOptions): PmCliError | null;
|
|
26
|
-
/** Run one SDK filesystem stage and translate only declared host faults. */
|
|
27
|
-
export declare function withHostEnvironmentBoundary<T>(operation: string, run: () => Promise<T>, options?: HostEnvironmentBoundaryOptions): Promise<T>;
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/host-environment-errors
|
|
3
|
+
* Public SDK compatibility surface for path-redacted host filesystem refusals.
|
|
4
|
+
*/
|
|
5
|
+
export { classifyHostEnvironmentFault, translateHostEnvironmentFault, withHostEnvironmentBoundary, type HostEnvironmentBoundaryOptions, type HostEnvironmentFaultCodeOverrides, } from "../../core/fs/host-environment-errors.js";
|
|
@@ -1,142 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module sdk/host-environment-errors
|
|
3
|
-
*
|
|
4
|
-
* Classifies host filesystem/resource failures at SDK boundaries without
|
|
5
|
-
* leaking local paths or swallowing genuine implementation defects.
|
|
3
|
+
* Public SDK compatibility surface for path-redacted host filesystem refusals.
|
|
6
4
|
*/
|
|
7
5
|
|
|
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]="
|
|
9
|
-
|
|
10
|
-
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
11
|
-
import { PmCliError } from "../../core/shared/errors.js";
|
|
12
|
-
const HOST_ENVIRONMENT_FAULTS = new Map([
|
|
13
|
-
[
|
|
14
|
-
"EACCES",
|
|
15
|
-
{
|
|
16
|
-
summary: "was denied filesystem permission",
|
|
17
|
-
recovery: "Grant the required filesystem access, then retry.",
|
|
18
|
-
category: "permission",
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
[
|
|
22
|
-
"EDQUOT",
|
|
23
|
-
{
|
|
24
|
-
summary: "exceeded the filesystem quota",
|
|
25
|
-
recovery: "Raise or reclaim the filesystem quota, then retry.",
|
|
26
|
-
category: "capacity",
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
[
|
|
30
|
-
"EMFILE",
|
|
31
|
-
{
|
|
32
|
-
summary: "exhausted the process file-descriptor limit",
|
|
33
|
-
recovery: "Close unused file handles or raise the process limit, then retry.",
|
|
34
|
-
category: "resource",
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
[
|
|
38
|
-
"ENFILE",
|
|
39
|
-
{
|
|
40
|
-
summary: "exhausted the host file-descriptor limit",
|
|
41
|
-
recovery: "Free host file descriptors or raise the host limit, then retry.",
|
|
42
|
-
category: "resource",
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
[
|
|
46
|
-
"ENOMEM",
|
|
47
|
-
{
|
|
48
|
-
summary: "ran out of available memory",
|
|
49
|
-
recovery: "Free memory or reduce concurrent work, then retry.",
|
|
50
|
-
category: "resource",
|
|
51
|
-
},
|
|
52
|
-
],
|
|
53
|
-
[
|
|
54
|
-
"ENOSPC",
|
|
55
|
-
{
|
|
56
|
-
summary: "ran out of storage space",
|
|
57
|
-
recovery: "Free storage on the filesystem holding the project, then retry.",
|
|
58
|
-
category: "capacity",
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
[
|
|
62
|
-
"EPERM",
|
|
63
|
-
{
|
|
64
|
-
summary: "was denied by the host permission policy",
|
|
65
|
-
recovery: "Grant the required filesystem permission, then retry.",
|
|
66
|
-
category: "permission",
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
[
|
|
70
|
-
"EROFS",
|
|
71
|
-
{
|
|
72
|
-
summary: "targeted a read-only filesystem",
|
|
73
|
-
recovery: "Use a writable project filesystem or remount it read-write, then retry.",
|
|
74
|
-
category: "permission",
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
|
-
]);
|
|
78
|
-
const OPERATION_PATTERN = /^[a-z][a-z0-9_]{0,63}$/u;
|
|
79
|
-
const HOST_ENVIRONMENT_ERRNO_NAMES = new Map([
|
|
80
|
-
[osConstants.errno.EACCES, "EACCES"],
|
|
81
|
-
[osConstants.errno.EDQUOT, "EDQUOT"],
|
|
82
|
-
[osConstants.errno.EMFILE, "EMFILE"],
|
|
83
|
-
[osConstants.errno.ENFILE, "ENFILE"],
|
|
84
|
-
[osConstants.errno.ENOMEM, "ENOMEM"],
|
|
85
|
-
[osConstants.errno.ENOSPC, "ENOSPC"],
|
|
86
|
-
[osConstants.errno.EPERM, "EPERM"],
|
|
87
|
-
[osConstants.errno.EROFS, "EROFS"],
|
|
88
|
-
].filter(([errno]) => Number.isInteger(errno)));
|
|
89
|
-
const HOST_ENVIRONMENT_FAULT_CODES = {
|
|
90
|
-
capacity: { code: "host_environment_capacity_fault" },
|
|
91
|
-
permission: { code: "host_environment_permission_fault" },
|
|
92
|
-
resource: { code: "host_environment_resource_fault" },
|
|
93
|
-
};
|
|
94
|
-
/** Return a declared host errno only when it represents recoverable environment state. */
|
|
95
|
-
export function classifyHostEnvironmentFault(error) {
|
|
96
|
-
if (typeof error !== "object" || error === null) {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
const errorRecord = error;
|
|
100
|
-
if (typeof errorRecord.code === "string" &&
|
|
101
|
-
HOST_ENVIRONMENT_FAULTS.has(errorRecord.code)) {
|
|
102
|
-
return errorRecord.code;
|
|
103
|
-
}
|
|
104
|
-
if (typeof errorRecord.errno !== "number" ||
|
|
105
|
-
!Number.isInteger(errorRecord.errno)) {
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
|
-
return HOST_ENVIRONMENT_ERRNO_NAMES.get(Math.abs(errorRecord.errno)) ?? null;
|
|
109
|
-
}
|
|
110
|
-
/** Translate one known host fault into a stable path-redacted SDK refusal. */
|
|
111
|
-
export function translateHostEnvironmentFault(error, operation, options = {}) {
|
|
112
|
-
const errno = classifyHostEnvironmentFault(error);
|
|
113
|
-
if (errno === null)
|
|
114
|
-
return null;
|
|
115
|
-
if (!OPERATION_PATTERN.test(operation)) {
|
|
116
|
-
throw new PmCliError("Host environment operation labels must be bounded identifiers.", EXIT_CODE.USAGE, { code: "host_environment_operation_invalid", field: "operation" });
|
|
117
|
-
}
|
|
118
|
-
const fault = HOST_ENVIRONMENT_FAULTS.get(errno);
|
|
119
|
-
return new PmCliError(`Host filesystem operation ${operation} ${fault.summary}.`, EXIT_CODE.GENERIC_FAILURE, {
|
|
120
|
-
code: options.codes?.[fault.category] ??
|
|
121
|
-
HOST_ENVIRONMENT_FAULT_CODES[fault.category].code,
|
|
122
|
-
reason: errno,
|
|
123
|
-
required: fault.recovery,
|
|
124
|
-
why: options.why ??
|
|
125
|
-
"The operating system refused a required project filesystem operation.",
|
|
126
|
-
nextSteps: [fault.recovery, ...(options.nextSteps ?? [])],
|
|
127
|
-
...(options.suggestedRetry
|
|
128
|
-
? { recovery: { suggested_retry: options.suggestedRetry } }
|
|
129
|
-
: {}),
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
/** Run one SDK filesystem stage and translate only declared host faults. */
|
|
133
|
-
export async function withHostEnvironmentBoundary(operation, run, options = {}) {
|
|
134
|
-
try {
|
|
135
|
-
return await run();
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
throw translateHostEnvironmentFault(error, operation, options) ?? error;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
6
|
+
!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]="8a0d8f6e-f4ff-5a0c-9205-d28e03df72b9")}catch(e){}}();
|
|
7
|
+
export { classifyHostEnvironmentFault, translateHostEnvironmentFault, withHostEnvironmentBoundary, } from "../../core/fs/host-environment-errors.js";
|
|
141
8
|
//# sourceMappingURL=host-environment-errors.js.map
|
|
142
|
-
//# debugId=
|
|
9
|
+
//# debugId=8a0d8f6e-f4ff-5a0c-9205-d28e03df72b9
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Provides cross-platform extension copy safety and owner-bound install locks.
|
|
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]="b100fde9-412b-587b-85ac-532117e2253f")}catch(e){}}();
|
|
8
|
+
import { withHostEnvironmentBoundary } from "../../core/fs/host-environment-errors.js";
|
|
8
9
|
import { randomUUID } from "node:crypto";
|
|
9
10
|
import fs from "node:fs/promises";
|
|
10
11
|
import os from "node:os";
|
|
@@ -88,7 +89,7 @@ export const resolveCanonicalExtensionInstallDestination = async (destinationDir
|
|
|
88
89
|
return path.join(canonicalDestinationParent, path.basename(resolvedDestination));
|
|
89
90
|
};
|
|
90
91
|
/** Copy an extension without recursively copying a destination nested below its source. */
|
|
91
|
-
export const copyExtensionDirectoryWithoutSelfNesting = async (sourceDirectory, destinationDirectory, copyDirectory, temporaryDirectory = os.tmpdir()) => {
|
|
92
|
+
export const copyExtensionDirectoryWithoutSelfNesting = async (sourceDirectory, destinationDirectory, copyDirectory, temporaryDirectory = os.tmpdir()) => withHostEnvironmentBoundary("extension_install_copy", async () => {
|
|
92
93
|
const resolvedSource = path.resolve(sourceDirectory);
|
|
93
94
|
const canonicalSource = await fs
|
|
94
95
|
.realpath(resolvedSource)
|
|
@@ -148,13 +149,15 @@ export const copyExtensionDirectoryWithoutSelfNesting = async (sourceDirectory,
|
|
|
148
149
|
finally {
|
|
149
150
|
await fs.rm(stagingRoot, { recursive: true, force: true });
|
|
150
151
|
}
|
|
151
|
-
};
|
|
152
|
+
});
|
|
152
153
|
/** Copy one extension directory with bounded transient-race retries. */
|
|
153
154
|
export const copyExtensionDirectoryForInstall = async (sourceDirectory, destinationDirectory, copyDirectory = fs.cp) => {
|
|
154
155
|
for (let attempt = 1; attempt <= EXTENSION_INSTALL_COPY_ATTEMPTS; attempt += 1) {
|
|
155
156
|
try {
|
|
156
|
-
await
|
|
157
|
-
|
|
157
|
+
await withHostEnvironmentBoundary("extension_install_copy", async () => {
|
|
158
|
+
await fs.rm(destinationDirectory, { recursive: true, force: true });
|
|
159
|
+
await copyExtensionDirectoryWithoutSelfNesting(sourceDirectory, destinationDirectory, copyDirectory);
|
|
160
|
+
});
|
|
158
161
|
return;
|
|
159
162
|
}
|
|
160
163
|
catch (error) {
|
|
@@ -308,4 +311,4 @@ export const withExtensionInstallLock = async (settingsRoot, destinationDirector
|
|
|
308
311
|
}
|
|
309
312
|
};
|
|
310
313
|
//# sourceMappingURL=install-runtime.js.map
|
|
311
|
-
//# debugId=
|
|
314
|
+
//# debugId=b100fde9-412b-587b-85ac-532117e2253f
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Captures and restores extension files and metadata around install persistence.
|
|
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]="58ec3f16-267a-5a31-abd2-df46bb82b716")}catch(e){}}();
|
|
8
|
+
import { withHostEnvironmentBoundary } from "../../core/fs/host-environment-errors.js";
|
|
8
9
|
import fs from "node:fs/promises";
|
|
9
10
|
import path from "node:path";
|
|
10
11
|
import { getSettingsPath } from "../../core/store/paths.js";
|
|
@@ -17,7 +18,7 @@ export const readOptionalMetadataFile = async (filePath) => fs.readFile(filePath
|
|
|
17
18
|
throw error;
|
|
18
19
|
});
|
|
19
20
|
/** Capture extension files and metadata before applying an install mutation. */
|
|
20
|
-
export const captureExtensionInstallSnapshot = async (selectedRoot, settingsRoot, destinationDirectory, destinationExists, backupDirectory) => {
|
|
21
|
+
export const captureExtensionInstallSnapshot = async (selectedRoot, settingsRoot, destinationDirectory, destinationExists, backupDirectory) => withHostEnvironmentBoundary("extension_install_backup", async () => {
|
|
21
22
|
const managedStatePath = resolveManagedExtensionStatePath(selectedRoot);
|
|
22
23
|
const settingsPath = getSettingsPath(settingsRoot);
|
|
23
24
|
const [managedStateContents, settingsContents] = await Promise.all([
|
|
@@ -39,9 +40,9 @@ export const captureExtensionInstallSnapshot = async (selectedRoot, settingsRoot
|
|
|
39
40
|
settingsPath,
|
|
40
41
|
settingsContents,
|
|
41
42
|
};
|
|
42
|
-
};
|
|
43
|
+
});
|
|
43
44
|
/** Restore directory and metadata snapshots after a partially persisted install. */
|
|
44
|
-
export const restoreExtensionInstallSnapshot = async (snapshot) => {
|
|
45
|
+
export const restoreExtensionInstallSnapshot = async (snapshot) => withHostEnvironmentBoundary("extension_install_rollback", async () => {
|
|
45
46
|
await fs.rm(snapshot.destinationDirectory, { recursive: true, force: true });
|
|
46
47
|
if (snapshot.destinationExists) {
|
|
47
48
|
await fs.cp(snapshot.backupDirectory, snapshot.destinationDirectory, {
|
|
@@ -61,6 +62,6 @@ export const restoreExtensionInstallSnapshot = async (snapshot) => {
|
|
|
61
62
|
await fs.writeFile(filePath, contents);
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
|
-
};
|
|
65
|
+
});
|
|
65
66
|
//# sourceMappingURL=install-snapshot.js.map
|
|
66
|
-
//# debugId=
|
|
67
|
+
//# debugId=58ec3f16-267a-5a31-abd2-df46bb82b716
|