@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,8 +4,9 @@
|
|
|
4
4
|
* Implements append-only history and replay behavior for Replay.
|
|
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]="b0230e20-93c4-531c-9cc1-85f85c1def7a")}catch(e){}}();
|
|
8
8
|
import jsonPatch from "fast-json-patch";
|
|
9
|
+
import { findHistoryIdentityDiscontinuities } from "./identity.js";
|
|
9
10
|
import { ITEM_METADATA_KEY_ORDER } from "../shared/constants.js";
|
|
10
11
|
import { canonicalDocument } from "../item/item-format.js";
|
|
11
12
|
import { toItemRecord } from "../item/item-record.js";
|
|
@@ -190,13 +191,12 @@ function assertHistoryEntryIntegrity(entry, index) {
|
|
|
190
191
|
throw new TypeError(`${integrityError}:entry_${index + 1}`);
|
|
191
192
|
}
|
|
192
193
|
}
|
|
193
|
-
/** Deterministically verify a history chain: each entry's before_hash must equal the prior replayed after_hash, the patch must strictly apply, and the recorded after_hash must equal the replayed result. */
|
|
194
194
|
/** Verify a chain and report the explicit or auto-detected item hash epoch. */
|
|
195
195
|
export function verifyHistoryChainWithVersion(entries) {
|
|
196
196
|
let replay = cloneEmptyReplayDocument();
|
|
197
197
|
let detectedVersion;
|
|
198
198
|
let authoritativeExplicitVersion;
|
|
199
|
-
const errors =
|
|
199
|
+
const errors = findHistoryIdentityDiscontinuities(entries).map((finding) => `verify_failed:duplicate_create:entry_${finding.repeated_create_index}:prior_${finding.prior_genesis_index}`);
|
|
200
200
|
for (let index = 0; index < entries.length; index += 1) {
|
|
201
201
|
const entry = entries[index];
|
|
202
202
|
const explicitVersion = entry.item_hash_version;
|
|
@@ -437,4 +437,4 @@ export function historyEntriesToRaw(entries) {
|
|
|
437
437
|
return `${entries.map((entry) => JSON.stringify(entry)).join("\n")}\n`;
|
|
438
438
|
}
|
|
439
439
|
//# sourceMappingURL=replay.js.map
|
|
440
|
-
//# debugId=
|
|
440
|
+
//# debugId=b0230e20-93c4-531c-9cc1-85f85c1def7a
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/history/version-address
|
|
3
|
+
* Stable ordinal addressing for streams whose retained prefix is a checkpoint.
|
|
4
|
+
*/
|
|
5
|
+
import type { HistoryEntry } from "../../types/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Return the number added to physical one-based positions to obtain durable
|
|
8
|
+
* version addresses. Legacy checkpoints cannot prove their original ordinal;
|
|
9
|
+
* refusing them prevents silently selecting a different historical state.
|
|
10
|
+
*/
|
|
11
|
+
export declare function historyVersionOffset(history: readonly HistoryEntry[], allowUnknown: true): number | null;
|
|
12
|
+
/** Resolve a required durable offset, refusing ambiguous legacy checkpoints. */
|
|
13
|
+
export declare function historyVersionOffset(history: readonly HistoryEntry[], allowUnknown?: false): number;
|
|
@@ -0,0 +1,33 @@
|
|
|
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]="7ad4e6c0-7545-51cb-9af7-4ba1ad4c4758")}catch(e){}}();
|
|
3
|
+
import { EXIT_CODE } from "../shared/constants.js";
|
|
4
|
+
import { PmCliError } from "../shared/errors.js";
|
|
5
|
+
/** Resolve the checkpoint offset with an explicit opt-in for unknown legacy addresses. */
|
|
6
|
+
export function historyVersionOffset(history, allowUnknown = false) {
|
|
7
|
+
const first = history[0];
|
|
8
|
+
if (first?.op !== "history_compact_baseline")
|
|
9
|
+
return 0;
|
|
10
|
+
const receipt = first.context?.history_compaction;
|
|
11
|
+
const offset = typeof receipt === "object" &&
|
|
12
|
+
receipt !== null &&
|
|
13
|
+
"version_offset" in receipt
|
|
14
|
+
? receipt.version_offset
|
|
15
|
+
: undefined;
|
|
16
|
+
if (typeof offset === "number" &&
|
|
17
|
+
Number.isSafeInteger(offset) &&
|
|
18
|
+
offset >= 0 &&
|
|
19
|
+
Number.isSafeInteger(offset + history.length)) {
|
|
20
|
+
return offset;
|
|
21
|
+
}
|
|
22
|
+
if (allowUnknown)
|
|
23
|
+
return null;
|
|
24
|
+
throw new PmCliError("This compacted stream has no trustworthy version offset; numeric history addresses are unavailable.", EXIT_CODE.USAGE, {
|
|
25
|
+
code: "history_version_mapping_unavailable",
|
|
26
|
+
required: "Use a retained timestamp or recover the pre-compaction stream from version control.",
|
|
27
|
+
nextSteps: [
|
|
28
|
+
"Run pm history <id> --full to inspect the retained timestamps and checkpoint evidence.",
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=version-address.js.map
|
|
33
|
+
//# debugId=7ad4e6c0-7545-51cb-9af7-4ba1ad4c4758
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { RuntimeStatusRegistry } from "../schema/runtime-schema.js";
|
|
2
2
|
import type { ItemMetadata, ItemStatus } from "../../types/index.js";
|
|
3
|
+
import { type ItemTypeRegistry } from "./type-registry.js";
|
|
4
|
+
/** Resolve dispatch semantics once for SDK callers, honoring custom and extension type aliases before built-in defaults. */
|
|
5
|
+
export declare function resolveItemExecutionRole(type: string, registry?: ItemTypeRegistry): "agent" | "human" | "gate";
|
|
3
6
|
/** Built-in ordering kinds that must remain reachable by blocker resolution. */
|
|
4
7
|
export declare const ACTIONABILITY_ORDERING_KINDS: readonly string[];
|
|
5
8
|
/** Collects the blocker item ids declared by an item: the legacy scalar `blocked_by` field plus every `blocked_by` dependency edge. Ids are trimmed, de-duplicated, and returned in stable lexicographic order. This is the single source of truth for "what must close before this item can proceed", shared by `pm next` readiness classification and the close-time auto-unblock sweep. */
|
|
@@ -54,11 +57,28 @@ export interface ActionabilityReport {
|
|
|
54
57
|
ready: ActionableEntry[];
|
|
55
58
|
/** Active leaves with at least one open blocker — waiting to become ready. */
|
|
56
59
|
blocked: ActionableEntry[];
|
|
60
|
+
/** Active containers with unresolved descendants, including their blocker evidence. */
|
|
61
|
+
containers: ActionableEntry[];
|
|
62
|
+
/** Unblocked leaf work that requires a human decision. */
|
|
63
|
+
decisions: ActionableEntry[];
|
|
64
|
+
/** Unblocked leaf outcome gates held out of automatic dispatch. */
|
|
65
|
+
gates: ActionableEntry[];
|
|
57
66
|
/** Active candidates considered before the leaf/blocker split. */
|
|
58
67
|
active_count: number;
|
|
59
68
|
/** Active candidates skipped because they still have open descendants. */
|
|
60
69
|
container_count: number;
|
|
61
70
|
}
|
|
71
|
+
/** Explicit dispatch opt-ins; dependency and lifecycle blocking always remain enforced. */
|
|
72
|
+
export interface ActionabilitySelectionOptions {
|
|
73
|
+
/** Include human decision work in the executable selection. */
|
|
74
|
+
includeDecisions?: boolean;
|
|
75
|
+
/** Include outcome gates in the executable selection. */
|
|
76
|
+
includeGates?: boolean;
|
|
77
|
+
/** Include containers whose descendants are still unfinished. */
|
|
78
|
+
includeContainers?: boolean;
|
|
79
|
+
}
|
|
80
|
+
/** Select dispatch candidates from a classified report while retaining held-out worklists. Ownership and ranking remain caller responsibilities. */
|
|
81
|
+
export declare function selectActionableEntries(report: ActionabilityReport, statusRegistry: RuntimeStatusRegistry, options?: ActionabilitySelectionOptions, typeRegistry?: ItemTypeRegistry): Pick<ActionabilityReport, "ready" | "decisions" | "gates">;
|
|
62
82
|
/**
|
|
63
83
|
* Partitions a candidate set into ready vs blocked leaf work using the corpus to
|
|
64
84
|
* resolve blockers, descendants, and downstream dependents.
|
|
@@ -70,4 +90,4 @@ export interface ActionabilityReport {
|
|
|
70
90
|
* blockers and the non-terminal items it would unblock. Returned lists preserve
|
|
71
91
|
* the candidate order so the caller can apply its own ranking.
|
|
72
92
|
*/
|
|
73
|
-
export declare function computeActionabilityReport(candidates: ItemMetadata[], corpus: ItemMetadata[], statusRegistry: RuntimeStatusRegistry): ActionabilityReport;
|
|
93
|
+
export declare function computeActionabilityReport(candidates: ItemMetadata[], corpus: ItemMetadata[], statusRegistry: RuntimeStatusRegistry, typeRegistry?: ItemTypeRegistry): ActionabilityReport;
|
|
@@ -10,9 +10,15 @@
|
|
|
10
10
|
* `blocked_by` resolution a single source of truth.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
!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]="
|
|
13
|
+
!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]="7d98ca40-57e8-5afe-8e9d-b694da0130d1")}catch(e){}}();
|
|
14
14
|
import { isTerminalStatus, normalizeStatusForRegistry } from "./status.js";
|
|
15
|
+
import { BUILTIN_ITEM_EXECUTION_ROLES, resolveTypeDefinition } from "./type-registry.js";
|
|
15
16
|
import { isExternalDependencyReference, isExternalDependencySourceKind, } from "./dependency-reference.js";
|
|
17
|
+
/** Resolve dispatch semantics once for SDK callers, honoring custom and extension type aliases before built-in defaults. */
|
|
18
|
+
export function resolveItemExecutionRole(type, registry) {
|
|
19
|
+
const definition = registry === undefined ? undefined : resolveTypeDefinition(type, registry);
|
|
20
|
+
return definition?.execution_role ?? BUILTIN_ITEM_EXECUTION_ROLES[type.trim().toLowerCase()] ?? "agent";
|
|
21
|
+
}
|
|
16
22
|
/** Dependency kind that marks "this item is blocked by the referenced item". */
|
|
17
23
|
const BLOCKED_BY_DEPENDENCY_KIND = "blocked_by";
|
|
18
24
|
/** Reverse dependency kind that marks "this item blocks the referenced item". */
|
|
@@ -177,6 +183,24 @@ export function collectDependencyBlockedIds(corpus, statusRegistry) {
|
|
|
177
183
|
}
|
|
178
184
|
return blocked;
|
|
179
185
|
}
|
|
186
|
+
/** Select dispatch candidates from a classified report while retaining held-out worklists. Ownership and ranking remain caller responsibilities. */
|
|
187
|
+
export function selectActionableEntries(report, statusRegistry, options = {}, typeRegistry) {
|
|
188
|
+
const candidates = [...report.ready, ...report.decisions, ...report.gates];
|
|
189
|
+
if (options.includeContainers === true) {
|
|
190
|
+
candidates.push(...report.containers.filter((entry) => entry.open_blockers.length === 0 && !statusRegistry.blocked_statuses.has(normalizeStatusForRegistry(entry.item.status, statusRegistry))));
|
|
191
|
+
}
|
|
192
|
+
const selected = { ready: [], decisions: [], gates: [] };
|
|
193
|
+
for (const entry of candidates) {
|
|
194
|
+
const role = resolveItemExecutionRole(entry.item.type, typeRegistry);
|
|
195
|
+
if (role === "human" && options.includeDecisions !== true)
|
|
196
|
+
selected.decisions.push(entry);
|
|
197
|
+
else if (role === "gate" && options.includeGates !== true)
|
|
198
|
+
selected.gates.push(entry);
|
|
199
|
+
else
|
|
200
|
+
selected.ready.push(entry);
|
|
201
|
+
}
|
|
202
|
+
return selected;
|
|
203
|
+
}
|
|
180
204
|
/** Resolves the registry's active status set, falling back to just the canonical open status when a custom schema declares none — the same safety net `pm context` applies so the report never misclassifies every item as inactive. */
|
|
181
205
|
function resolveActiveStatusSet(statusRegistry) {
|
|
182
206
|
/* c8 ignore start -- fallback applies only to custom schemas that intentionally define zero active statuses */
|
|
@@ -242,7 +266,7 @@ function indexCorpus(corpus) {
|
|
|
242
266
|
* blockers and the non-terminal items it would unblock. Returned lists preserve
|
|
243
267
|
* the candidate order so the caller can apply its own ranking.
|
|
244
268
|
*/
|
|
245
|
-
export function computeActionabilityReport(candidates, corpus, statusRegistry) {
|
|
269
|
+
export function computeActionabilityReport(candidates, corpus, statusRegistry, typeRegistry) {
|
|
246
270
|
const { itemsById, childrenByParent, blockedByReverse, blockerIdsByItem } = indexCorpus(corpus);
|
|
247
271
|
const activeStatuses = new Set([
|
|
248
272
|
...resolveActiveStatusSet(statusRegistry),
|
|
@@ -255,16 +279,14 @@ export function computeActionabilityReport(candidates, corpus, statusRegistry) {
|
|
|
255
279
|
.map((entry) => normalizeItemId(entry.id)));
|
|
256
280
|
const ready = [];
|
|
257
281
|
const blocked = [];
|
|
282
|
+
const containers = [];
|
|
283
|
+
const decisions = [];
|
|
284
|
+
const gates = [];
|
|
258
285
|
let activeCount = 0;
|
|
259
|
-
let containerCount = 0;
|
|
260
286
|
for (const item of candidates) {
|
|
261
287
|
if (!activeStatuses.has(normalizeStatusForRegistry(item.status, statusRegistry)))
|
|
262
288
|
continue;
|
|
263
289
|
activeCount += 1;
|
|
264
|
-
if (hasOpenDescendant(item.id, childrenByParent, statusRegistry)) {
|
|
265
|
-
containerCount += 1;
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
290
|
const openBlockers = resolveItemBlockersWithIndex(item, itemsById, statusRegistry, blockerIdsByItem).filter((blocker) => !blocker.resolved);
|
|
269
291
|
const unblocks = (blockedByReverse.get(normalizeItemId(item.id)) ?? [])
|
|
270
292
|
.filter((dependentId) => nonTerminalIds.has(normalizeItemId(dependentId)))
|
|
@@ -274,9 +296,19 @@ export function computeActionabilityReport(candidates, corpus, statusRegistry) {
|
|
|
274
296
|
open_blockers: openBlockers,
|
|
275
297
|
unblocks,
|
|
276
298
|
};
|
|
299
|
+
if (hasOpenDescendant(item.id, childrenByParent, statusRegistry)) {
|
|
300
|
+
containers.push(entry);
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
277
303
|
const lifecycleBlocked = statusRegistry.blocked_statuses.has(normalizeStatusForRegistry(item.status, statusRegistry));
|
|
278
304
|
if (openBlockers.length === 0 && !lifecycleBlocked) {
|
|
279
|
-
|
|
305
|
+
const role = resolveItemExecutionRole(item.type, typeRegistry);
|
|
306
|
+
if (role === "human")
|
|
307
|
+
decisions.push(entry);
|
|
308
|
+
else if (role === "gate")
|
|
309
|
+
gates.push(entry);
|
|
310
|
+
else
|
|
311
|
+
ready.push(entry);
|
|
280
312
|
}
|
|
281
313
|
else {
|
|
282
314
|
blocked.push(entry);
|
|
@@ -285,9 +317,12 @@ export function computeActionabilityReport(candidates, corpus, statusRegistry) {
|
|
|
285
317
|
return {
|
|
286
318
|
ready,
|
|
287
319
|
blocked,
|
|
320
|
+
containers,
|
|
321
|
+
decisions,
|
|
322
|
+
gates,
|
|
288
323
|
active_count: activeCount,
|
|
289
|
-
container_count:
|
|
324
|
+
container_count: containers.length,
|
|
290
325
|
};
|
|
291
326
|
}
|
|
292
327
|
//# sourceMappingURL=actionability.js.map
|
|
293
|
-
//# debugId=
|
|
328
|
+
//# debugId=7d98ca40-57e8-5afe-8e9d-b694da0130d1
|
package/dist/core/item/id.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Defines item parsing, formatting, and lifecycle helpers for Id.
|
|
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]="04f02467-a4ee-5616-9fbf-3df1141efccf")}catch(e){}}();
|
|
8
8
|
import crypto from "node:crypto";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { TYPE_TO_FOLDER } from "../shared/constants.js";
|
|
@@ -60,11 +60,13 @@ function randomToken(length) {
|
|
|
60
60
|
}
|
|
61
61
|
return token;
|
|
62
62
|
}
|
|
63
|
+
/** Reserve an identity when either a live item path or its retained history exists. */
|
|
63
64
|
async function idExists(pmRoot, id, typeToFolder) {
|
|
64
65
|
const checks = [...new Set(Object.values(typeToFolder))].flatMap((folder) => [
|
|
65
66
|
path.join(pmRoot, folder, `${id}.md`),
|
|
66
67
|
path.join(pmRoot, folder, `${id}.toon`),
|
|
67
68
|
]);
|
|
69
|
+
checks.push(path.join(pmRoot, "history", `${id}.jsonl`));
|
|
68
70
|
return (await Promise.all(checks.map((target) => pathExists(target)))).some(Boolean);
|
|
69
71
|
}
|
|
70
72
|
/** Bounds accepted for the configurable random id token length (`ids.token_length`). */
|
|
@@ -95,8 +97,10 @@ export async function generateItemId(pmRoot, prefix, options = {}) {
|
|
|
95
97
|
while (tokenLength <= maxTokenLength) {
|
|
96
98
|
for (let i = 0; i < 32; i += 1) {
|
|
97
99
|
const id = `${normalizePrefix(prefix)}${randomToken(tokenLength)}`;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
const occupied = await (options.probeExisting === false
|
|
101
|
+
? pathExists(path.join(pmRoot, "history", `${id}.jsonl`))
|
|
102
|
+
: idExists(pmRoot, id, options.typeToFolder ?? TYPE_TO_FOLDER));
|
|
103
|
+
if (!occupied) {
|
|
100
104
|
return id;
|
|
101
105
|
}
|
|
102
106
|
attempts += 1;
|
|
@@ -106,4 +110,4 @@ export async function generateItemId(pmRoot, prefix, options = {}) {
|
|
|
106
110
|
throw new Error(`Unable to generate unique id after ${attempts} attempts`);
|
|
107
111
|
}
|
|
108
112
|
//# sourceMappingURL=id.js.map
|
|
109
|
-
//# debugId=
|
|
113
|
+
//# debugId=04f02467-a4ee-5616-9fbf-3df1141efccf
|
|
@@ -38,6 +38,8 @@ export interface NormalizeItemTypeDefinitionOptions {
|
|
|
38
38
|
/** How to resolve a raw policy `command` value (defaults to {@link keepPolicyCommand}). */
|
|
39
39
|
resolvePolicyCommand?: ResolvePolicyCommand;
|
|
40
40
|
}
|
|
41
|
+
/** Validate an execution role before a settings or extension definition enters scheduling. Unknown values fail instead of silently enabling dispatch. */
|
|
42
|
+
export declare function parseItemExecutionRole(value: unknown): ItemTypeDefinition["execution_role"];
|
|
41
43
|
/**
|
|
42
44
|
* Normalize a full {@link ItemTypeDefinition}, returning null when the name is blank.
|
|
43
45
|
*
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
/** Dedupe + sort a string list: trim, drop blanks, unique, locale-sorted. */
|
|
17
17
|
|
|
18
|
-
!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]="
|
|
18
|
+
!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]="f02cb2e7-2d5f-5cc8-8a60-18db78b50da0")}catch(e){}}();
|
|
19
19
|
export function normalizeItemTypeStringList(values) {
|
|
20
20
|
return [
|
|
21
21
|
...new Set((values ?? [])
|
|
@@ -85,6 +85,12 @@ function optionalNonEmptyString(value) {
|
|
|
85
85
|
const normalized = value?.trim();
|
|
86
86
|
return normalized && normalized.length > 0 ? normalized : undefined;
|
|
87
87
|
}
|
|
88
|
+
/** Validate an execution role before a settings or extension definition enters scheduling. Unknown values fail instead of silently enabling dispatch. */
|
|
89
|
+
export function parseItemExecutionRole(value) {
|
|
90
|
+
if (value === undefined || value === "agent" || value === "human" || value === "gate")
|
|
91
|
+
return value;
|
|
92
|
+
throw new Error("Item type execution_role must be agent, human, or gate.");
|
|
93
|
+
}
|
|
88
94
|
/**
|
|
89
95
|
* Normalize a full {@link ItemTypeDefinition}, returning null when the name is blank.
|
|
90
96
|
*
|
|
@@ -113,6 +119,7 @@ export function normalizeItemTypeDefinition(definition, options = {}) {
|
|
|
113
119
|
name,
|
|
114
120
|
description: optionalNonEmptyString(definition.description),
|
|
115
121
|
default_status: optionalNonEmptyString(definition.default_status),
|
|
122
|
+
...(definition.execution_role === undefined ? {} : { execution_role: parseItemExecutionRole(definition.execution_role) }),
|
|
116
123
|
folder: optionalNonEmptyString(definition.folder),
|
|
117
124
|
aliases: aliases.length > 0 ? aliases : undefined,
|
|
118
125
|
required_create_fields: normalizeOptionalStringList(definition.required_create_fields, hasRequiredCreateFields),
|
|
@@ -124,4 +131,4 @@ export function normalizeItemTypeDefinition(definition, options = {}) {
|
|
|
124
131
|
};
|
|
125
132
|
}
|
|
126
133
|
//# sourceMappingURL=item-type-definition.js.map
|
|
127
|
-
//# debugId=
|
|
134
|
+
//# debugId=f02cb2e7-2d5f-5cc8-8a60-18db78b50da0
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ExtensionRegistrationRegistry } from "../extensions/loader.js";
|
|
2
|
-
import type { ItemTypeCommandOptionPolicy, ItemTypeOptionDefinition, PmSettings } from "../../types/index.js";
|
|
2
|
+
import type { ItemTypeCommandOptionPolicy, ItemTypeDefinition, ItemTypeOptionDefinition, PmSettings } from "../../types/index.js";
|
|
3
|
+
/** Default dispatch roles for built-in types whose work requires human input or outcome verification. Custom definitions can override these through the same registry. */
|
|
4
|
+
export declare const BUILTIN_ITEM_EXECUTION_ROLES: Readonly<Record<string, "human" | "gate">>;
|
|
3
5
|
/** Fallback required create fields used when callers do not provide an override. */
|
|
4
6
|
export declare const DEFAULT_REQUIRED_CREATE_FIELDS: readonly ["title", "description", "status", "priority", "tags", "body", "deadline", "estimatedMinutes", "acceptanceCriteria", "author", "message", "assignee"];
|
|
5
7
|
/** Fallback required create repeatables used when callers do not provide an override. */
|
|
@@ -31,6 +33,8 @@ export interface ResolvedItemTypeDefinition {
|
|
|
31
33
|
aliases: string[];
|
|
32
34
|
/** Optional per-type status applied at create time when `--status` is omitted. */
|
|
33
35
|
default_status?: string;
|
|
36
|
+
/** Effective dispatch role; absent legacy definitions are resolved through the built-in defaults. */
|
|
37
|
+
execution_role?: ItemTypeDefinition["execution_role"];
|
|
34
38
|
/** Value that configures or reports required create fields for this contract. */
|
|
35
39
|
required_create_fields: string[];
|
|
36
40
|
/** Value that configures or reports required create repeatables for this contract. */
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* Defines item parsing, formatting, and lifecycle helpers for Type Registry.
|
|
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]="506efdc7-b04e-5023-ab59-57ede87558f9")}catch(e){}}();
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { TYPE_TO_FOLDER } from "../shared/constants.js";
|
|
10
10
|
import { ITEM_TYPE_VALUES } from "../../types/index.js";
|
|
11
|
-
import { normalizeItemTypeDefinition as normalizeSharedItemTypeDefinition, normalizeItemTypeStringList, strictPolicyCommand, } from "./item-type-definition.js";
|
|
11
|
+
import { normalizeItemTypeDefinition as normalizeSharedItemTypeDefinition, normalizeItemTypeStringList, strictPolicyCommand, parseItemExecutionRole, } from "./item-type-definition.js";
|
|
12
|
+
/** Default dispatch roles for built-in types whose work requires human input or outcome verification. Custom definitions can override these through the same registry. */
|
|
13
|
+
export const BUILTIN_ITEM_EXECUTION_ROLES = Object.freeze({ decision: "human", milestone: "gate" });
|
|
12
14
|
/** Fallback required create fields used when callers do not provide an override. */
|
|
13
15
|
export const DEFAULT_REQUIRED_CREATE_FIELDS = [
|
|
14
16
|
"title",
|
|
@@ -421,6 +423,7 @@ function coerceTypeDefinitionFromUnknown(raw) {
|
|
|
421
423
|
name,
|
|
422
424
|
description,
|
|
423
425
|
default_status: defaultStatus,
|
|
426
|
+
execution_role: parseItemExecutionRole(record.execution_role),
|
|
424
427
|
folder,
|
|
425
428
|
aliases: readStringArray(record, "aliases"),
|
|
426
429
|
required_create_fields: readStringArray(record, "required_create_fields"),
|
|
@@ -462,6 +465,7 @@ function buildResolvedTypeDefinition(normalizedDefinition, existing) {
|
|
|
462
465
|
toDefaultFolder(keepName));
|
|
463
466
|
const resolvedDefinition = {
|
|
464
467
|
name: keepName,
|
|
468
|
+
execution_role: normalizedDefinition.execution_role,
|
|
465
469
|
folder,
|
|
466
470
|
aliases: normalizeItemTypeStringList([
|
|
467
471
|
...(existing?.aliases ?? []),
|
|
@@ -488,7 +492,7 @@ function applyTypeDefinitions(source, target) {
|
|
|
488
492
|
}
|
|
489
493
|
const lowerName = normalizedDefinition.name.toLowerCase();
|
|
490
494
|
const existing = target.get(lowerName);
|
|
491
|
-
target.set(lowerName, buildResolvedTypeDefinition(normalizedDefinition, existing));
|
|
495
|
+
target.set(lowerName, buildResolvedTypeDefinition({ ...normalizedDefinition, execution_role: normalizedDefinition.execution_role ?? existing?.execution_role }, existing));
|
|
492
496
|
}
|
|
493
497
|
}
|
|
494
498
|
function collectExtensionTypeDefinitions(registrations) {
|
|
@@ -516,6 +520,7 @@ export function resolveItemTypeRegistry(settings, extensionRegistrations = null)
|
|
|
516
520
|
for (const builtin of ITEM_TYPE_VALUES) {
|
|
517
521
|
byLowerName.set(builtin.toLowerCase(), {
|
|
518
522
|
name: builtin,
|
|
523
|
+
execution_role: BUILTIN_ITEM_EXECUTION_ROLES[builtin.toLowerCase()] ?? "agent",
|
|
519
524
|
folder: TYPE_TO_FOLDER[builtin],
|
|
520
525
|
aliases: [],
|
|
521
526
|
required_create_fields: [...DEFAULT_REQUIRED_CREATE_FIELDS],
|
|
@@ -708,4 +713,4 @@ export function validateTypeOptions(typeName, rawTypeOptions, registry) {
|
|
|
708
713
|
};
|
|
709
714
|
}
|
|
710
715
|
//# sourceMappingURL=type-registry.js.map
|
|
711
|
-
//# debugId=
|
|
716
|
+
//# debugId=506efdc7-b04e-5023-ab59-57ede87558f9
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* MCP server, and returns the original reference unchanged when nothing is compacted.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
!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]="
|
|
22
|
+
!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]="d6a389b0-7a14-56e7-ac2c-17fcdecc7b29")}catch(e){}}();
|
|
23
23
|
const CHANGED_FIELDS_KEY = "changed_fields";
|
|
24
24
|
const CHANGED_FIELD_COUNT_KEY = "changed_field_count";
|
|
25
25
|
const ROWS_KEY = "rows";
|
|
@@ -115,6 +115,7 @@ function projectIdOnlyResult(result) {
|
|
|
115
115
|
}
|
|
116
116
|
: { id };
|
|
117
117
|
}
|
|
118
|
+
/** Project a recognized item mutation to identity and change counts while preserving warnings and executable recovery. */
|
|
118
119
|
function projectCompactMutationEnvelope(result) {
|
|
119
120
|
if (!isPlainObject(result) || !isPlainObject(result.item))
|
|
120
121
|
return null;
|
|
@@ -137,10 +138,15 @@ function projectCompactMutationEnvelope(result) {
|
|
|
137
138
|
: {}),
|
|
138
139
|
changed_field_count: changedFields.length,
|
|
139
140
|
};
|
|
141
|
+
appendCompactMutationEvidence(result, result.item, compact);
|
|
142
|
+
return compact;
|
|
143
|
+
}
|
|
144
|
+
/** Keep lifecycle context, warnings, and executable recovery alongside the compact identity. */
|
|
145
|
+
function appendCompactMutationEvidence(result, item, compact) {
|
|
140
146
|
const closeReason = typeof result.close_reason === "string"
|
|
141
147
|
? result.close_reason
|
|
142
|
-
: typeof
|
|
143
|
-
?
|
|
148
|
+
: typeof item.close_reason === "string"
|
|
149
|
+
? item.close_reason
|
|
144
150
|
: undefined;
|
|
145
151
|
if (closeReason !== undefined)
|
|
146
152
|
compact.close_reason = closeReason;
|
|
@@ -149,7 +155,8 @@ function projectCompactMutationEnvelope(result) {
|
|
|
149
155
|
compact.recurrence = recurrence;
|
|
150
156
|
if (Array.isArray(result.warnings) && result.warnings.length > 0)
|
|
151
157
|
compact.warnings = result.warnings;
|
|
152
|
-
|
|
158
|
+
if (isPlainObject(result.recovery))
|
|
159
|
+
compact.recovery = result.recovery;
|
|
153
160
|
}
|
|
154
161
|
function compactUpdateManyRows(envelope) {
|
|
155
162
|
const rows = isUpdateManyMutationEnvelope(envelope)
|
|
@@ -208,4 +215,4 @@ export function projectMutationResult(result, options = {}) {
|
|
|
208
215
|
return changed ? projected : result;
|
|
209
216
|
}
|
|
210
217
|
//# sourceMappingURL=mutation-projection.js.map
|
|
211
|
-
//# debugId=
|
|
218
|
+
//# debugId=d6a389b0-7a14-56e7-ac2c-17fcdecc7b29
|
|
@@ -53,6 +53,14 @@ export interface PmCliErrorRecoveryPayload {
|
|
|
53
53
|
export interface PmCliErrorContext {
|
|
54
54
|
/** Value that configures or reports code for this contract. */
|
|
55
55
|
code?: string;
|
|
56
|
+
/** Item whose document could not be decoded or parsed. */
|
|
57
|
+
item_id?: string;
|
|
58
|
+
/** Exact filesystem path of the unreadable item document. */
|
|
59
|
+
item_path?: string;
|
|
60
|
+
/** Original document size before decoding or parsing. */
|
|
61
|
+
byte_length?: number;
|
|
62
|
+
/** Whether the original item document contained no bytes. */
|
|
63
|
+
empty?: boolean;
|
|
56
64
|
/** Stable failure class within the operation-specific error code. */
|
|
57
65
|
reason?: string;
|
|
58
66
|
/** Metadata field responsible for a validation failure, when known. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Implements the exported pm cli error runtime abstraction for core/shared/errors.ts. */
|
|
2
2
|
|
|
3
|
-
!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]="
|
|
3
|
+
!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]="9ab4b378-900c-5a2a-9237-b1d8d4f2ae13")}catch(e){}}();
|
|
4
4
|
export class PmCliError extends Error {
|
|
5
5
|
/** Value that configures or reports exit code for this contract. */
|
|
6
6
|
exitCode;
|
|
@@ -18,4 +18,4 @@ export class PmCliError extends Error {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
//# sourceMappingURL=errors.js.map
|
|
21
|
-
//# debugId=
|
|
21
|
+
//# debugId=9ab4b378-900c-5a2a-9237-b1d8d4f2ae13
|
|
@@ -4,13 +4,13 @@
|
|
|
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]="530ad63f-f7c5-52c9-9f81-a74b1cd4c36e")}catch(e){}}();
|
|
8
8
|
import fs from "node:fs/promises";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
11
|
import { createRequire } from "node:module";
|
|
12
12
|
const QUERY_INDEX_FILENAME = "metadata-query-index.sqlite";
|
|
13
|
-
const QUERY_INDEX_VERSION = "
|
|
13
|
+
const QUERY_INDEX_VERSION = "5";
|
|
14
14
|
function loadDatabaseSync(loadModule) {
|
|
15
15
|
try {
|
|
16
16
|
const loaded = loadModule(["node", "sqlite"].join(":"));
|
|
@@ -102,6 +102,7 @@ function writeMetadata(database, key, value) {
|
|
|
102
102
|
.prepare("INSERT INTO metadata(key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value")
|
|
103
103
|
.run(key, value);
|
|
104
104
|
}
|
|
105
|
+
/** Upsert authoritative metadata and replace dependent search, key and linked-file rows in the caller transaction. */
|
|
105
106
|
function insertRow(database, row) {
|
|
106
107
|
const metadata = row.metadata;
|
|
107
108
|
database
|
|
@@ -128,10 +129,12 @@ function insertRow(database, row) {
|
|
|
128
129
|
database
|
|
129
130
|
.prepare("DELETE FROM item_linked_files WHERE item_id = ?")
|
|
130
131
|
.run(metadata.id);
|
|
131
|
-
|
|
132
|
+
// FTS UNINDEXED columns cannot provide identity lookup. Share the items rowid
|
|
133
|
+
// so both rebuilding and incremental maintenance use a single indexed row.
|
|
134
|
+
database.prepare("DELETE FROM item_search WHERE rowid = (SELECT rowid FROM items WHERE id = ?)").run(metadata.id);
|
|
132
135
|
database
|
|
133
|
-
.prepare("INSERT INTO item_search(id, title, description, tags)
|
|
134
|
-
.run(metadata.id, metadata.title, metadata.description, metadata.tags.join(" "));
|
|
136
|
+
.prepare("INSERT INTO item_search(rowid, id, title, description, tags) SELECT rowid, ?, ?, ?, ? FROM items WHERE id = ?")
|
|
137
|
+
.run(metadata.id, metadata.title, metadata.description, metadata.tags.join(" "), metadata.id);
|
|
135
138
|
const insertMetadataKey = database.prepare("INSERT INTO item_metadata_keys(item_id, key) VALUES (?, ?)");
|
|
136
139
|
for (const key of Object.keys(metadata)) {
|
|
137
140
|
insertMetadataKey.run(metadata.id, key);
|
|
@@ -203,13 +206,13 @@ export async function updateItemMetadataQueryIndex(options) {
|
|
|
203
206
|
}
|
|
204
207
|
database.exec("BEGIN IMMEDIATE");
|
|
205
208
|
const deleteByPath = database.prepare("DELETE FROM items WHERE relative_path = ?");
|
|
206
|
-
const
|
|
207
|
-
const
|
|
209
|
+
const findRowidByPath = database.prepare("SELECT rowid FROM items WHERE relative_path = ?");
|
|
210
|
+
const deleteSearchByRowid = database.prepare("DELETE FROM item_search WHERE rowid = ?");
|
|
208
211
|
for (const relativePath of options.deletedRelativePaths ?? []) {
|
|
209
|
-
const deleted =
|
|
212
|
+
const deleted = findRowidByPath.get(relativePath);
|
|
210
213
|
deleteByPath.run(relativePath);
|
|
211
214
|
if (deleted)
|
|
212
|
-
|
|
215
|
+
deleteSearchByRowid.run(deleted.rowid);
|
|
213
216
|
}
|
|
214
217
|
if (options.row)
|
|
215
218
|
insertRow(database, options.row);
|
|
@@ -470,4 +473,4 @@ export const _testOnly = {
|
|
|
470
473
|
},
|
|
471
474
|
};
|
|
472
475
|
//# sourceMappingURL=item-metadata-query-index.js.map
|
|
473
|
-
//# debugId=
|
|
476
|
+
//# debugId=530ad63f-f7c5-52c9-9f81-a74b1cd4c36e
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Logical metadata work, independent of output projection and cache hit rate. */
|
|
2
|
+
export interface ItemMetadataReadWork {
|
|
3
|
+
/** Completed full, light, or body-bearing item-store enumeration calls. */
|
|
4
|
+
enumeration_calls: number;
|
|
5
|
+
/** Metadata rows returned by those calls, counting repeated enumeration. */
|
|
6
|
+
metadata_rows: number;
|
|
7
|
+
}
|
|
8
|
+
/** Record completed enumeration in each enclosing measurement, without retaining item data. */
|
|
9
|
+
export declare function recordItemMetadataEnumeration(rowCount: number): void;
|
|
10
|
+
/**
|
|
11
|
+
* Measure an awaited operation without changing its result or failure semantics.
|
|
12
|
+
* Concurrent roots remain isolated; nested measurements also contribute to their
|
|
13
|
+
* parents. The returned snapshot excludes work completed after the operation.
|
|
14
|
+
* Counters cover filesystem item-store enumeration APIs, not arbitrary host I/O.
|
|
15
|
+
*/
|
|
16
|
+
export declare function measureItemMetadataReadWork<T>(operation: () => T | Promise<T>): Promise<{
|
|
17
|
+
result: T;
|
|
18
|
+
work: Readonly<ItemMetadataReadWork>;
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/store/item-metadata-read-work
|
|
3
|
+
*
|
|
4
|
+
* Measures successful filesystem metadata enumerations within one async SDK
|
|
5
|
+
* operation. Cache hits count too: materializing a cached corpus is still work.
|
|
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]="1cd39e2f-41c7-5005-925d-d4539cda15d3")}catch(e){}}();
|
|
9
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
10
|
+
import { channel } from "node:diagnostics_channel";
|
|
11
|
+
const observers = new AsyncLocalStorage();
|
|
12
|
+
const enumerations = channel("@unbrained/pm-cli/item-metadata-enumeration/v1");
|
|
13
|
+
/** Record completed enumeration in each enclosing measurement, without retaining item data. */
|
|
14
|
+
export function recordItemMetadataEnumeration(rowCount) {
|
|
15
|
+
enumerations.publish(rowCount);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Measure an awaited operation without changing its result or failure semantics.
|
|
19
|
+
* Concurrent roots remain isolated; nested measurements also contribute to their
|
|
20
|
+
* parents. The returned snapshot excludes work completed after the operation.
|
|
21
|
+
* Counters cover filesystem item-store enumeration APIs, not arbitrary host I/O.
|
|
22
|
+
*/
|
|
23
|
+
export async function measureItemMetadataReadWork(operation) {
|
|
24
|
+
const work = { enumeration_calls: 0, metadata_rows: 0 };
|
|
25
|
+
// A named channel crosses the published query/bundled runtime boundary;
|
|
26
|
+
// async membership prevents concurrent roots from counting each other's work.
|
|
27
|
+
/** Count notifications only while this measurement belongs to the active async scope. */
|
|
28
|
+
const observe = (message) => {
|
|
29
|
+
if (observers.getStore()?.includes(work)) {
|
|
30
|
+
work.enumeration_calls += 1;
|
|
31
|
+
work.metadata_rows += message;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
enumerations.subscribe(observe);
|
|
35
|
+
try {
|
|
36
|
+
const result = await observers.run([...(observers.getStore() ?? []), work], operation);
|
|
37
|
+
return { result, work: { ...work } };
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
enumerations.unsubscribe(observe);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=item-metadata-read-work.js.map
|
|
44
|
+
//# debugId=1cd39e2f-41c7-5005-925d-d4539cda15d3
|
|
@@ -25,6 +25,20 @@ export declare function readLocatedItem(item: LocatedItem, options?: {
|
|
|
25
25
|
raw: string;
|
|
26
26
|
document: ItemDocument;
|
|
27
27
|
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Read once and retain a recoverable parse failure beside its exact text snapshot.
|
|
30
|
+
* Filesystem and merge-conflict errors still throw; callers must explicitly
|
|
31
|
+
* reconstruct an invalid document before performing any mutation.
|
|
32
|
+
*/
|
|
33
|
+
export declare function readLocatedItemSnapshot(item: LocatedItem, options?: Parameters<typeof readLocatedItem>[1]): Promise<{
|
|
34
|
+
raw: string;
|
|
35
|
+
document: ItemDocument;
|
|
36
|
+
error: null;
|
|
37
|
+
} | {
|
|
38
|
+
raw: string;
|
|
39
|
+
document: null;
|
|
40
|
+
error: PmCliError;
|
|
41
|
+
}>;
|
|
28
42
|
/** Implements list all item metadata for the public runtime surface of this module. */
|
|
29
43
|
export declare function listAllItemMetadata(pmRoot: string, preferredFormat?: ItemFormat, typeToFolder?: Record<string, string>, warnings?: string[], schema?: RuntimeSchemaSettings): Promise<ItemMetadata[]>;
|
|
30
44
|
/**
|