@unbrained/pm-cli 2026.8.30 → 2026.9.1
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 +1 -1
- package/.agents/skills/pm-developer/SKILL.md +1 -1
- package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +2 -2
- package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +1 -1
- package/.agents/skills/pm-developer/references/TOKEN_BUDGETS.md +1 -1
- package/.agents/skills/pm-extensions/SKILL.md +2 -2
- package/.agents/skills/pm-extensions/references/AUTHORING.md +1 -1
- package/.agents/skills/pm-extensions/references/LIFECYCLE.md +1 -1
- package/.agents/skills/pm-sdk/SKILL.md +1 -1
- package/.agents/skills/pm-user/SKILL.md +2 -2
- package/.agents/skills/pm-user/references/WORKFLOWS.md +2 -2
- package/.claude-plugin/marketplace.json +2 -2
- package/AGENTS.md +16 -14
- package/CHANGELOG.md +41 -6
- package/README.md +3 -3
- package/dist/cli/commands/merge.d.ts +1 -1
- package/dist/cli/commands/merge.js +3 -3
- package/dist/cli/register-list-query.js +32 -17
- package/dist/cli/register-mutation.js +8 -5
- package/dist/cli/register-operations.d.ts +2 -0
- package/dist/cli/register-operations.js +20 -9
- package/dist/cli-bundle/bundle-manifest.json +144 -144
- package/dist/cli-bundle/chunks/{chunk-CMIEDWAY.js → chunk-2MC2LCXZ.js} +41 -41
- package/dist/cli-bundle/chunks/{chunk-WS2GJQVG.js → chunk-3WICXLVT.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-7SKMLSMX.js → chunk-6XIIGE7U.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-ALKKAUFN.js +35 -0
- package/dist/cli-bundle/chunks/{chunk-MTTKAUBX.js → chunk-DTGWEL23.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-GOACULJW.js +13 -0
- package/dist/cli-bundle/chunks/chunk-NOPL37X4.js +205 -0
- package/dist/cli-bundle/chunks/{chunk-2UETTHY6.js → chunk-TAG4VC22.js} +30 -30
- package/dist/cli-bundle/chunks/{chunk-3TEF3HM5.js → chunk-U45JXJCC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TGNAA66W.js → chunk-X4RCGLTX.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-2MKLQL2E.js → chunk-Y7VOMSZT.js} +2 -2
- package/dist/cli-bundle/chunks/{register-list-query-OMKJ5ONN.js → register-list-query-XYNX4ASQ.js} +11 -11
- package/dist/cli-bundle/chunks/register-mutation-2MVLRS3J.js +20 -0
- package/dist/cli-bundle/chunks/register-operations-WCIDXBU3.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-GLQ5SYV3.js → register-setup-KVNC5KPL.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-HVQ22RC4.js → chunk-2FEZ5SKM.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-Y3JJXRVK.js → chunk-4O4CJAR6.js} +5 -5
- package/dist/cli-bundle/focused-chunks/chunk-7VATS5QY.js +16 -0
- package/dist/cli-bundle/focused-chunks/{chunk-LYFWQMVC.js → chunk-BEVHCEWG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-TDK3OCX3.js → chunk-FWPLDEXF.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-JEFKLWMM.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-JZYPPMXF.js → chunk-KB5OFSFD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-73EDXGYE.js → chunk-MKHG3T76.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-3AVAWVZA.js → chunk-PF3E6Q36.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-AD6ULRAF.js → chunk-QDFJIRKN.js} +4 -4
- package/dist/cli-bundle/focused-chunks/{chunk-RKOKG43G.js → chunk-RMRCQPWU.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-XXOWRJZ5.js → chunk-S4U5CN5Q.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-THEPQMLX.js → chunk-SVXJYD6G.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-T2LXXSOD.js +158 -0
- package/dist/cli-bundle/focused-chunks/chunk-Y6JJIX6I.js +51 -0
- package/dist/cli-bundle/main.js +2 -2
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +1 -1
- package/dist/cli-bundle/sdk-core.js +27 -27
- 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 +33 -33
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +10 -10
- package/dist/core/history/drift-scan.js +6 -6
- package/dist/core/history/history.d.ts +6 -0
- package/dist/core/history/history.js +47 -5
- package/dist/core/history/replay.d.ts +12 -1
- package/dist/core/history/replay.js +60 -39
- package/dist/core/schema/runtime-schema.d.ts +4 -0
- package/dist/core/schema/runtime-schema.js +60 -48
- package/dist/core/schema/status-defs-file.js +5 -2
- package/dist/mcp/legacy-adapter.d.ts +11 -2
- package/dist/mcp/legacy-adapter.js +26 -12
- package/dist/mcp/server.d.ts +2 -2
- package/dist/mcp/server.js +78 -15
- package/dist/mcp/tool-definitions.js +56 -2
- package/dist/sdk/agent-capability-contracts.js +4 -2
- package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
- package/dist/sdk/cli-contracts/flag-contracts.js +6 -2
- package/dist/sdk/cli-contracts/grammar-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts/grammar-contracts.js +12 -2
- package/dist/sdk/cli-contracts/runtime-contracts.js +3 -2
- package/dist/sdk/cli-contracts/tool-schema.js +11 -3
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +14 -2
- package/dist/sdk/governance/health.js +17 -6
- package/dist/sdk/governance/status-role-diagnostics.d.ts +27 -0
- package/dist/sdk/governance/status-role-diagnostics.js +36 -0
- package/dist/sdk/governance/validate-normalization.d.ts +6 -0
- package/dist/sdk/governance/validate-normalization.js +37 -0
- package/dist/sdk/governance/validate.d.ts +1 -1
- package/dist/sdk/governance/validate.js +20 -35
- package/dist/sdk/governance/workspace-position.d.ts +69 -0
- package/dist/sdk/governance/workspace-position.js +164 -0
- package/dist/sdk/governance.d.ts +2 -0
- package/dist/sdk/governance.js +4 -2
- package/dist/sdk/history-read.js +14 -6
- package/dist/sdk/history-repair.js +17 -10
- package/dist/sdk/index.d.ts +2 -1
- package/dist/sdk/index.js +4 -3
- package/dist/sdk/init-agent-guidance.js +4 -4
- package/dist/sdk/lifecycle/update.js +23 -10
- package/dist/sdk/mcp/discovery.d.ts +152 -0
- package/dist/sdk/mcp/discovery.js +495 -0
- package/dist/sdk/mcp/protocol.d.ts +10 -2
- package/dist/sdk/mcp/protocol.js +15 -4
- package/dist/sdk/merge/index.d.ts +1 -1
- package/dist/sdk/merge/index.js +3 -3
- package/dist/sdk/merge/receipts.d.ts +27 -1
- package/dist/sdk/merge/receipts.js +27 -8
- package/dist/sdk/merge/three-way.d.ts +3 -1
- package/dist/sdk/merge/three-way.js +9 -7
- package/dist/sdk/query/context.js +11 -14
- package/dist/sdk/query/list.d.ts +2 -0
- package/dist/sdk/query/list.js +33 -12
- package/dist/sdk/runtime-extended-actions.js +10 -6
- package/dist/sdk/schema.js +12 -2
- package/dist/sdk/test/execution.d.ts +15 -0
- package/dist/sdk/test/execution.js +35 -27
- package/docs/AGENT_GUIDE.md +12 -4
- package/docs/AGENT_PROVENANCE_ADR.md +1 -1
- package/docs/AGENT_RUNTIME_PRIMITIVES.md +2 -2
- package/docs/ARCHITECTURE.md +5 -0
- package/docs/CLAUDE_CODE_PLUGIN.md +5 -5
- package/docs/COMMANDS.md +12 -12
- package/docs/CONFIGURATION.md +1 -1
- package/docs/CONTEXT_RECOVERY_PRIMITIVES.md +14 -5
- package/docs/DEFECT_RECURRENCE.md +2 -0
- package/docs/MCP_2026_07_28.md +33 -9
- package/docs/MCP_2026_07_28_CONFORMANCE.md +1 -0
- package/docs/MCP_CAPABILITY_SURFACES.md +7 -1
- package/docs/MCP_REMOTE_TRANSPORT_SECURITY.md +15 -3
- package/docs/MERGE_SAFETY.md +30 -2
- package/docs/ONBOARDING.md +1 -1
- package/docs/OUTPUT_TOKEN_ACCOUNTING.md +5 -3
- package/docs/PROGRESSIVE_TOOL_DISCOVERY.md +42 -0
- package/docs/README.md +3 -1
- package/docs/READ_OUTPUT_CONTRACTS.md +1 -1
- package/docs/RECURRENCE_RECOVERY_CONTRACTS.md +1 -1
- package/docs/SDK.md +3 -3
- package/docs/TESTING.md +23 -14
- package/docs/WORKSPACE_POSITION_AND_LIFECYCLE.md +113 -0
- package/docs/agent-task-token-baseline.json +157 -3
- package/docs/agent-task-transcripts.json +143 -0
- package/docs/examples/policy-restricted-extension/README.md +2 -2
- package/docs/examples/starter-extension/README.md +1 -1
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +4 -3
- package/docs/performance/cli-transport-overhead.md +8 -6
- package/marketplace.json +2 -2
- package/package.json +4 -4
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/README.md +4 -3
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/sdk/public-surface.json +314 -10
- package/dist/cli-bundle/chunks/chunk-7X6OZEIV.js +0 -34
- package/dist/cli-bundle/chunks/chunk-GNWPTEBW.js +0 -205
- package/dist/cli-bundle/chunks/chunk-N6OR6FAR.js +0 -13
- package/dist/cli-bundle/chunks/register-mutation-QBSNCOY3.js +0 -20
- package/dist/cli-bundle/chunks/register-operations-UC77FQZC.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-3UMBF26I.js +0 -158
- package/dist/cli-bundle/focused-chunks/chunk-AXZ5AJAF.js +0 -50
- package/dist/cli-bundle/focused-chunks/chunk-G6PATS5E.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-LLNTHF5X.js +0 -2
|
@@ -1,14 +1,14 @@
|
|
|
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]="1c6c65ef-115b-50e2-815e-84f6e91158cd")}catch(e){}}();
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { getHistoryPath } from "../store/paths.js";
|
|
7
7
|
import { isFileMissingError, writeFileAtomic } from "../fs/fs-utils.js";
|
|
8
|
-
import { CURRENT_HISTORY_ITEM_HASH_VERSION, SUPPORTED_HISTORY_ITEM_HASH_VERSIONS,
|
|
8
|
+
import { CURRENT_HISTORY_ITEM_HASH_VERSION, SUPPORTED_HISTORY_ITEM_HASH_VERSIONS, hashDocumentVerificationCandidates, } from "./history.js";
|
|
9
9
|
import { verifyHistoryChainWithVersion } from "./replay.js";
|
|
10
10
|
import { getWorkspaceHistoryPath, inspectWorkspaceHistoryState, WORKSPACE_HISTORY_ID, } from "./workspace-history.js";
|
|
11
|
-
const DRIFT_CACHE_VERSION =
|
|
11
|
+
const DRIFT_CACHE_VERSION = 9;
|
|
12
12
|
const DRIFT_CACHE_FILENAME = "history-drift-cache.json";
|
|
13
13
|
function getDriftCachePath(pmRoot) {
|
|
14
14
|
return path.join(pmRoot, "runtime", DRIFT_CACHE_FILENAME);
|
|
@@ -237,8 +237,8 @@ async function scanItemHistory(pmRoot, item, cache, accumulator) {
|
|
|
237
237
|
const { body, ...itemMetadata } = item;
|
|
238
238
|
if (!resolved.verification.latestHashComparable)
|
|
239
239
|
return resolved.cacheDirty;
|
|
240
|
-
const
|
|
241
|
-
if (
|
|
240
|
+
const currentHashes = hashDocumentVerificationCandidates({ metadata: itemMetadata, body }, resolved.verification.itemHashVersion);
|
|
241
|
+
if (!currentHashes.includes(resolved.verification.latestAfterHash))
|
|
242
242
|
accumulator.hashMismatches.push(item.id);
|
|
243
243
|
return resolved.cacheDirty;
|
|
244
244
|
}
|
|
@@ -330,4 +330,4 @@ export async function scanHistoryDrift(pmRoot, items, options = {}) {
|
|
|
330
330
|
return { ...accumulator, driftedItems };
|
|
331
331
|
}
|
|
332
332
|
//# sourceMappingURL=drift-scan.js.map
|
|
333
|
-
//# debugId=
|
|
333
|
+
//# debugId=1c6c65ef-115b-50e2-815e-84f6e91158cd
|
|
@@ -12,6 +12,12 @@ declare function isDefinedPointerPath(document: unknown, path: string): boolean;
|
|
|
12
12
|
export declare function hashDocument(document: ItemDocument): string;
|
|
13
13
|
/** Hash an item with an explicit canonicalization epoch for replay compatibility. */
|
|
14
14
|
export declare function hashDocumentForVersion(document: ItemDocument, version: HistoryItemHashVersion): string;
|
|
15
|
+
/**
|
|
16
|
+
* Return the ordered hash candidates accepted when verifying one immutable
|
|
17
|
+
* history epoch. Epoch 2 has both its established expanded hash first and the
|
|
18
|
+
* earlier field-frozen writer hash second; the other epochs have one form.
|
|
19
|
+
*/
|
|
20
|
+
export declare function hashDocumentVerificationCandidates(document: ItemDocument, version: HistoryItemHashVersion): [string, ...string[]];
|
|
15
21
|
/** Implements hash empty document for the public runtime surface of this module. */
|
|
16
22
|
export declare function hashEmptyDocument(): string;
|
|
17
23
|
/** Implements create history entry for the public runtime surface of this module. */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements append-only history and replay behavior for History.
|
|
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]="60d6ec0e-a8ed-5a5d-b5bd-d29da8532a79")}catch(e){}}();
|
|
8
8
|
import jsonPatch from "fast-json-patch";
|
|
9
9
|
import { ITEM_METADATA_KEY_ORDER } from "../shared/constants.js";
|
|
10
10
|
import { runActiveServiceOverride } from "../extensions/index.js";
|
|
@@ -117,7 +117,7 @@ function normalizeHistoryPatchOps(beforeDocument, patch) {
|
|
|
117
117
|
}
|
|
118
118
|
return normalized;
|
|
119
119
|
}
|
|
120
|
-
function canonicalHashDocument(document, version) {
|
|
120
|
+
function canonicalHashDocument(document, version, legacyV2Fields = false) {
|
|
121
121
|
const hasMetadata = document.metadata && Object.keys(document.metadata).length > 0;
|
|
122
122
|
if (!hasMetadata) {
|
|
123
123
|
return {
|
|
@@ -126,12 +126,40 @@ function canonicalHashDocument(document, version) {
|
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
128
|
const canonical = canonicalDocument(document);
|
|
129
|
-
|
|
129
|
+
// Epoch 1 and the earliest epoch-2 writer predate linked-test provenance,
|
|
130
|
+
// workspace isolation, per-execution receipts, and case-preserving
|
|
131
|
+
// dependency ids. Later epoch-2 writers included those fields without
|
|
132
|
+
// advancing the marker, so verification must retain both immutable forms.
|
|
133
|
+
const usesLegacyFields = version === 1 || (version === 2 && legacyV2Fields);
|
|
134
|
+
const epochMetadata = usesLegacyFields
|
|
130
135
|
? {
|
|
131
136
|
...canonical.metadata,
|
|
132
|
-
|
|
137
|
+
...(canonical.metadata.dependencies === undefined
|
|
138
|
+
? {}
|
|
139
|
+
: {
|
|
140
|
+
dependencies: canonical.metadata.dependencies.map((dependency) => ({
|
|
141
|
+
...dependency,
|
|
142
|
+
id: dependency.id.toLowerCase(),
|
|
143
|
+
})),
|
|
144
|
+
}),
|
|
145
|
+
...(canonical.metadata.tests === undefined
|
|
146
|
+
? {}
|
|
147
|
+
: {
|
|
148
|
+
tests: canonical.metadata.tests.map(({ workspace_context_mode: _workspaceContextMode, provenance: _provenance, provenance_invalid: _provenanceInvalid, ...test }) => test),
|
|
149
|
+
}),
|
|
150
|
+
...(canonical.metadata.test_runs === undefined
|
|
151
|
+
? {}
|
|
152
|
+
: {
|
|
153
|
+
test_runs: canonical.metadata.test_runs.map(({ executions: _executions, ...testRun }) => testRun),
|
|
154
|
+
}),
|
|
133
155
|
}
|
|
134
156
|
: canonical.metadata;
|
|
157
|
+
const metadata = version === 1 && epochMetadata.tests
|
|
158
|
+
? {
|
|
159
|
+
...epochMetadata,
|
|
160
|
+
tests: [...epochMetadata.tests].sort(compareLegacyLinkedTests),
|
|
161
|
+
}
|
|
162
|
+
: epochMetadata;
|
|
135
163
|
const orderedMetadata = orderObject(toItemRecord(metadata), ITEM_METADATA_KEY_ORDER);
|
|
136
164
|
return {
|
|
137
165
|
front_matter: orderedMetadata,
|
|
@@ -164,6 +192,20 @@ export function hashDocumentForVersion(document, version) {
|
|
|
164
192
|
}
|
|
165
193
|
return sha256Hex(stableStringify(canonicalHashDocument(document, version)));
|
|
166
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Return the ordered hash candidates accepted when verifying one immutable
|
|
197
|
+
* history epoch. Epoch 2 has both its established expanded hash first and the
|
|
198
|
+
* earlier field-frozen writer hash second; the other epochs have one form.
|
|
199
|
+
*/
|
|
200
|
+
export function hashDocumentVerificationCandidates(document, version) {
|
|
201
|
+
const canonicalHash = hashDocumentForVersion(document, version);
|
|
202
|
+
return version === 2
|
|
203
|
+
? [
|
|
204
|
+
canonicalHash,
|
|
205
|
+
sha256Hex(stableStringify(canonicalHashDocument(document, version, true))),
|
|
206
|
+
]
|
|
207
|
+
: [canonicalHash];
|
|
208
|
+
}
|
|
167
209
|
/** Implements hash empty document for the public runtime surface of this module. */
|
|
168
210
|
export function hashEmptyDocument() {
|
|
169
211
|
return sha256Hex(stableStringify(EMPTY_LEGACY_HASH_DOCUMENT));
|
|
@@ -292,4 +334,4 @@ export const _testOnly = {
|
|
|
292
334
|
isDefinedPointerPath,
|
|
293
335
|
};
|
|
294
336
|
//# sourceMappingURL=history.js.map
|
|
295
|
-
//# debugId=
|
|
337
|
+
//# debugId=60d6ec0e-a8ed-5a5d-b5bd-d29da8532a79
|
|
@@ -21,6 +21,12 @@ export declare const EMPTY_REPLAY_DOCUMENT: ReplayDocument;
|
|
|
21
21
|
export declare function cloneEmptyReplayDocument(): ReplayDocument;
|
|
22
22
|
/** Implements replay hash for the public runtime surface of this module. */
|
|
23
23
|
export declare function replayHash(document: ReplayDocument, version?: HistoryItemHashVersion): string;
|
|
24
|
+
/**
|
|
25
|
+
* Return hash candidates that preserve the semantic variant within an epoch.
|
|
26
|
+
* Duplicate values are intentional: before and after candidates use the same
|
|
27
|
+
* index when a patch introduces a field that distinguishes legacy epoch 2.
|
|
28
|
+
*/
|
|
29
|
+
export declare function replayHashVerificationCandidates(document: ReplayDocument, version: HistoryItemHashVersion): [string, ...string[]];
|
|
24
30
|
/** Implements replay to item document for the public runtime surface of this module. */
|
|
25
31
|
export declare function replayToItemDocument(document: ReplayDocument): ItemDocument;
|
|
26
32
|
/** Converts a materialized replay document into a canonical item document. Use this when callers have already rejected the empty/deleted replay state and need restored metadata validated through the normal item-metadata rules. */
|
|
@@ -98,6 +104,11 @@ export interface ReanchorResult {
|
|
|
98
104
|
/** Whether rewritten entries explicitly carry the hash epoch field. */
|
|
99
105
|
explicitItemHashVersion: boolean;
|
|
100
106
|
}
|
|
107
|
+
/** Controls whether re-anchoring preserves historical writer transitions or emits one exact hash surface. */
|
|
108
|
+
export interface ReanchorHistoryOptions {
|
|
109
|
+
/** Keep one semantic hash candidate for the complete rewritten stream so adjacent stored endpoints are identical. */
|
|
110
|
+
continuousHashSurface?: boolean;
|
|
111
|
+
}
|
|
101
112
|
/**
|
|
102
113
|
* Resolve the hash epoch a repair must retain.
|
|
103
114
|
*
|
|
@@ -108,6 +119,6 @@ export interface ReanchorResult {
|
|
|
108
119
|
*/
|
|
109
120
|
export declare function resolveHistoryRepairItemHashVersion(entries: HistoryEntry[]): HistoryItemHashVersion;
|
|
110
121
|
/** Re-anchor a drifted history chain: replay every entry from empty, recompute the before/after hashes, and only rewrite a patch when the original op set no longer strictly applies (legacy drift). Clean entries keep their patch verbatim so the on-disk diff stays minimal. The returned chain verifies via verifyHistoryChain. */
|
|
111
|
-
export declare function reanchorHistoryEntries(entries: HistoryEntry[], itemHashVersion?: 1 | 2 | 3): ReanchorResult;
|
|
122
|
+
export declare function reanchorHistoryEntries(entries: HistoryEntry[], itemHashVersion?: 1 | 2 | 3, options?: ReanchorHistoryOptions): ReanchorResult;
|
|
112
123
|
/** Implements history entries to raw for the public runtime surface of this module. */
|
|
113
124
|
export declare function historyEntriesToRaw(entries: HistoryEntry[]): string;
|
|
@@ -4,13 +4,13 @@
|
|
|
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]="c9488ed4-8228-5e7c-9717-69dd7a3275c4")}catch(e){}}();
|
|
8
8
|
import jsonPatch from "fast-json-patch";
|
|
9
9
|
import { ITEM_METADATA_KEY_ORDER } from "../shared/constants.js";
|
|
10
10
|
import { canonicalDocument } from "../item/item-format.js";
|
|
11
11
|
import { toItemRecord } from "../item/item-record.js";
|
|
12
12
|
import { orderObject, sha256Hex, stableStringify, } from "../shared/serialization.js";
|
|
13
|
-
import { CURRENT_HISTORY_ITEM_HASH_VERSION, SUPPORTED_HISTORY_ITEM_HASH_VERSIONS,
|
|
13
|
+
import { CURRENT_HISTORY_ITEM_HASH_VERSION, SUPPORTED_HISTORY_ITEM_HASH_VERSIONS, hashDocumentVerificationCandidates, } from "./history.js";
|
|
14
14
|
/** Public contract for empty replay document, shared by SDK and presentation-layer consumers. */
|
|
15
15
|
export const EMPTY_REPLAY_DOCUMENT = {
|
|
16
16
|
metadata: {},
|
|
@@ -22,23 +22,42 @@ export function cloneEmptyReplayDocument() {
|
|
|
22
22
|
}
|
|
23
23
|
/** Implements replay hash for the public runtime surface of this module. */
|
|
24
24
|
export function replayHash(document, version = CURRENT_HISTORY_ITEM_HASH_VERSION) {
|
|
25
|
+
return replayHashVerificationCandidates(document, version)[0];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Return hash candidates that preserve the semantic variant within an epoch.
|
|
29
|
+
* Duplicate values are intentional: before and after candidates use the same
|
|
30
|
+
* index when a patch introduces a field that distinguishes legacy epoch 2.
|
|
31
|
+
*/
|
|
32
|
+
export function replayHashVerificationCandidates(document, version) {
|
|
25
33
|
if (Object.keys(document.metadata).length === 0 ||
|
|
26
34
|
Array.isArray(document.metadata.tags)) {
|
|
27
35
|
try {
|
|
28
|
-
return
|
|
36
|
+
return hashDocumentVerificationCandidates(replayToItemDocument(document), version);
|
|
29
37
|
}
|
|
30
38
|
catch {
|
|
31
39
|
// Fall through when another malformed legacy field cannot be canonicalized.
|
|
32
40
|
}
|
|
33
41
|
}
|
|
34
|
-
|
|
35
|
-
// normalize. Pre-create/legacy replay states and other malformed metadata cannot
|
|
36
|
-
// switch hash algorithms without invalidating immutable history chains.
|
|
37
|
-
return sha256Hex(stableStringify({
|
|
42
|
+
const fallback = sha256Hex(stableStringify({
|
|
38
43
|
replay_fallback: true,
|
|
39
44
|
metadata: document.metadata,
|
|
40
45
|
body: document.body,
|
|
41
46
|
}));
|
|
47
|
+
return version === 2 ? [fallback, fallback] : [fallback];
|
|
48
|
+
}
|
|
49
|
+
/** Match one recorded entry against corresponding before/after hash variants. */
|
|
50
|
+
function matchReplayHashCandidates(before, after, version, entry) {
|
|
51
|
+
const beforeHashes = replayHashVerificationCandidates(before, version);
|
|
52
|
+
const afterHashes = replayHashVerificationCandidates(after, version);
|
|
53
|
+
return {
|
|
54
|
+
beforeHashes,
|
|
55
|
+
afterHashes,
|
|
56
|
+
pairIndex: beforeHashes.findIndex((beforeHash, hashIndex) => beforeHash === entry.before_hash &&
|
|
57
|
+
afterHashes[hashIndex] === entry.after_hash),
|
|
58
|
+
beforeIndex: beforeHashes.indexOf(entry.before_hash),
|
|
59
|
+
afterIndex: afterHashes.indexOf(entry.after_hash),
|
|
60
|
+
};
|
|
42
61
|
}
|
|
43
62
|
/** Implements replay to item document for the public runtime surface of this module. */
|
|
44
63
|
export function replayToItemDocument(document) {
|
|
@@ -156,22 +175,9 @@ export function verifyHistoryChainWithVersion(entries) {
|
|
|
156
175
|
for (let index = 0; index < entries.length; index += 1) {
|
|
157
176
|
const entry = entries[index];
|
|
158
177
|
const explicitVersion = entry.item_hash_version;
|
|
159
|
-
|
|
178
|
+
const unsupportedVersion = isUnsupportedExplicitHistoryItemHashVersion(explicitVersion);
|
|
179
|
+
if (unsupportedVersion) {
|
|
160
180
|
errors.push(`verify_failed:unsupported_item_hash_version:${String(explicitVersion)}:entry_${index + 1}`);
|
|
161
|
-
const applied = tryApplyReplayPatch(replay, entry.patch);
|
|
162
|
-
if (!applied.ok) {
|
|
163
|
-
return {
|
|
164
|
-
ok: false,
|
|
165
|
-
errors: [
|
|
166
|
-
...errors,
|
|
167
|
-
`verify_failed:patch_apply_failed:entry_${index + 1}`,
|
|
168
|
-
],
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
replay = applied.document;
|
|
172
|
-
detectedVersion = undefined;
|
|
173
|
-
authoritativeExplicitVersion = undefined;
|
|
174
|
-
continue;
|
|
175
181
|
}
|
|
176
182
|
const applied = tryApplyReplayPatch(replay, entry.patch);
|
|
177
183
|
if (!applied.ok) {
|
|
@@ -183,30 +189,32 @@ export function verifyHistoryChainWithVersion(entries) {
|
|
|
183
189
|
],
|
|
184
190
|
};
|
|
185
191
|
}
|
|
192
|
+
if (unsupportedVersion) {
|
|
193
|
+
replay = applied.document;
|
|
194
|
+
detectedVersion = undefined;
|
|
195
|
+
authoritativeExplicitVersion = undefined;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
186
198
|
// Prefer legacy epoch 1 when an unversioned entry is valid under both
|
|
187
199
|
// algorithms, but retain compatibility with transitional epoch-2 writers
|
|
188
200
|
// that shipped before item_hash_version became explicit.
|
|
189
201
|
const candidates = historyEntryHashCandidates(explicitVersion, authoritativeExplicitVersion);
|
|
190
|
-
const
|
|
191
|
-
|
|
202
|
+
const candidateMatches = candidates.map((version) => ({
|
|
203
|
+
version,
|
|
204
|
+
match: matchReplayHashCandidates(replay, applied.document, version, entry),
|
|
205
|
+
}));
|
|
206
|
+
const matchingVersion = candidateMatches.find(({ match }) => match.pairIndex >= 0);
|
|
207
|
+
if (matchingVersion === undefined) {
|
|
208
|
+
const beforeMatches = candidateMatches.some(({ match }) => match.beforeIndex >= 0);
|
|
192
209
|
return {
|
|
193
210
|
ok: false,
|
|
194
211
|
errors: [
|
|
195
212
|
...errors,
|
|
196
|
-
`verify_failed:
|
|
197
|
-
],
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
const version = beforeMatches.find((candidate) => replayHash(applied.document, candidate) === entry.after_hash);
|
|
201
|
-
if (version === undefined) {
|
|
202
|
-
return {
|
|
203
|
-
ok: false,
|
|
204
|
-
errors: [
|
|
205
|
-
...errors,
|
|
206
|
-
`verify_failed:after_hash_mismatch:entry_${index + 1}`,
|
|
213
|
+
`verify_failed:${beforeMatches ? "after" : "before"}_hash_mismatch:entry_${index + 1}`,
|
|
207
214
|
],
|
|
208
215
|
};
|
|
209
216
|
}
|
|
217
|
+
const version = matchingVersion.version;
|
|
210
218
|
replay = applied.document;
|
|
211
219
|
detectedVersion = version;
|
|
212
220
|
authoritativeExplicitVersion =
|
|
@@ -297,7 +305,7 @@ export function resolveHistoryRepairItemHashVersion(entries) {
|
|
|
297
305
|
return CURRENT_HISTORY_ITEM_HASH_VERSION;
|
|
298
306
|
}
|
|
299
307
|
/** Re-anchor a drifted history chain: replay every entry from empty, recompute the before/after hashes, and only rewrite a patch when the original op set no longer strictly applies (legacy drift). Clean entries keep their patch verbatim so the on-disk diff stays minimal. The returned chain verifies via verifyHistoryChain. */
|
|
300
|
-
export function reanchorHistoryEntries(entries, itemHashVersion = resolveHistoryRepairItemHashVersion(entries)) {
|
|
308
|
+
export function reanchorHistoryEntries(entries, itemHashVersion = resolveHistoryRepairItemHashVersion(entries), options = {}) {
|
|
301
309
|
const unsupportedIndex = entries.findIndex((entry) => isUnsupportedExplicitHistoryItemHashVersion(entry.item_hash_version));
|
|
302
310
|
if (unsupportedIndex >= 0) {
|
|
303
311
|
throw new TypeError(`unsupported_item_hash_version:${String(entries[unsupportedIndex]?.item_hash_version)}:entry_${unsupportedIndex + 1}`);
|
|
@@ -309,11 +317,11 @@ export function reanchorHistoryEntries(entries, itemHashVersion = resolveHistory
|
|
|
309
317
|
let entriesPatchRepaired = 0;
|
|
310
318
|
let convertedReplaceToAdd = 0;
|
|
311
319
|
let skippedOps = 0;
|
|
320
|
+
let semanticIndex;
|
|
312
321
|
const explicitItemHashVersion = itemHashVersion !== 1 ||
|
|
313
322
|
entries.some((entry) => entry.item_hash_version !== undefined);
|
|
314
323
|
for (let index = 0; index < entries.length; index += 1) {
|
|
315
324
|
const entry = entries[index];
|
|
316
|
-
const beforeHash = replayHash(replay, itemHashVersion);
|
|
317
325
|
const strict = tryApplyReplayPatch(replay, entry.patch);
|
|
318
326
|
let next;
|
|
319
327
|
let outPatch;
|
|
@@ -335,7 +343,20 @@ export function reanchorHistoryEntries(entries, itemHashVersion = resolveHistory
|
|
|
335
343
|
skippedOps += entrySkipped;
|
|
336
344
|
entriesPatchRepaired += 1;
|
|
337
345
|
}
|
|
338
|
-
const
|
|
346
|
+
const hashMatch = matchReplayHashCandidates(replay, next, itemHashVersion, entry);
|
|
347
|
+
if (semanticIndex === undefined || options.continuousHashSurface !== true) {
|
|
348
|
+
semanticIndex = [
|
|
349
|
+
hashMatch.pairIndex,
|
|
350
|
+
hashMatch.beforeIndex,
|
|
351
|
+
hashMatch.afterIndex,
|
|
352
|
+
Math.min(semanticIndex ?? 0, hashMatch.beforeHashes.length - 1),
|
|
353
|
+
].find((candidate) => candidate >= 0);
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
semanticIndex = Math.min(semanticIndex, hashMatch.beforeHashes.length - 1);
|
|
357
|
+
}
|
|
358
|
+
const beforeHash = hashMatch.beforeHashes[semanticIndex];
|
|
359
|
+
const afterHash = hashMatch.afterHashes[semanticIndex];
|
|
339
360
|
const rehashed = beforeHash !== entry.before_hash || afterHash !== entry.after_hash;
|
|
340
361
|
if (rehashed) {
|
|
341
362
|
entriesRehashed += 1;
|
|
@@ -382,4 +403,4 @@ export function historyEntriesToRaw(entries) {
|
|
|
382
403
|
return `${entries.map((entry) => JSON.stringify(entry)).join("\n")}\n`;
|
|
383
404
|
}
|
|
384
405
|
//# sourceMappingURL=replay.js.map
|
|
385
|
-
//# debugId=
|
|
406
|
+
//# debugId=c9488ed4-8228-5e7c-9717-69dd7a3275c4
|
|
@@ -75,6 +75,10 @@ export interface RuntimeStatusRegistry {
|
|
|
75
75
|
draft_statuses: Set<string>;
|
|
76
76
|
/** Configured status id representing the open lifecycle state. */
|
|
77
77
|
open_status: string;
|
|
78
|
+
/** Configured status id representing the in-progress lifecycle state. */
|
|
79
|
+
in_progress_status: string;
|
|
80
|
+
/** Configured status id representing the blocked lifecycle state. */
|
|
81
|
+
blocked_status: string;
|
|
78
82
|
/** Configured status id representing the closed lifecycle state. */
|
|
79
83
|
close_status: string;
|
|
80
84
|
/** Configured status id representing the canceled lifecycle state. */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Resolves configurable schema, fields, statuses, and workflows for Runtime Schema.
|
|
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]="633ef301-42a3-5b73-a4ed-7af0e0e40371")}catch(e){}}();
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { pathExists, readFileIfExists, writeFileAtomic, } from "../fs/fs-utils.js";
|
|
10
10
|
import { DEFAULT_STATUS_DEFINITIONS, DEFAULT_WORKFLOW_DEFINITION, } from "../shared/constants.js";
|
|
@@ -52,8 +52,7 @@ const RUNTIME_FIELD_VALUE_SCHEMA_SHAPE_VALIDATORS = [
|
|
|
52
52
|
(Array.isArray(schema.enum) &&
|
|
53
53
|
schema.enum.every((entry) => isStructuredJsonValue(entry))),
|
|
54
54
|
(schema) => schema.min_length === undefined ||
|
|
55
|
-
(Number.isInteger(schema.min_length) &&
|
|
56
|
-
schema.min_length >= 0),
|
|
55
|
+
(Number.isInteger(schema.min_length) && schema.min_length >= 0),
|
|
57
56
|
(schema) => schema.min_items === undefined ||
|
|
58
57
|
(Number.isInteger(schema.min_items) && schema.min_items >= 0),
|
|
59
58
|
(schema) => schema.format === undefined || schema.format === "date-time",
|
|
@@ -62,8 +61,7 @@ const RUNTIME_FIELD_VALUE_SCHEMA_SHAPE_VALIDATORS = [
|
|
|
62
61
|
schema.required.every((entry) => typeof entry === "string" && entry.length > 0)),
|
|
63
62
|
(schema) => schema.additional_properties === undefined ||
|
|
64
63
|
typeof schema.additional_properties === "boolean",
|
|
65
|
-
(schema) => schema.properties === undefined ||
|
|
66
|
-
isPlainObject(schema.properties),
|
|
64
|
+
(schema) => schema.properties === undefined || isPlainObject(schema.properties),
|
|
67
65
|
(schema) => schema.one_of === undefined ||
|
|
68
66
|
(Array.isArray(schema.one_of) && schema.one_of.length > 0),
|
|
69
67
|
];
|
|
@@ -137,9 +135,7 @@ function normalizeRuntimeFieldValueSchema(value, depth = 0, ancestors = new Set(
|
|
|
137
135
|
min_items: minItems,
|
|
138
136
|
format: format,
|
|
139
137
|
properties: normalizedProperties,
|
|
140
|
-
required: required === undefined
|
|
141
|
-
? undefined
|
|
142
|
-
: [...new Set(required)],
|
|
138
|
+
required: required === undefined ? undefined : [...new Set(required)],
|
|
143
139
|
additional_properties: additionalProperties,
|
|
144
140
|
items: normalizedItems,
|
|
145
141
|
one_of: normalizedOneOf,
|
|
@@ -329,7 +325,10 @@ function normalizeRuntimeFieldDefinition(definition) {
|
|
|
329
325
|
description: description && description.length > 0 ? description : undefined,
|
|
330
326
|
type,
|
|
331
327
|
commands,
|
|
332
|
-
repeatable: [
|
|
328
|
+
repeatable: [
|
|
329
|
+
definition.repeatable === true,
|
|
330
|
+
type === "string_array",
|
|
331
|
+
].includes(true),
|
|
333
332
|
required: definition.required === true,
|
|
334
333
|
required_on_create: definition.required_on_create === true,
|
|
335
334
|
required_types: requiredTypes,
|
|
@@ -658,27 +657,22 @@ export async function loadRuntimeSchemaFromOptionalFiles(pmRoot, schema) {
|
|
|
658
657
|
created_paths: [],
|
|
659
658
|
};
|
|
660
659
|
}
|
|
661
|
-
function preferredStatusForRole(definitions, role, fallbackValues) {
|
|
662
|
-
const withRole = definitions.filter((definition) => definition.roles.includes(role));
|
|
663
|
-
if (withRole.length > 0) {
|
|
664
|
-
return withRole[0].id;
|
|
665
|
-
}
|
|
660
|
+
function preferredStatusForRole(definitions, role, fallbackValues, fallbackFirst = false) {
|
|
666
661
|
const normalizedFallbacks = fallbackValues
|
|
667
662
|
.map((value) => normalizeStatusId(value))
|
|
668
663
|
.filter((value) => typeof value === "string");
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
664
|
+
const fallbackMatch = normalizedFallbacks.find((normalized) => definitions.some((definition) => definition.id === normalized));
|
|
665
|
+
if (fallbackFirst && fallbackMatch !== undefined) {
|
|
666
|
+
return fallbackMatch;
|
|
673
667
|
}
|
|
674
|
-
|
|
668
|
+
const withRole = definitions.find((definition) => definition.roles.includes(role));
|
|
669
|
+
if (withRole !== undefined) {
|
|
670
|
+
return withRole.id;
|
|
671
|
+
}
|
|
672
|
+
return fallbackMatch ?? definitions[0]?.id;
|
|
675
673
|
}
|
|
676
|
-
/**
|
|
677
|
-
|
|
678
|
-
const normalizedSchema = normalizeRuntimeSchemaSettings(schema);
|
|
679
|
-
const definitions = normalizedSchema.statuses
|
|
680
|
-
.map((definition, index) => normalizeRuntimeStatusDefinition(definition, index))
|
|
681
|
-
.filter((definition) => definition !== null);
|
|
674
|
+
/** Build normalized identifier and alias indexes for runtime status lookup. */
|
|
675
|
+
function buildRuntimeStatusIndexes(definitions) {
|
|
682
676
|
const aliasToId = new Map();
|
|
683
677
|
const byId = new Map();
|
|
684
678
|
for (const definition of definitions) {
|
|
@@ -692,42 +686,58 @@ export function resolveRuntimeStatusRegistry(schema) {
|
|
|
692
686
|
aliasToId.set(alias.replaceAll("_", " "), definition.id);
|
|
693
687
|
}
|
|
694
688
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
const
|
|
700
|
-
|
|
689
|
+
return { aliasToId, byId };
|
|
690
|
+
}
|
|
691
|
+
/** Classify runtime statuses into lifecycle role sets used by all consumers. */
|
|
692
|
+
function buildRuntimeStatusRoleSets(definitions) {
|
|
693
|
+
const result = {
|
|
694
|
+
activeStatuses: new Set(),
|
|
695
|
+
blockedStatuses: new Set(),
|
|
696
|
+
draftStatuses: new Set(),
|
|
697
|
+
terminalCanceledStatuses: new Set(),
|
|
698
|
+
terminalDoneStatuses: new Set(),
|
|
699
|
+
terminalStatuses: new Set(),
|
|
700
|
+
};
|
|
701
701
|
for (const definition of definitions) {
|
|
702
702
|
const roles = new Set(definition.roles);
|
|
703
703
|
if (roles.has("terminal") ||
|
|
704
704
|
roles.has("terminal_done") ||
|
|
705
705
|
roles.has("terminal_canceled")) {
|
|
706
|
-
terminalStatuses.add(definition.id);
|
|
707
|
-
}
|
|
708
|
-
if (roles.has("terminal_done")) {
|
|
709
|
-
terminalDoneStatuses.add(definition.id);
|
|
706
|
+
result.terminalStatuses.add(definition.id);
|
|
710
707
|
}
|
|
708
|
+
if (roles.has("terminal_done"))
|
|
709
|
+
result.terminalDoneStatuses.add(definition.id);
|
|
711
710
|
if (roles.has("terminal_canceled")) {
|
|
712
|
-
terminalCanceledStatuses.add(definition.id);
|
|
713
|
-
}
|
|
714
|
-
if (roles.has("active")) {
|
|
715
|
-
activeStatuses.add(definition.id);
|
|
716
|
-
}
|
|
717
|
-
if (roles.has("blocked")) {
|
|
718
|
-
blockedStatuses.add(definition.id);
|
|
719
|
-
}
|
|
720
|
-
if (roles.has("draft")) {
|
|
721
|
-
draftStatuses.add(definition.id);
|
|
711
|
+
result.terminalCanceledStatuses.add(definition.id);
|
|
722
712
|
}
|
|
713
|
+
if (roles.has("active"))
|
|
714
|
+
result.activeStatuses.add(definition.id);
|
|
715
|
+
if (roles.has("blocked"))
|
|
716
|
+
result.blockedStatuses.add(definition.id);
|
|
717
|
+
if (roles.has("draft"))
|
|
718
|
+
result.draftStatuses.add(definition.id);
|
|
723
719
|
}
|
|
720
|
+
return result;
|
|
721
|
+
}
|
|
722
|
+
/** Implements resolve runtime status registry for the public runtime surface of this module. */
|
|
723
|
+
export function resolveRuntimeStatusRegistry(schema) {
|
|
724
|
+
const normalizedSchema = normalizeRuntimeSchemaSettings(schema);
|
|
725
|
+
const definitions = normalizedSchema.statuses
|
|
726
|
+
.map((definition, index) => normalizeRuntimeStatusDefinition(definition, index))
|
|
727
|
+
.filter((definition) => definition !== null);
|
|
728
|
+
const { aliasToId, byId } = buildRuntimeStatusIndexes(definitions);
|
|
729
|
+
const { activeStatuses, blockedStatuses, draftStatuses, terminalCanceledStatuses, terminalDoneStatuses, terminalStatuses, } = buildRuntimeStatusRoleSets(definitions);
|
|
724
730
|
const workflow = normalizedSchema.workflow;
|
|
725
|
-
const openStatus = normalizeStatusId(workflow.open_status) ??
|
|
731
|
+
const openStatus = (normalizeStatusId(workflow.open_status) ??
|
|
726
732
|
preferredStatusForRole(definitions, "default_open", [
|
|
727
733
|
"open",
|
|
728
734
|
"in_progress",
|
|
729
735
|
STATUS_VALUES[0],
|
|
730
|
-
]);
|
|
736
|
+
]));
|
|
737
|
+
const inProgressStatus = normalizeStatusId(workflow.in_progress_status) ??
|
|
738
|
+
preferredStatusForRole(definitions, "active", ["in_progress", "in-progress", openStatus], true);
|
|
739
|
+
const blockedStatus = normalizeStatusId(workflow.blocked_status) ??
|
|
740
|
+
preferredStatusForRole(definitions, "blocked", ["blocked"]);
|
|
731
741
|
const closeStatus = normalizeStatusId(workflow.close_status) ??
|
|
732
742
|
preferredStatusForRole(definitions, "default_close", [
|
|
733
743
|
"closed",
|
|
@@ -750,6 +760,8 @@ export function resolveRuntimeStatusRegistry(schema) {
|
|
|
750
760
|
blocked_statuses: blockedStatuses,
|
|
751
761
|
draft_statuses: draftStatuses,
|
|
752
762
|
open_status: openStatus,
|
|
763
|
+
in_progress_status: inProgressStatus,
|
|
764
|
+
blocked_status: blockedStatus,
|
|
753
765
|
close_status: closeStatus,
|
|
754
766
|
canceled_status: canceledStatus,
|
|
755
767
|
};
|
|
@@ -812,4 +824,4 @@ export function statusIsTerminal(status, registry) {
|
|
|
812
824
|
return registry.terminal_statuses.has(normalized);
|
|
813
825
|
}
|
|
814
826
|
//# sourceMappingURL=runtime-schema.js.map
|
|
815
|
-
//# debugId=
|
|
827
|
+
//# debugId=633ef301-42a3-5b73-a4ed-7af0e0e40371
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Resolves configurable schema, fields, statuses, and workflows for Status Defs File.
|
|
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]="ec456832-5120-5171-93fd-861ea4125acb")}catch(e){}}();
|
|
8
8
|
import { RUNTIME_STATUS_ROLE_VALUES } from "../../types/index.js";
|
|
9
9
|
import { DEFAULT_RUNTIME_STATUS_DEFINITIONS } from "./runtime-schema.js";
|
|
10
10
|
import { normalizeStatusToken } from "./status-token.js";
|
|
@@ -72,6 +72,9 @@ export function normalizeAddStatusInput(raw) {
|
|
|
72
72
|
roles.push(role);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
+
if (roles.length === 0) {
|
|
76
|
+
throw new Error(`Status role must include at least one lifecycle role. Allowed roles: ${RUNTIME_STATUS_ROLE_VALUES.join(", ")}.`);
|
|
77
|
+
}
|
|
75
78
|
}
|
|
76
79
|
const aliases = raw.aliases === undefined
|
|
77
80
|
? undefined
|
|
@@ -222,4 +225,4 @@ export function assertStatusTokensAvailable(input, resolvedAliasToId) {
|
|
|
222
225
|
}
|
|
223
226
|
}
|
|
224
227
|
//# sourceMappingURL=status-defs-file.js.map
|
|
225
|
-
//# debugId=
|
|
228
|
+
//# debugId=ec456832-5120-5171-93fd-861ea4125acb
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module mcp/legacy-adapter
|
|
3
3
|
*
|
|
4
|
-
* Isolates the bounded
|
|
4
|
+
* Isolates the bounded initialize-era stdio compatibility surface from the
|
|
5
5
|
* canonical stateless dispatcher. No modern transport imports policy from it.
|
|
6
6
|
*/
|
|
7
7
|
import { type AgentClientInfo } from "../sdk/runtime-primitives.js";
|
|
8
|
-
import { type PmMcpImplementation, type PmMcpServerCapabilities } from "../sdk/mcp/protocol.js";
|
|
8
|
+
import { PM_MCP_LEGACY_PROTOCOL_VERSIONS, type PmMcpImplementation, type PmMcpServerCapabilities } from "../sdk/mcp/protocol.js";
|
|
9
9
|
/** Minimal request shape consumed by the compatibility adapter. */
|
|
10
10
|
export interface LegacyMcpRequest {
|
|
11
11
|
/** Legacy method name. */
|
|
@@ -36,6 +36,15 @@ export interface LegacyMcpAdapterOptions {
|
|
|
36
36
|
/** Render one legacy prompt. */
|
|
37
37
|
getPrompt: (params: Record<string, unknown> | undefined) => Record<string, unknown>;
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the legacy revision a handshake negotiates, or refuse with the full
|
|
41
|
+
* supported set.
|
|
42
|
+
*
|
|
43
|
+
* A legacy client has no fall-forward mechanism, so the refusal names every
|
|
44
|
+
* accepted legacy revision alongside the canonical modern one: the error text
|
|
45
|
+
* is the only diagnostic such a client can surface.
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolveLegacyProtocolVersion(requestedVersion: unknown): (typeof PM_MCP_LEGACY_PROTOCOL_VERSIONS)[number];
|
|
39
48
|
/** Explicit compatibility adapter with no cross-process or modern-session role. */
|
|
40
49
|
export declare class LegacyMcpAdapter {
|
|
41
50
|
#private;
|