@unbrained/pm-cli 2026.10.8 → 2026.10.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +36 -0
- package/dist/cli/register-list-query.js +2 -2
- package/dist/cli/register-mutation.js +2 -2
- package/dist/cli-bundle/bundle-manifest.json +150 -150
- package/dist/cli-bundle/chunks/{chunk-MJVRF67I.js → chunk-2JYTSTQP.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-UGFN5NJ2.js → chunk-BXSXT5Z6.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-HFCIAXLP.js → chunk-ESRACL6K.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-34L2BS2Z.js → chunk-K2UTE75T.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ZHIMZ65M.js → chunk-KNW3RSLS.js} +30 -30
- package/dist/cli-bundle/chunks/chunk-MEWBSWE3.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-RCFZ6H2Y.js → chunk-OBLO45UM.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-FOLSEOJ2.js → chunk-RBPOO46D.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TNU56MZI.js → chunk-RUT3CCAG.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-K6E2FFUT.js → chunk-S445XEYT.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ZBVAZ7XX.js → chunk-SSY4OSJR.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-OG66KEOF.js → chunk-YMLF6QT7.js} +75 -79
- package/dist/cli-bundle/chunks/{chunk-L7U5FSZ5.js → chunk-ZWRLAOA4.js} +2 -2
- package/dist/cli-bundle/chunks/{register-list-query-PYVSPGPV.js → register-list-query-T6BOR67M.js} +7 -7
- package/dist/cli-bundle/chunks/register-mutation-6NXR7SAJ.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-WL25C3NP.js → register-operations-PDOBQZUJ.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-PFKYNEQI.js → register-setup-MAYFPKBX.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-6TKAFFEB.js → chunk-2CJWTLQG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-EOUORVJA.js → chunk-52UJEHEV.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-V3EPBB6V.js → chunk-AU6VJGTY.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-L3CZNKZE.js → chunk-B3YW6H2I.js} +16 -20
- package/dist/cli-bundle/focused-chunks/{chunk-XT7JAVHI.js → chunk-DMSADMEU.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-A3W6HFFO.js → chunk-EIOQNLBQ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-OLCJ2PJS.js → chunk-GVGFUD52.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-2KSPGWLH.js → chunk-JGFSSR3G.js} +16 -16
- package/dist/cli-bundle/focused-chunks/{chunk-MW2TQHZ3.js → chunk-KNJR2WUO.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-MJQ253F3.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-F2ME5MJY.js → chunk-PBCYGO7X.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-PBPPIGUL.js → chunk-PLTTMQAW.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-SIEGIPNT.js +165 -0
- package/dist/cli-bundle/focused-chunks/{chunk-DRHJOG5X.js → chunk-W5AE7GKZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-LZQGEVKT.js → chunk-WAOXID5J.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-BDT5EALU.js → chunk-WOEZJUA2.js} +2 -2
- 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 +22 -22
- 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 +50 -50
- 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/history/event-index.d.ts +1 -2
- package/dist/core/history/event-index.js +2 -2
- package/dist/core/item/item-format.d.ts +2 -0
- package/dist/core/item/item-format.js +3 -3
- package/dist/core/output/output.d.ts +16 -14
- package/dist/core/output/output.js +6 -10
- package/dist/core/schema/runtime-field-values.d.ts +2 -2
- package/dist/core/schema/runtime-field-values.js +1 -1
- package/dist/core/store/item-format-migration.js +1 -1
- package/dist/core/store/item-metadata-query-index.d.ts +1 -2
- package/dist/core/store/item-metadata-query-index.js +1 -1
- package/dist/core/store/item-store.js +1 -1
- package/dist/core/store/sqlite-runtime.d.ts +15 -0
- package/dist/core/store/sqlite-runtime.js +2 -0
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
- package/dist/sdk/governance/reliability.d.ts +74 -0
- package/dist/sdk/governance/reliability.js +2 -0
- package/dist/sdk/governance.d.ts +1 -0
- package/dist/sdk/governance.js +1 -1
- package/dist/sdk/output/table-rows.d.ts +37 -0
- package/dist/sdk/output/table-rows.js +2 -0
- package/dist/sdk/output.d.ts +1 -0
- package/dist/sdk/output.js +2 -2
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/read-output-contracts.d.ts +3 -3
- package/dist/sdk/read-output-contracts.js +1 -1
- package/dist/sdk/structured-mutations.d.ts +5 -1
- package/dist/sdk/structured-mutations.js +1 -1
- package/dist/sdk/test/workspace-snapshot.d.ts +1 -1
- package/dist/sdk/test/workspace-snapshot.js +1 -1
- package/docs/AGENT_OUTPUT_ENCODINGS.md +119 -0
- package/docs/PACKAGE_GATE_ACCEPTANCE.md +56 -0
- package/docs/QUALITY_EVIDENCE.md +52 -1
- package/docs/README.md +2 -0
- package/docs/RELEASE_RELIABILITY.md +54 -3
- package/docs/SDK.md +16 -2
- package/docs/TESTING.md +47 -3
- package/docs/agent-task-token-baseline.json +15 -14
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +4 -3
- package/marketplace.json +2 -2
- package/package.json +1 -1
- 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/package.json +2 -2
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/pm-codex/package.json +2 -2
- package/plugins/pm-codex/plugin.json +1 -1
- package/runtime-dependencies.json +2 -2
- package/dist/cli-bundle/chunks/chunk-JDTBPW4Y.js +0 -2
- package/dist/cli-bundle/chunks/register-mutation-WXP3YLIN.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-OSKXYRYZ.js +0 -165
- package/dist/cli-bundle/focused-chunks/chunk-PEBOVLEG.js +0 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DatabaseSync } from "node:sqlite";
|
|
2
2
|
import type { HistoryEntry } from "../../types/index.js";
|
|
3
|
+
import { loadDatabaseSync, loadStableDatabaseSync } from "../store/sqlite-runtime.js";
|
|
3
4
|
type DatabaseSyncConstructor = typeof DatabaseSync;
|
|
4
5
|
/** Stable location of one history entry inside its authoritative stream. */
|
|
5
6
|
export interface IndexedHistoryEvent {
|
|
@@ -49,8 +50,6 @@ export interface HistoryEventIndexQueryResult {
|
|
|
49
50
|
}
|
|
50
51
|
/** Latest substantive immutable event for each requested history stream. */
|
|
51
52
|
export type LatestSubstantiveHistoryEvents = Readonly<Record<string, IndexedHistoryEvent>>;
|
|
52
|
-
declare function loadDatabaseSync(loadModule: (specifier: string) => unknown): DatabaseSyncConstructor | null;
|
|
53
|
-
declare function loadStableDatabaseSync(nodeVersion: string, loadModule: (specifier: string) => unknown): DatabaseSyncConstructor | null;
|
|
54
53
|
/** Rebuild the complete optional event projection from authoritative streams. */
|
|
55
54
|
export declare function rebuildHistoryEventIndex(pmRoot: string): Promise<boolean>;
|
|
56
55
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
-
`,{flag:"wx"}),{pendingPath,committedPath:path.join(directory,`${token}.committed`)}}function sameInvalidationNames(left,right){return left.length===right.length&&left.every((name,index)=>name===right[index])}async function invalidateHistoryEventIndex(pmRoot){try{await fs.rm(eventIndexPath(pmRoot),{force:!0})}catch{}}async function withHistoryEventIndexLock(pmRoot,operation){const release=await acquireLock(pmRoot,HISTORY_EVENT_INDEX_LOCK_ID,HISTORY_EVENT_INDEX_LOCK_TTL_SECONDS,`history-event-index:${process.pid}`,!1,!1,HISTORY_EVENT_INDEX_LOCK_WAIT_MS);try{return await operation()}finally{await release()}}async function readAuthoritativeHistorySnapshot(pmRoot){const historyRoot=path.join(pmRoot,"history"),entries=await fs.readdir(historyRoot,{withFileTypes:!0}).catch(error=>{if(typeof error=="object"&&error!==null&&"code"in error&&error.code==="ENOENT")return[];throw error}),cached=authoritativeHistoryCaches.get(pmRoot)??{streams:new Map,ordered_events:[]},presentStreams=new Set;let changed=!authoritativeHistoryCaches.has(pmRoot);for(const historyFile of entries.filter(entry=>entry.isFile()&&entry.name.endsWith(".jsonl")).sort((left,right)=>left.name.localeCompare(right.name))){const streamId=historyFile.name.slice(0,-6);presentStreams.add(streamId);const historyPath=path.join(historyRoot,historyFile.name),stats=await fs.stat(historyPath,{bigint:!0}),signature=[stats.dev,stats.ino,stats.size,stats.mtimeNs,stats.ctimeNs].join(":");if(cached.streams.get(streamId)?.signature===signature)continue;const history=await readIndexableHistoryEntries(historyPath,streamId);cached.streams.set(streamId,{signature,byte_size:Number(stats.size),events:history.map((entry,streamOffset)=>({stream_id:streamId,stream_offset:streamOffset,entry}))}),changed=!0}for(const streamId of cached.streams.keys())presentStreams.has(streamId)||(cached.streams.delete(streamId),changed=!0);if(changed&&(cached.ordered_events=[...cached.streams.values()].flatMap(stream=>stream.events).sort(compareHistoryEventPosition)),authoritativeHistoryCaches.delete(pmRoot),authoritativeHistoryCaches.set(pmRoot,cached),authoritativeHistoryCaches.size>AUTHORITATIVE_HISTORY_CACHE_LIMIT){const oldestRoot=authoritativeHistoryCaches.keys().next().value;authoritativeHistoryCaches.delete(oldestRoot)}return{events:cached.ordered_events,stream_byte_sizes:new Map([...cached.streams].map(([streamId,stream])=>[streamId,stream.byte_size]))}}async function readIndexableHistoryEntries(historyPath,streamId){const entries=await readHistoryEntries(historyPath,streamId);for(const[index,entry]of entries.entries())if(typeof entry.ts!="string"||!isMillisecondPrecisionRfc3339DateTime(entry.ts.trim()))throw new PmCliError(`History for ${streamId} contains an invalid or sub-millisecond timestamp at line ${index+1}. Repair or restore the history stream and retry.`,EXIT_CODE.GENERIC_FAILURE,{code:"history_timestamp_invalid"});return entries.map(entry=>({...entry,ts:new Date(entry.ts.trim()).toISOString()}))}async function readAuthoritativeHistoryEvents(pmRoot){return(await readAuthoritativeHistorySnapshot(pmRoot)).events}
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="59e8ff0e-d2af-5f7a-a64b-1b86e075acdc")}catch{}})();import fs from"node:fs/promises";import path from"node:path";import{randomUUID}from"node:crypto";import{createRequire}from"node:module";import{isFileMissingError}from"../fs/fs-utils.js";import{acquireLock,captureProcessIdentity,isProcessIdentityAlive}from"../lock/lock.js";import{EXIT_CODE}from"../shared/constants.js";import{PmCliError}from"../shared/errors.js";import{isMillisecondPrecisionRfc3339DateTime}from"../shared/time.js";import{readHistoryEntries}from"./read.js";import{classifyHistoryEvent}from"./event-classification.js";import{loadDatabaseSync,loadStableDatabaseSync}from"../store/sqlite-runtime.js";const EVENT_INDEX_FILENAME="history-event-index.sqlite",EVENT_INDEX_VERSION="5",AUTHORITATIVE_HISTORY_CACHE_LIMIT=8,HISTORY_EVENT_INDEX_LOCK_ID="history-event-index",HISTORY_EVENT_INDEX_LOCK_TTL_SECONDS=300,HISTORY_EVENT_INDEX_LOCK_WAIT_MS=3e4,HISTORY_EVENT_INDEX_INVALIDATION_LOCK_ID="history-event-index-invalidation",HISTORY_EVENT_INDEX_INVALIDATION_DIRECTORY="history-event-index-invalidations",HISTORY_EVENT_INDEX_INVALIDATION_MAX_UNVERIFIED_AGE_MS=HISTORY_EVENT_INDEX_LOCK_TTL_SECONDS*2*1e3,HISTORY_INDEX_LOCK_CONTENDED=Symbol("history-index-lock-contended"),authoritativeHistoryCaches=new Map;function eventIndexPath(pmRoot){return path.join(pmRoot,"runtime",EVENT_INDEX_FILENAME)}function historyEventIndexInvalidationDirectory(pmRoot){return path.join(pmRoot,"runtime",HISTORY_EVENT_INDEX_INVALIDATION_DIRECTORY)}async function listHistoryEventIndexInvalidations(pmRoot){const entries=await fs.readdir(historyEventIndexInvalidationDirectory(pmRoot)).catch(error=>{if(isFileMissingError(error))return[];throw error});return{pending:entries.filter(name=>name.endsWith(".pending")).sort(),committed:entries.filter(name=>name.endsWith(".committed")).sort()}}async function recoverAbandonedHistoryEventIndexInvalidations(pmRoot){const invalidations=await listHistoryEventIndexInvalidations(pmRoot);return{pending:(await Promise.all(invalidations.pending.map(async name=>{const owner=/^(\d+)-(unknown|\d+)-(\d+)-.+\.pending$/u.exec(name);if(owner!==null){const processStartIdentity=owner[2];if(await isProcessIdentityAlive({pid:Number(owner[1]),...processStartIdentity==="unknown"?{}:{process_start_identity:processStartIdentity}},Math.max(0,Date.now()-Number(owner[3])),HISTORY_EVENT_INDEX_INVALIDATION_MAX_UNVERIFIED_AGE_MS))return name}return await fs.rm(path.join(historyEventIndexInvalidationDirectory(pmRoot),name),{force:!0}),null}))).filter(name=>name!==null),committed:invalidations.committed}}async function withHistoryEventIndexInvalidationLock(pmRoot,operation){const release=await acquireLock(pmRoot,HISTORY_EVENT_INDEX_INVALIDATION_LOCK_ID,HISTORY_EVENT_INDEX_LOCK_TTL_SECONDS,`history-event-index-invalidation:${process.pid}`,!1,!1,HISTORY_EVENT_INDEX_LOCK_WAIT_MS);try{return await operation()}finally{await release()}}async function beginHistoryEventIndexInvalidation(pmRoot){const directory=historyEventIndexInvalidationDirectory(pmRoot);await fs.mkdir(directory,{recursive:!0});const token=randomUUID(),processIdentity=await captureProcessIdentity(),pendingPath=path.join(directory,`${processIdentity.pid}-${processIdentity.process_start_identity??"unknown"}-${Date.now()}-${token}.pending`);return await fs.writeFile(pendingPath,`pending
|
|
2
|
+
`,{flag:"wx"}),{pendingPath,committedPath:path.join(directory,`${token}.committed`)}}function sameInvalidationNames(left,right){return left.length===right.length&&left.every((name,index)=>name===right[index])}async function invalidateHistoryEventIndex(pmRoot){try{await fs.rm(eventIndexPath(pmRoot),{force:!0})}catch{}}async function withHistoryEventIndexLock(pmRoot,operation){const release=await acquireLock(pmRoot,HISTORY_EVENT_INDEX_LOCK_ID,HISTORY_EVENT_INDEX_LOCK_TTL_SECONDS,`history-event-index:${process.pid}`,!1,!1,HISTORY_EVENT_INDEX_LOCK_WAIT_MS);try{return await operation()}finally{await release()}}async function readAuthoritativeHistorySnapshot(pmRoot){const historyRoot=path.join(pmRoot,"history"),entries=await fs.readdir(historyRoot,{withFileTypes:!0}).catch(error=>{if(typeof error=="object"&&error!==null&&"code"in error&&error.code==="ENOENT")return[];throw error}),cached=authoritativeHistoryCaches.get(pmRoot)??{streams:new Map,ordered_events:[]},presentStreams=new Set;let changed=!authoritativeHistoryCaches.has(pmRoot);for(const historyFile of entries.filter(entry=>entry.isFile()&&entry.name.endsWith(".jsonl")).sort((left,right)=>left.name.localeCompare(right.name))){const streamId=historyFile.name.slice(0,-6);presentStreams.add(streamId);const historyPath=path.join(historyRoot,historyFile.name),stats=await fs.stat(historyPath,{bigint:!0}),signature=[stats.dev,stats.ino,stats.size,stats.mtimeNs,stats.ctimeNs].join(":");if(cached.streams.get(streamId)?.signature===signature)continue;const history=await readIndexableHistoryEntries(historyPath,streamId);cached.streams.set(streamId,{signature,byte_size:Number(stats.size),events:history.map((entry,streamOffset)=>({stream_id:streamId,stream_offset:streamOffset,entry}))}),changed=!0}for(const streamId of cached.streams.keys())presentStreams.has(streamId)||(cached.streams.delete(streamId),changed=!0);if(changed&&(cached.ordered_events=[...cached.streams.values()].flatMap(stream=>stream.events).sort(compareHistoryEventPosition)),authoritativeHistoryCaches.delete(pmRoot),authoritativeHistoryCaches.set(pmRoot,cached),authoritativeHistoryCaches.size>AUTHORITATIVE_HISTORY_CACHE_LIMIT){const oldestRoot=authoritativeHistoryCaches.keys().next().value;authoritativeHistoryCaches.delete(oldestRoot)}return{events:cached.ordered_events,stream_byte_sizes:new Map([...cached.streams].map(([streamId,stream])=>[streamId,stream.byte_size]))}}async function readIndexableHistoryEntries(historyPath,streamId){const entries=await readHistoryEntries(historyPath,streamId);for(const[index,entry]of entries.entries())if(typeof entry.ts!="string"||!isMillisecondPrecisionRfc3339DateTime(entry.ts.trim()))throw new PmCliError(`History for ${streamId} contains an invalid or sub-millisecond timestamp at line ${index+1}. Repair or restore the history stream and retry.`,EXIT_CODE.GENERIC_FAILURE,{code:"history_timestamp_invalid"});return entries.map(entry=>({...entry,ts:new Date(entry.ts.trim()).toISOString()}))}async function readAuthoritativeHistoryEvents(pmRoot){return(await readAuthoritativeHistorySnapshot(pmRoot)).events}let RuntimeDatabaseSync;function resolveDatabaseSync(){return RuntimeDatabaseSync!==void 0||(RuntimeDatabaseSync=loadStableDatabaseSync(process.versions.node,createRequire(import.meta.url))),RuntimeDatabaseSync}function createSchema(database){database.exec(`
|
|
3
3
|
PRAGMA journal_mode = OFF;
|
|
4
4
|
PRAGMA synchronous = OFF;
|
|
5
5
|
CREATE TABLE metadata (
|
|
@@ -19,6 +19,8 @@ export interface ItemDocumentFormatOptions {
|
|
|
19
19
|
extensionFieldNames?: readonly string[];
|
|
20
20
|
/** Value that configures or reports on warning for this contract. */
|
|
21
21
|
onWarning?: (warning: string) => void;
|
|
22
|
+
/** Refuse ahead-of-runtime markers before metadata validation; raw inspection defaults to preserving them. */
|
|
23
|
+
requireSupportedFormat?: boolean;
|
|
22
24
|
}
|
|
23
25
|
declare function runtimeFieldRequiredForType(definition: RuntimeFieldRegistry["definitions"][number], typeName: string): boolean;
|
|
24
26
|
declare function buildKnownItemMetadataKeys(runtimeContext: RuntimeSchemaValidationContext): Set<string>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e44f5fd8-80d0-57b0-bb1d-ab2e69a99e7e")}catch{}})();import{encode as encodeToon}from"@toon-format/toon";import{isDeepStrictEqual}from"node:util";import{CONFIDENCE_TEXT_VALUES,ISSUE_SEVERITY_VALUES,PLAN_STEP_STATUS_VALUES,RECURRENCE_FREQUENCY_VALUES,RECURRENCE_WEEKDAY_VALUES,STATUS_VALUES,weekdayOrderIndex}from"../../types/index.js";import{coerceRuntimeFieldValue}from"../schema/runtime-field-values.js";import{resolveRuntimeFieldRegistry,resolveRuntimeStatusRegistry}from"../schema/runtime-schema.js";import{BASELINE_ITEM_FORMAT_VERSION,normalizeItemFormatVersion}from"./item-format-version.js";import{normalizeStatusInput}from"./status.js";import{decodeToonItemContent}from"./toon-decode.js";import{EXIT_CODE,ITEM_METADATA_KEY_ORDER}from"../shared/constants.js";import{findFirstMergeConflictMarker}from"../shared/conflict-markers.js";import{PmCliError}from"../shared/errors.js";import{orderObject}from"../shared/serialization.js";import{compareTimestampStrings,isTimestampLiteral}from"../shared/time.js";import{coerceFiniteNumber}from"../shared/primitives.js";const LINKED_TEST_PM_CONTEXT_MODE_VALUES=new Set(["schema","tracker","auto","none"]),LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES=new Set(["source","isolated","snapshot"]),LINKED_TEST_TRUST_REASON_VALUES=new Set(["legacy","local_mutation","local_source_ref","acknowledged","invalid_provenance","foreign_source_ref"]),ITEM_TEST_RUN_STATUS_VALUES=new Set(["passed","failed","stopped","canceled"]),PLAN_STEP_STATUS_SET=new Set(PLAN_STEP_STATUS_VALUES);function normalizePathValue(value){return value.replaceAll("\\","/")}function firstNonZeroComparison(comparisons){for(const comparison of comparisons)if(comparison!==0)return comparison;return 0}function deleteUndefinedFields(record){for(const[key,value]of Object.entries(record))value===void 0&&delete record[key]}const REQUIRED_STRING_FIELDS=["id","title","description","created_at","updated_at"],STATIC_ITEM_METADATA_FIELD_SET=new Set(ITEM_METADATA_KEY_ORDER);function resolveRuntimeSchemaValidationContext(options){if(options?.schema)return{statusRegistry:resolveRuntimeStatusRegistry(options.schema),fieldRegistry:resolveRuntimeFieldRegistry(options.schema),unknownFieldPolicy:options.schema.unknown_field_policy??"allow",extensionFieldNames:new Set(options.extensionFieldNames??[]),onWarning:options.onWarning}}function runtimeFieldRequiredForType(definition,typeName){return definition.required?definition.required_types.length===0?!0:definition.required_types.map(value=>value.toLowerCase()).includes(typeName.trim().toLowerCase()):!1}function validationError(message){const field=message.match(/^([a-z_][\w.]*)\s/u)?.[1];throw new PmCliError(`Invalid item metadata: ${message}`,EXIT_CODE.GENERIC_FAILURE,{code:"item_document_invalid",reason:message.includes("required")?"missing_required_field":"schema_validation_error",...field?{field}:{},required:"Provide an item document whose metadata satisfies the active runtime schema.",why:message})}function documentSyntaxError(format,message){throw new PmCliError(message,EXIT_CODE.GENERIC_FAILURE,{code:"item_document_invalid",reason:"syntax_error",format,required:`Provide a syntactically valid ${format==="toon"?"TOON":"JSON Markdown"} item document.`,why:"The document could not be decoded far enough to validate item metadata."})}function buildKnownItemMetadataKeys(runtimeContext){const knownKeys=new Set(STATIC_ITEM_METADATA_FIELD_SET);for(const definition of runtimeContext.fieldRegistry?.definitions??[])knownKeys.add(definition.metadata_key);for(const fieldName of runtimeContext.extensionFieldNames)knownKeys.add(fieldName);return knownKeys}function assertItemMetadataCondition(condition,message){condition||validationError(message)}function requireItemMetadataRecord(value,message){return(typeof value!="object"||value===null||Array.isArray(value))&&validationError(message),value}function assertTimestampField(record,fieldName){const rawValue=record[fieldName];assertItemMetadataCondition(typeof rawValue=="string",`${fieldName} must be a string`),assertItemMetadataCondition(isTimestampLiteral(rawValue),`${fieldName} must be a valid ISO timestamp`)}function assertPositiveIntegerField(record,fieldName,messagePrefix){const value=record[fieldName];value!==void 0&&assertItemMetadataCondition(typeof value=="number"&&Number.isInteger(value)&&value>=1,`${messagePrefix} must be an integer >= 1`)}function assertOptionalTimestampString(record,fieldName,messagePrefix){const value=record[fieldName];value!==void 0&&(assertItemMetadataCondition(typeof value=="string",`${messagePrefix} must be a string`),assertItemMetadataCondition(isTimestampLiteral(value),`${messagePrefix} must be a valid ISO timestamp`))}function assertRecurrenceWeekdays(value){if(value!==void 0){assertItemMetadataCondition(Array.isArray(value),"event.recurrence.by_weekday must be an array");for(const weekday of value){assertItemMetadataCondition(typeof weekday=="string","event.recurrence.by_weekday entries must be strings");const normalizedWeekday=weekday.trim().toLowerCase();assertItemMetadataCondition(RECURRENCE_WEEKDAY_VALUES.includes(normalizedWeekday),`event.recurrence.by_weekday entries must be one of: ${RECURRENCE_WEEKDAY_VALUES.join(", ")}`)}}}function assertRecurrenceMonthDays(value){if(value!==void 0){assertItemMetadataCondition(Array.isArray(value),"event.recurrence.by_month_day must be an array");for(const day of value)assertItemMetadataCondition(typeof day=="number"&&Number.isInteger(day)&&day>=1&&day<=31,"event.recurrence.by_month_day entries must be integers 1..31")}}function assertRecurrenceExdates(value){if(value!==void 0){assertItemMetadataCondition(Array.isArray(value),"event.recurrence.exdates must be an array");for(const exdate of value)assertItemMetadataCondition(typeof exdate=="string","event.recurrence.exdates entries must be strings"),assertItemMetadataCondition(isTimestampLiteral(exdate),"event.recurrence.exdates entries must be valid ISO timestamps")}}function assertValidRecurrenceRule(recurrence){const recurrenceRecord=requireItemMetadataRecord(recurrence,"event.recurrence must be an object");assertItemMetadataCondition(typeof recurrenceRecord.freq=="string","event.recurrence.freq must be a string");const frequency=recurrenceRecord.freq.trim().toLowerCase();assertItemMetadataCondition(RECURRENCE_FREQUENCY_VALUES.includes(frequency),`event.recurrence.freq must be one of: ${RECURRENCE_FREQUENCY_VALUES.join(", ")}`),assertPositiveIntegerField(recurrenceRecord,"interval","event.recurrence.interval"),assertPositiveIntegerField(recurrenceRecord,"count","event.recurrence.count"),assertOptionalTimestampString(recurrenceRecord,"until","event.recurrence.until"),assertRecurrenceWeekdays(recurrenceRecord.by_weekday),assertRecurrenceMonthDays(recurrenceRecord.by_month_day),assertRecurrenceExdates(recurrenceRecord.exdates)}function assertRequiredItemMetadataFields(record){for(const fieldName of REQUIRED_STRING_FIELDS)assertItemMetadataCondition(typeof record[fieldName]=="string",`${fieldName} is required and must be a string`);const itemType=record.type;assertItemMetadataCondition(typeof itemType=="string"&&itemType.trim().length>0,"type must be a non-empty string");const formatVersion=record.pm_format_version;return formatVersion!==void 0&&assertItemMetadataCondition(typeof formatVersion=="number"&&Number.isInteger(formatVersion)&&formatVersion>=BASELINE_ITEM_FORMAT_VERSION,`pm_format_version must be an integer >= ${BASELINE_ITEM_FORMAT_VERSION}`),itemType}function assertStatusItemMetadataField(record,runtimeContext){const status=record.status;assertItemMetadataCondition(typeof status=="string"&&status.trim().length>0,"status must be a non-empty string");const statusRegistry=runtimeContext?.statusRegistry,normalizedStatus=normalizeStatusInput(status,statusRegistry),statusDomain=statusRegistry?statusRegistry.definitions.map(definition=>definition.id):[...STATUS_VALUES];assertItemMetadataCondition(normalizedStatus!==void 0,`status must be one of: ${statusDomain.join(", ")}`)}function assertPriorityAndTags(record){const priority=record.priority;assertItemMetadataCondition(typeof priority=="number"&&Number.isInteger(priority)&&[0,1,2,3,4].includes(priority),"priority must be an integer 0..4");const tags=record.tags;assertItemMetadataCondition(Array.isArray(tags),"tags must be an array");for(const tag of tags)assertItemMetadataCondition(typeof tag=="string","tags entries must be strings")}function assertConfidenceItemMetadataField(record){const confidence=record.confidence;if(confidence!==void 0){if(typeof confidence=="number"){assertItemMetadataCondition(Number.isInteger(confidence)&&confidence>=0&&confidence<=100,"confidence number value must be an integer 0..100");return}if(typeof confidence=="string"){const normalizedConfidence=confidence.trim().toLowerCase(),isKnownTextConfidence=normalizedConfidence==="med"||CONFIDENCE_TEXT_VALUES.includes(normalizedConfidence);assertItemMetadataCondition(isKnownTextConfidence,`confidence string value must be one of: ${[...CONFIDENCE_TEXT_VALUES,"med"].join(", ")}`);return}assertItemMetadataCondition(!1,"confidence must be a number or string")}}function assertSeverityItemMetadataField(record){const severity=record.severity;if(severity===void 0)return;typeof severity!="string"&&validationError("severity must be a string");const normalizedSeverity=severity.trim().toLowerCase(),isKnownSeverity=normalizedSeverity==="med"||ISSUE_SEVERITY_VALUES.includes(normalizedSeverity);assertItemMetadataCondition(isKnownSeverity,`severity value must be one of: ${[...ISSUE_SEVERITY_VALUES,"med"].join(", ")}`)}function assertRegressionItemMetadataField(record){record.regression!==void 0&&typeof record.regression!="boolean"&&validationError("regression must be a boolean")}function assertReminderEntries(record){const reminders=record.reminders;if(reminders!==void 0){assertItemMetadataCondition(Array.isArray(reminders),"reminders must be an array");for(const reminder of reminders){const reminderRecord=requireItemMetadataRecord(reminder,"reminders entries must be objects");assertItemMetadataCondition(typeof reminderRecord.at=="string","reminder.at must be a string"),assertItemMetadataCondition(isTimestampLiteral(reminderRecord.at),"reminder.at must be a valid ISO timestamp"),assertItemMetadataCondition(typeof reminderRecord.text=="string","reminder.text must be a string"),assertItemMetadataCondition(reminderRecord.text.trim().length>0,"reminder.text must not be empty")}}}function assertEventStringFields(eventRecord){for(const stringField of["title","description","location","timezone"])eventRecord[stringField]!==void 0&&(assertItemMetadataCondition(typeof eventRecord[stringField]=="string",`event.${stringField} must be a string`),assertItemMetadataCondition(eventRecord[stringField].trim().length>0,`event.${stringField} must not be empty`))}function assertEventRecurrence(eventRecord){eventRecord.recurrence!==void 0&&(assertValidRecurrenceRule(eventRecord.recurrence),eventRecord.recurrence.until!==void 0&&assertItemMetadataCondition(compareTimestampStrings(eventRecord.recurrence.until,eventRecord.start_at)>=0,"event.recurrence.until must be at or after event.start_at"))}function assertCalendarEventEntry(event){const eventRecord=requireItemMetadataRecord(event,"events entries must be objects");assertItemMetadataCondition(typeof eventRecord.start_at=="string","event.start_at must be a string"),assertItemMetadataCondition(isTimestampLiteral(eventRecord.start_at),"event.start_at must be a valid ISO timestamp"),eventRecord.end_at!==void 0&&(assertItemMetadataCondition(typeof eventRecord.end_at=="string","event.end_at must be a string"),assertItemMetadataCondition(isTimestampLiteral(eventRecord.end_at),"event.end_at must be a valid ISO timestamp"),assertItemMetadataCondition(compareTimestampStrings(eventRecord.end_at,eventRecord.start_at)>0,"event.end_at must be after event.start_at")),assertEventStringFields(eventRecord),eventRecord.all_day!==void 0&&assertItemMetadataCondition(typeof eventRecord.all_day=="boolean","event.all_day must be a boolean"),assertEventRecurrence(eventRecord)}function assertCalendarEvents(record){const events=record.events;if(events!==void 0){assertItemMetadataCondition(Array.isArray(events),"events must be an array");for(const event of events)assertCalendarEventEntry(event)}}function assertOptionalStringFields(record){for(const fieldName of["source_type","source_owner","design","external_ref"]){const value=record[fieldName];value!==void 0&&assertItemMetadataCondition(typeof value=="string",`${fieldName} must be a string`)}}function assertTypeOptionsField(record){const typeOptions=record.type_options;if(typeOptions===void 0)return;const typeOptionsRecord=requireItemMetadataRecord(typeOptions,"type_options must be an object");for(const[optionKey,optionValue]of Object.entries(typeOptionsRecord))assertItemMetadataCondition(optionKey.trim().length>0,"type_options keys must be non-empty"),assertItemMetadataCondition(typeof optionValue=="string","type_options values must be strings"),assertItemMetadataCondition(optionValue.trim().length>0,"type_options values must be non-empty strings")}function coerceRuntimeItemMetadataFields(record,itemType,runtimeContext){if(runtimeContext?.fieldRegistry)for(const definition of runtimeContext.fieldRegistry.definitions){const fieldValue=record[definition.metadata_key];if(fieldValue===void 0){runtimeFieldRequiredForType(definition,itemType)&&validationError(`missing required schema field: ${definition.metadata_key}`);continue}try{record[definition.metadata_key]=coerceRuntimeFieldValue(definition,fieldValue,`metadata field "${definition.metadata_key}"`)}catch(error){validationError(String(error?.message).replace(/^Invalid\s+/u,""))}}}function assertRuntimeUnknownItemMetadataFields(record,runtimeContext){if(!runtimeContext||runtimeContext.unknownFieldPolicy==="allow")return;const knownKeys=buildKnownItemMetadataKeys(runtimeContext),unknownKeys=Object.keys(record).filter(key=>!knownKeys.has(key)).sort((left,right)=>left.localeCompare(right));unknownKeys.length!==0&&(runtimeContext.unknownFieldPolicy==="reject"?validationError(`unknown schema fields are not allowed: ${unknownKeys.join(", ")}`):runtimeContext.onWarning?.(`item_unknown_schema_fields:${unknownKeys.join(",")}`))}function assertValidItemMetadata(itemMetadata,runtimeContext){const record=requireItemMetadataRecord(itemMetadata,"item metadata must be an object"),itemType=assertRequiredItemMetadataFields(record);assertStatusItemMetadataField(record,runtimeContext),assertPriorityAndTags(record),assertConfidenceItemMetadataField(record),assertSeverityItemMetadataField(record),assertRegressionItemMetadataField(record),assertTimestampField(record,"created_at"),assertTimestampField(record,"updated_at"),record.deadline!==void 0&&assertTimestampField(record,"deadline"),assertReminderEntries(record),assertCalendarEvents(record),assertOptionalTimestampString(record,"closed_at","closed_at"),assertOptionalTimestampString(record,"completed_at","completed_at"),assertOptionalStringFields(record),assertTypeOptionsField(record),coerceRuntimeItemMetadataFields(record,itemType,runtimeContext),assertRuntimeUnknownItemMetadataFields(record,runtimeContext)}function sortDependencies(values){if(!(!values||values.length===0))return[...values].map(value=>({id:value.id.trim(),kind:value.kind,created_at:value.created_at,author:value.author?.trim()||void 0,source_kind:value.source_kind?.trim()||void 0,author_source:value.author_source})).sort((a,b)=>{const byCreated=compareTimestampStrings(a.created_at,b.created_at);if(byCreated!==0)return byCreated;const byId=a.id.localeCompare(b.id);if(byId!==0)return byId;const byKind=a.kind.localeCompare(b.kind);return byKind!==0?byKind:(a.source_kind??"").localeCompare(b.source_kind??"")})}function sortLogValues(values){if(!(!values||values.length===0))return[...values].sort((a,b)=>{const byCreated=compareTimestampStrings(a.created_at,b.created_at);if(byCreated!==0)return byCreated;const byText=a.text.localeCompare(b.text);return byText!==0?byText:a.author.localeCompare(b.author)})}function sortReminders(values){if(!values||values.length===0)return;const normalized=[...values].map(value=>({at:value.at,text:value.text.trim()})).filter(value=>value.text.length>0).sort((a,b)=>{const byAt=compareTimestampStrings(a.at,b.at);return byAt!==0?byAt:a.text.localeCompare(b.text)});return normalized.length===0?void 0:normalized}function normalizeRecurrenceRule(value){if(!value)return;const normalizedFrequency=value.freq.trim().toLowerCase();if(!RECURRENCE_FREQUENCY_VALUES.includes(normalizedFrequency))return;const byWeekday=Array.from(new Set((value.by_weekday??[]).map(weekday=>weekday.trim().toLowerCase()).filter(weekday=>RECURRENCE_WEEKDAY_VALUES.includes(weekday)))).sort((a,b)=>weekdayOrderIndex(a)-weekdayOrderIndex(b)),byMonthDay=Array.from(new Set((value.by_month_day??[]).filter(day=>Number.isInteger(day)&&day>=1&&day<=31).map(day=>day))).sort((a,b)=>a-b),exdates=Array.from(new Set((value.exdates??[]).map(timestamp=>timestamp.trim()).filter(timestamp=>isTimestampLiteral(timestamp)))).sort((a,b)=>compareTimestampStrings(a,b)),normalized={freq:normalizedFrequency,interval:value.interval!==void 0&&value.interval>1?value.interval:void 0,count:value.count,until:value.until?.trim()||void 0,by_weekday:byWeekday.length>0?byWeekday:void 0,by_month_day:byMonthDay.length>0?byMonthDay:void 0,exdates:exdates.length>0?exdates:void 0};for(const[key,fieldValue]of Object.entries(normalized))fieldValue===void 0&&delete normalized[key];return normalized}function sortEvents(values){return!Array.isArray(values)||values.length===0?void 0:[...values].map(normalizeCalendarEvent).sort(compareCalendarEvents)}function normalizeCalendarEvent(value){const event={start_at:value.start_at,end_at:value.end_at||void 0,title:value.title?.trim()||void 0,description:value.description?.trim()||void 0,location:value.location?.trim()||void 0,all_day:value.all_day,timezone:value.timezone?.trim()||void 0,recurrence:normalizeRecurrenceRule(value.recurrence)};return deleteUndefinedFields(event),event}function compareCalendarEvents(a,b){return firstNonZeroComparison([compareTimestampStrings(a.start_at,b.start_at),(a.end_at??"").localeCompare(b.end_at??""),(a.title??"").localeCompare(b.title??""),+!!a.all_day-+!!b.all_day,(a.timezone??"").localeCompare(b.timezone??""),(a.location??"").localeCompare(b.location??""),(a.description??"").localeCompare(b.description??""),JSON.stringify(a.recurrence??{}).localeCompare(JSON.stringify(b.recurrence??{}))])}function normalizeFiles(values){if(!(!values||values.length===0))return values.map(value=>({path:normalizePathValue(value.path),scope:value.scope,note:value.note?.trim()||void 0}))}function normalizeTestRunSummaries(values){if(!values||values.length===0)return;const normalized=values.map(normalizeTestRunSummary).filter(value=>value.run_id.length>0&&value.started_at.length>0&&value.finished_at.length>0&&value.recorded_at.length>0).sort((a,b)=>firstNonZeroComparison([compareTimestampStrings(a.recorded_at,b.recorded_at),a.run_id.localeCompare(b.run_id),a.kind.localeCompare(b.kind)]));return normalized.length>0?normalized:void 0}function normalizeNonNegativeInteger(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0?Math.floor(value):void 0}function normalizePositiveInteger(value){return typeof value=="number"&&Number.isFinite(value)&&value>=1?Math.floor(value):void 0}function stringOrEmpty(value){return typeof value=="string"?value:""}function normalizeTestRunMeasurements(value){if(!Array.isArray(value))return;const normalized=value.filter(measurement=>measurement!==null&&typeof measurement=="object"&&typeof measurement.name=="string"&&measurement.name.trim().length>0&&typeof measurement.value=="number"&&Number.isFinite(measurement.value)&&typeof measurement.recorded_at=="string"&&measurement.recorded_at.trim().length>0).map(measurement=>({name:measurement.name.trim(),value:measurement.value,unit:typeof measurement.unit=="string"&&measurement.unit.trim()||void 0,threshold:typeof measurement.threshold=="number"&&Number.isFinite(measurement.threshold)?measurement.threshold:void 0,recorded_at:measurement.recorded_at.trim()})),deduplicated=[...new Map(normalized.map(measurement=>[measurement.name,measurement])).values()].sort((left,right)=>left.name.localeCompare(right.name)).slice(0,32);return deduplicated.length>0?deduplicated:void 0}function normalizeTestRunEnum(value,allowedValues){return typeof value=="string"&&allowedValues.has(value)?value:void 0}function normalizeTestRunExecutions(values){if(!Array.isArray(values))return;const executions=values.filter(execution=>execution&&typeof execution.command=="string"&&execution.command.trim().length>0).slice(0,32).map(execution=>({command:execution.command.trim(),requested_pm_context_mode:normalizeTestRunEnum(execution.requested_pm_context_mode,LINKED_TEST_PM_CONTEXT_MODE_VALUES),pm_context_mode:normalizeTestRunEnum(execution.pm_context_mode,LINKED_TEST_PM_CONTEXT_MODE_VALUES),workspace_context_mode:normalizeTestRunEnum(execution.workspace_context_mode,LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES),trust_reason:normalizeTestRunEnum(execution.trust_reason,LINKED_TEST_TRUST_REASON_VALUES)}));return executions.length>0?executions:void 0}function normalizeTestRunSummary(value){const runId=typeof value.run_id=="string"?value.run_id.trim():"",kind=value.kind==="test"||value.kind==="test-all"?value.kind:"test",status=ITEM_TEST_RUN_STATUS_VALUES.has(value.status)?value.status:"failed",summary={run_id:runId,kind,status,started_at:stringOrEmpty(value.started_at),finished_at:stringOrEmpty(value.finished_at),recorded_at:stringOrEmpty(value.recorded_at),attempt:normalizePositiveInteger(value.attempt),resumed_from:value.resumed_from?.trim()||void 0,passed:normalizeNonNegativeInteger(value.passed)??0,failed:normalizeNonNegativeInteger(value.failed)??0,skipped:normalizeNonNegativeInteger(value.skipped)??0,items:normalizeNonNegativeInteger(value.items),linked_tests:normalizeNonNegativeInteger(value.linked_tests),fail_on_skipped_triggered:value.fail_on_skipped_triggered===!0?!0:void 0,measurements:normalizeTestRunMeasurements(value.measurements),executions:normalizeTestRunExecutions(value.executions)};return deleteUndefinedFields(summary),summary}function sortTests(values){if(!(!Array.isArray(values)||values.length===0))return values.map(normalizeLinkedTest)}function normalizeTrimmedStringList(value){if(!Array.isArray(value))return;const normalized=[...new Set(value.filter(entry=>typeof entry=="string").map(entry=>entry.trim()).filter(entry=>entry.length>0))].sort((a,b)=>a.localeCompare(b));return normalized.length>0?normalized:void 0}function isPlainObjectRecord(value){if(!value||typeof value!="object"||Array.isArray(value))return!1;const prototype=Object.getPrototypeOf(value);return prototype===Object.prototype||prototype===null}function isUnsafeObjectKey(key){return key==="__proto__"||key==="constructor"||key==="prototype"}function normalizeStringRecord(value){if(!isPlainObjectRecord(value))return;const entries=Object.entries(value).map(([key,recordValue])=>[key.trim(),String(recordValue).trim()]).filter(([key,recordValue])=>key.length>0&&!isUnsafeObjectKey(key)&&recordValue.length>0).sort(([left],[right])=>left.localeCompare(right));return entries.length>0?Object.fromEntries(entries):void 0}function normalizeNumericRecord(value){if(!isPlainObjectRecord(value))return;const entries=Object.entries(value).map(([key,recordValue])=>[key.trim(),Number(recordValue)]).filter(([key,recordValue])=>key.length>0&&!isUnsafeObjectKey(key)&&Number.isFinite(recordValue)).sort(([left],[right])=>left.localeCompare(right));return entries.length>0?Object.fromEntries(entries):void 0}function normalizeLinkedTestContextMode(value){const normalized=value?.trim().toLowerCase();if(!(!normalized||!LINKED_TEST_PM_CONTEXT_MODE_VALUES.has(normalized)))return normalized}function normalizeLinkedTestWorkspaceContextMode(value){const normalized=value?.trim().toLowerCase();if(!(!normalized||!LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES.has(normalized)))return normalized}function normalizeLinkedTestProvenance(value,invalid){if(invalid===!0)return{provenance_invalid:!0};if(value===void 0)return{};if(!isPlainObjectRecord(value))return{provenance_invalid:!0};const author=trimStringOrUndefined(value.author),createdAt=trimStringOrUndefined(value.created_at),sourceKind=value.source_kind;return!author||!createdAt||!isTimestampLiteral(createdAt)||sourceKind!=="local_mutation"&&sourceKind!=="merge_union"?{provenance_invalid:!0}:{provenance:{author,created_at:createdAt,source_kind:sourceKind,source_ref:trimStringOrUndefined(value.source_ref)}}}function normalizeLinkedTest(value){const test={command:value.command?.trim()||void 0,path:value.path?normalizePathValue(value.path):void 0,scope:value.scope,timeout_seconds:typeof value.timeout_seconds=="number"&&Number.isFinite(value.timeout_seconds)&&value.timeout_seconds>0?value.timeout_seconds:void 0,pm_context_mode:normalizeLinkedTestContextMode(value.pm_context_mode),workspace_context_mode:normalizeLinkedTestWorkspaceContextMode(value.workspace_context_mode),...normalizeLinkedTestProvenance(value.provenance,value.provenance_invalid),env_set:normalizeStringRecord(value.env_set),env_clear:normalizeTrimmedStringList(value.env_clear),shared_host_safe:value.shared_host_safe===!0?!0:void 0,assert_stdout_contains:normalizeTrimmedStringList(value.assert_stdout_contains),assert_stdout_regex:normalizeTrimmedStringList(value.assert_stdout_regex),assert_stderr_contains:normalizeTrimmedStringList(value.assert_stderr_contains),assert_stderr_regex:normalizeTrimmedStringList(value.assert_stderr_regex),assert_stdout_min_lines:normalizeNonNegativeInteger(value.assert_stdout_min_lines),assert_json_field_equals:normalizeStringRecord(value.assert_json_field_equals),assert_json_field_gte:normalizeNumericRecord(value.assert_json_field_gte),note:value.note?.trim()||void 0};return deleteUndefinedFields(test),test}function sortDocs(values){if(!(!values||values.length===0))return[...values].map(value=>({path:normalizePathValue(value.path),scope:value.scope,note:value.note?.trim()||void 0})).sort((a,b)=>{const byScope=a.scope.localeCompare(b.scope);if(byScope!==0)return byScope;const byPath=a.path.localeCompare(b.path);return byPath!==0?byPath:(a.note??"").localeCompare(b.note??"")})}function trimStringOrUndefined(value){if(typeof value!="string")return;const trimmed=value.trim();return trimmed.length>0?trimmed:void 0}function normalizePlanStepLinks(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,id=trimStringOrUndefined(record.id),kind=trimStringOrUndefined(record.kind);if(!id||!kind)continue;const link={id,kind},note=trimStringOrUndefined(record.note);note&&(link.note=note),record.required_before_step===!0&&(link.required_before_step=!0),out.push(link)}return out.length>0?out:void 0}function normalizePlanStepFiles(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,path=trimStringOrUndefined(record.path);if(!path)continue;const file={path:normalizePathValue(path)};(record.scope==="project"||record.scope==="global")&&(file.scope=record.scope);const note=trimStringOrUndefined(record.note);note&&(file.note=note),out.push(file)}return out.length>0?out:void 0}function normalizePlanStepTests(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,command=trimStringOrUndefined(record.command),path=trimStringOrUndefined(record.path);if(!command&&!path)continue;const test={};command&&(test.command=command),path&&(test.path=normalizePathValue(path));const note=trimStringOrUndefined(record.note);note&&(test.note=note),out.push(test)}return out.length>0?out:void 0}function normalizePlanStepDocs(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,path=trimStringOrUndefined(record.path);if(!path)continue;const doc={path:normalizePathValue(path)};(record.scope==="project"||record.scope==="global")&&(doc.scope=record.scope);const note=trimStringOrUndefined(record.note);note&&(doc.note=note),out.push(doc)}return out.length>0?out:void 0}function normalizePlanStepEntry(entry){if(entry===null||typeof entry!="object")return;const record=entry,id=trimStringOrUndefined(record.id),title=trimStringOrUndefined(record.title),statusRaw=trimStringOrUndefined(record.status),status=statusRaw&&PLAN_STEP_STATUS_SET.has(statusRaw)?statusRaw:void 0,order=coerceFiniteNumber(record.order)??Number.NaN,created_at=typeof record.created_at=="string"?record.created_at:"",updated_at=typeof record.updated_at=="string"?record.updated_at:"";if(!id||!title||!status||!Number.isFinite(order)||!created_at||!updated_at)return;const step={id,order,title,status,created_at,updated_at};return applyPlanStepOptionalFields(step,record),step}function applyPlanStepOptionalFields(step,record){const stringFields=[["body","body"],["owner","owner"],["evidence","evidence"],["blocked_reason","blocked_reason"],["superseded_by","superseded_by"]];for(const[target,source]of stringFields){const value=trimStringOrUndefined(record[source]);value&&(step[target]=value)}const completedAt=typeof record.completed_at=="string"?record.completed_at:void 0;completedAt&&completedAt.length>0&&(step.completed_at=completedAt);const collectionFields=[["linked_items","linked_items",normalizePlanStepLinks],["files","files",normalizePlanStepFiles],["tests","tests",normalizePlanStepTests],["docs","docs",normalizePlanStepDocs]];for(const[target,source,normalize]of collectionFields){const value=normalize(record[source]);value&&(step[target]=value)}}function normalizePlanSteps(value){if(!Array.isArray(value))return;const out=value.flatMap(entry=>{const step=normalizePlanStepEntry(entry);return step?[step]:[]});return out.sort((left,right)=>left.order-right.order),out.length>0?out:void 0}function normalizePlanDecisions(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,ts=typeof record.ts=="string"?record.ts:"",author=typeof record.author=="string"?record.author:"",decision=trimStringOrUndefined(record.decision);if(!ts||!author||!decision)continue;const item={ts,author,decision},rationale=trimStringOrUndefined(record.rationale);rationale&&(item.rationale=rationale);const evidence=trimStringOrUndefined(record.evidence);evidence&&(item.evidence=evidence);const stepId=trimStringOrUndefined(record.step_id);stepId&&(item.step_id=stepId),out.push(item)}return out.length>0?out:void 0}function normalizePlanDiscoveries(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,ts=typeof record.ts=="string"?record.ts:"",author=typeof record.author=="string"?record.author:"",text=trimStringOrUndefined(record.text);if(!ts||!author||!text)continue;const item={ts,author,text},stepId=trimStringOrUndefined(record.step_id);stepId&&(item.step_id=stepId),out.push(item)}return out.length>0?out:void 0}function normalizePlanValidation(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,text=trimStringOrUndefined(record.text);if(!text)continue;const item={text},command=trimStringOrUndefined(record.command);command&&(item.command=command);const expected=trimStringOrUndefined(record.expected);expected&&(item.expected=expected),out.push(item)}return out.length>0?out:void 0}function normalizeTypeOptions(values){if(!values)return;const normalizedEntries=Object.entries(values).map(([key,value])=>[key.trim(),value.trim()]).filter(([key,value])=>key.length>0&&value.length>0).sort((left,right)=>left[0].localeCompare(right[0]));if(normalizedEntries.length!==0)return Object.fromEntries(normalizedEntries)}function normalizeBody(body){let start=0;for(;start<body.length&&body[start]===`
|
|
2
|
-
`;)start+=1;return body.slice(start).trimEnd()}function normalizeConfidenceValue(value){if(value===void 0)return;if(typeof value=="number")return value;const normalized=value.trim().toLowerCase();if(normalized==="med")return"medium";if(CONFIDENCE_TEXT_VALUES.includes(normalized))return normalized}function normalizeSeverityValue(value){if(value===void 0)return;const normalized=value.trim().toLowerCase();if(normalized==="med")return"medium";if(ISSUE_SEVERITY_VALUES.includes(normalized))return normalized}function emptyStringToUndefined(value){return value||void 0}function copyExtensionItemMetadataFields(normalized,source){const targetRecord=normalized,sourceRecord=source;for(const[key,value]of Object.entries(sourceRecord))isUnsafeObjectKey(key)||Object.prototype.hasOwnProperty.call(targetRecord,key)||value===void 0||(targetRecord[key]=value)}function coerceNormalizedRuntimeFields(normalized,runtimeContext){if(!runtimeContext?.fieldRegistry)return;const record=normalized;for(const definition of runtimeContext.fieldRegistry.definitions){const currentValue=record[definition.metadata_key];currentValue!==void 0&&(record[definition.metadata_key]=coerceRuntimeFieldValue(definition,currentValue,`metadata field "${definition.metadata_key}"
|
|
3
|
-
`,cursor),lineEnd=nextNewline===-1?normalizedContent.length:nextNewline,line=normalizedContent.slice(cursor,lineEnd).replace(/\r$/,""),afterLine=nextNewline===-1?lineEnd:lineEnd+1;if(line.trim()==="---")return{content:normalizedContent.slice(afterLine).replace(/^\s+/,""),stripped:!0};cursor=afterLine}return{content:normalizedContent,stripped:!1}}function normalizeParsedItemMetadata(itemMetadata,options){return normalizeItemMetadata(itemMetadata,{...options,onWarning:void 0})}function parseJsonMarkdownItemDocument(content,runtimeContext,options={}){const normalized=stripLeadingYamlDocument(content);normalized.stripped&&options.onWarning?.("json_markdown_leading_yaml_frontmatter_ignored");const{frontMatter,body}=splitFrontMatter(normalized.content);frontMatter||(content.trimStart().startsWith("{")&&documentSyntaxError("json_markdown","JSON front matter is not valid JSON"),documentSyntaxError("json_markdown","JSON Markdown item document is missing JSON front matter"));let parsed;try{parsed=JSON.parse(frontMatter)}catch{documentSyntaxError("json_markdown","JSON front matter is not valid JSON")}return assertValidItemMetadata(parsed,runtimeContext),{metadata:normalizeParsedItemMetadata(parsed,options),body:normalizeBody(body)}}function parseToonItemDocument(content,runtimeContext,options={}){let parsed;try{parsed=decodeToonItemContent(content).value}catch{documentSyntaxError("toon","TOON item document is not valid TOON")}assertItemMetadataCondition(typeof parsed=="object"&&parsed!==null&&!Array.isArray(parsed),"TOON item document must be an object");const record=parsed;if(
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e2f15e0b-06b0-5e02-a91e-2886f94ffc63")}catch{}})();import{encode as encodeToon}from"@toon-format/toon";import{isDeepStrictEqual}from"node:util";import{CONFIDENCE_TEXT_VALUES,ISSUE_SEVERITY_VALUES,PLAN_STEP_STATUS_VALUES,RECURRENCE_FREQUENCY_VALUES,RECURRENCE_WEEKDAY_VALUES,STATUS_VALUES,weekdayOrderIndex}from"../../types/index.js";import{coerceRuntimeFieldValue}from"../schema/runtime-field-values.js";import{resolveRuntimeFieldRegistry,resolveRuntimeStatusRegistry}from"../schema/runtime-schema.js";import{BASELINE_ITEM_FORMAT_VERSION,CURRENT_ITEM_FORMAT_VERSION,effectiveItemFormatVersion,normalizeItemFormatVersion}from"./item-format-version.js";import{normalizeStatusInput}from"./status.js";import{decodeToonItemContent}from"./toon-decode.js";import{EXIT_CODE,ITEM_METADATA_KEY_ORDER}from"../shared/constants.js";import{findFirstMergeConflictMarker}from"../shared/conflict-markers.js";import{PmCliError}from"../shared/errors.js";import{orderObject}from"../shared/serialization.js";import{compareTimestampStrings,isTimestampLiteral}from"../shared/time.js";import{coerceFiniteNumber}from"../shared/primitives.js";const LINKED_TEST_PM_CONTEXT_MODE_VALUES=new Set(["schema","tracker","auto","none"]),LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES=new Set(["source","isolated","snapshot"]),LINKED_TEST_TRUST_REASON_VALUES=new Set(["legacy","local_mutation","local_source_ref","acknowledged","invalid_provenance","foreign_source_ref"]),ITEM_TEST_RUN_STATUS_VALUES=new Set(["passed","failed","stopped","canceled"]),PLAN_STEP_STATUS_SET=new Set(PLAN_STEP_STATUS_VALUES);function normalizePathValue(value){return value.replaceAll("\\","/")}function firstNonZeroComparison(comparisons){for(const comparison of comparisons)if(comparison!==0)return comparison;return 0}function deleteUndefinedFields(record){for(const[key,value]of Object.entries(record))value===void 0&&delete record[key]}const REQUIRED_STRING_FIELDS=["id","title","description","created_at","updated_at"],STATIC_ITEM_METADATA_FIELD_SET=new Set(ITEM_METADATA_KEY_ORDER);function resolveRuntimeSchemaValidationContext(options){if(options?.schema)return{statusRegistry:resolveRuntimeStatusRegistry(options.schema),fieldRegistry:resolveRuntimeFieldRegistry(options.schema),unknownFieldPolicy:options.schema.unknown_field_policy??"allow",extensionFieldNames:new Set(options.extensionFieldNames??[]),onWarning:options.onWarning}}function runtimeFieldRequiredForType(definition,typeName){return definition.required?definition.required_types.length===0?!0:definition.required_types.map(value=>value.toLowerCase()).includes(typeName.trim().toLowerCase()):!1}function validationError(message){const field=message.match(/^([a-z_][\w.]*)\s/u)?.[1];throw new PmCliError(`Invalid item metadata: ${message}`,EXIT_CODE.GENERIC_FAILURE,{code:"item_document_invalid",reason:message.includes("required")?"missing_required_field":"schema_validation_error",...field?{field}:{},required:"Provide an item document whose metadata satisfies the active runtime schema.",why:message})}function documentSyntaxError(format,message){throw new PmCliError(message,EXIT_CODE.GENERIC_FAILURE,{code:"item_document_invalid",reason:"syntax_error",format,required:`Provide a syntactically valid ${format==="toon"?"TOON":"JSON Markdown"} item document.`,why:"The document could not be decoded far enough to validate item metadata."})}function assertSupportedItemFormat(metadata,required){if(!required||typeof metadata!="object"||metadata===null)return;const formatVersion=effectiveItemFormatVersion(metadata);if(!(formatVersion<=CURRENT_ITEM_FORMAT_VERSION))throw new PmCliError(`Stored item uses format version ${formatVersion}; this runtime supports up to ${CURRENT_ITEM_FORMAT_VERSION}. Upgrade pm before reading or changing this item.`,EXIT_CODE.CONFLICT,{code:"item_format_version_unsupported",format_version:formatVersion,required:"Upgrade to a pm runtime supporting the stored item format.",nextSteps:["Preserve the original item and history; do not lower pm_format_version to bypass compatibility checks."]})}function buildKnownItemMetadataKeys(runtimeContext){const knownKeys=new Set(STATIC_ITEM_METADATA_FIELD_SET);for(const definition of runtimeContext.fieldRegistry?.definitions??[])knownKeys.add(definition.metadata_key);for(const fieldName of runtimeContext.extensionFieldNames)knownKeys.add(fieldName);return knownKeys}function assertItemMetadataCondition(condition,message){condition||validationError(message)}function requireItemMetadataRecord(value,message){return(typeof value!="object"||value===null||Array.isArray(value))&&validationError(message),value}function assertTimestampField(record,fieldName){const rawValue=record[fieldName];assertItemMetadataCondition(typeof rawValue=="string",`${fieldName} must be a string`),assertItemMetadataCondition(isTimestampLiteral(rawValue),`${fieldName} must be a valid ISO timestamp`)}function assertPositiveIntegerField(record,fieldName,messagePrefix){const value=record[fieldName];value!==void 0&&assertItemMetadataCondition(typeof value=="number"&&Number.isInteger(value)&&value>=1,`${messagePrefix} must be an integer >= 1`)}function assertOptionalTimestampString(record,fieldName,messagePrefix){const value=record[fieldName];value!==void 0&&(assertItemMetadataCondition(typeof value=="string",`${messagePrefix} must be a string`),assertItemMetadataCondition(isTimestampLiteral(value),`${messagePrefix} must be a valid ISO timestamp`))}function assertRecurrenceWeekdays(value){if(value!==void 0){assertItemMetadataCondition(Array.isArray(value),"event.recurrence.by_weekday must be an array");for(const weekday of value){assertItemMetadataCondition(typeof weekday=="string","event.recurrence.by_weekday entries must be strings");const normalizedWeekday=weekday.trim().toLowerCase();assertItemMetadataCondition(RECURRENCE_WEEKDAY_VALUES.includes(normalizedWeekday),`event.recurrence.by_weekday entries must be one of: ${RECURRENCE_WEEKDAY_VALUES.join(", ")}`)}}}function assertRecurrenceMonthDays(value){if(value!==void 0){assertItemMetadataCondition(Array.isArray(value),"event.recurrence.by_month_day must be an array");for(const day of value)assertItemMetadataCondition(typeof day=="number"&&Number.isInteger(day)&&day>=1&&day<=31,"event.recurrence.by_month_day entries must be integers 1..31")}}function assertRecurrenceExdates(value){if(value!==void 0){assertItemMetadataCondition(Array.isArray(value),"event.recurrence.exdates must be an array");for(const exdate of value)assertItemMetadataCondition(typeof exdate=="string","event.recurrence.exdates entries must be strings"),assertItemMetadataCondition(isTimestampLiteral(exdate),"event.recurrence.exdates entries must be valid ISO timestamps")}}function assertValidRecurrenceRule(recurrence){const recurrenceRecord=requireItemMetadataRecord(recurrence,"event.recurrence must be an object");assertItemMetadataCondition(typeof recurrenceRecord.freq=="string","event.recurrence.freq must be a string");const frequency=recurrenceRecord.freq.trim().toLowerCase();assertItemMetadataCondition(RECURRENCE_FREQUENCY_VALUES.includes(frequency),`event.recurrence.freq must be one of: ${RECURRENCE_FREQUENCY_VALUES.join(", ")}`),assertPositiveIntegerField(recurrenceRecord,"interval","event.recurrence.interval"),assertPositiveIntegerField(recurrenceRecord,"count","event.recurrence.count"),assertOptionalTimestampString(recurrenceRecord,"until","event.recurrence.until"),assertRecurrenceWeekdays(recurrenceRecord.by_weekday),assertRecurrenceMonthDays(recurrenceRecord.by_month_day),assertRecurrenceExdates(recurrenceRecord.exdates)}function assertRequiredItemMetadataFields(record){for(const fieldName of REQUIRED_STRING_FIELDS)assertItemMetadataCondition(typeof record[fieldName]=="string",`${fieldName} is required and must be a string`);const itemType=record.type;assertItemMetadataCondition(typeof itemType=="string"&&itemType.trim().length>0,"type must be a non-empty string");const formatVersion=record.pm_format_version;return formatVersion!==void 0&&assertItemMetadataCondition(typeof formatVersion=="number"&&Number.isInteger(formatVersion)&&formatVersion>=BASELINE_ITEM_FORMAT_VERSION,`pm_format_version must be an integer >= ${BASELINE_ITEM_FORMAT_VERSION}`),itemType}function assertStatusItemMetadataField(record,runtimeContext){const status=record.status;assertItemMetadataCondition(typeof status=="string"&&status.trim().length>0,"status must be a non-empty string");const statusRegistry=runtimeContext?.statusRegistry,normalizedStatus=normalizeStatusInput(status,statusRegistry),statusDomain=statusRegistry?statusRegistry.definitions.map(definition=>definition.id):[...STATUS_VALUES];assertItemMetadataCondition(normalizedStatus!==void 0,`status must be one of: ${statusDomain.join(", ")}`)}function assertPriorityAndTags(record){const priority=record.priority;assertItemMetadataCondition(typeof priority=="number"&&Number.isInteger(priority)&&[0,1,2,3,4].includes(priority),"priority must be an integer 0..4");const tags=record.tags;assertItemMetadataCondition(Array.isArray(tags),"tags must be an array");for(const tag of tags)assertItemMetadataCondition(typeof tag=="string","tags entries must be strings")}function assertConfidenceItemMetadataField(record){const confidence=record.confidence;if(confidence!==void 0){if(typeof confidence=="number"){assertItemMetadataCondition(Number.isInteger(confidence)&&confidence>=0&&confidence<=100,"confidence number value must be an integer 0..100");return}if(typeof confidence=="string"){const normalizedConfidence=confidence.trim().toLowerCase(),isKnownTextConfidence=normalizedConfidence==="med"||CONFIDENCE_TEXT_VALUES.includes(normalizedConfidence);assertItemMetadataCondition(isKnownTextConfidence,`confidence string value must be one of: ${[...CONFIDENCE_TEXT_VALUES,"med"].join(", ")}`);return}assertItemMetadataCondition(!1,"confidence must be a number or string")}}function assertSeverityItemMetadataField(record){const severity=record.severity;if(severity===void 0)return;typeof severity!="string"&&validationError("severity must be a string");const normalizedSeverity=severity.trim().toLowerCase(),isKnownSeverity=normalizedSeverity==="med"||ISSUE_SEVERITY_VALUES.includes(normalizedSeverity);assertItemMetadataCondition(isKnownSeverity,`severity value must be one of: ${[...ISSUE_SEVERITY_VALUES,"med"].join(", ")}`)}function assertRegressionItemMetadataField(record){record.regression!==void 0&&typeof record.regression!="boolean"&&validationError("regression must be a boolean")}function assertReminderEntries(record){const reminders=record.reminders;if(reminders!==void 0){assertItemMetadataCondition(Array.isArray(reminders),"reminders must be an array");for(const reminder of reminders){const reminderRecord=requireItemMetadataRecord(reminder,"reminders entries must be objects");assertItemMetadataCondition(typeof reminderRecord.at=="string","reminder.at must be a string"),assertItemMetadataCondition(isTimestampLiteral(reminderRecord.at),"reminder.at must be a valid ISO timestamp"),assertItemMetadataCondition(typeof reminderRecord.text=="string","reminder.text must be a string"),assertItemMetadataCondition(reminderRecord.text.trim().length>0,"reminder.text must not be empty")}}}function assertEventStringFields(eventRecord){for(const stringField of["title","description","location","timezone"])eventRecord[stringField]!==void 0&&(assertItemMetadataCondition(typeof eventRecord[stringField]=="string",`event.${stringField} must be a string`),assertItemMetadataCondition(eventRecord[stringField].trim().length>0,`event.${stringField} must not be empty`))}function assertEventRecurrence(eventRecord){eventRecord.recurrence!==void 0&&(assertValidRecurrenceRule(eventRecord.recurrence),eventRecord.recurrence.until!==void 0&&assertItemMetadataCondition(compareTimestampStrings(eventRecord.recurrence.until,eventRecord.start_at)>=0,"event.recurrence.until must be at or after event.start_at"))}function assertCalendarEventEntry(event){const eventRecord=requireItemMetadataRecord(event,"events entries must be objects");assertItemMetadataCondition(typeof eventRecord.start_at=="string","event.start_at must be a string"),assertItemMetadataCondition(isTimestampLiteral(eventRecord.start_at),"event.start_at must be a valid ISO timestamp"),eventRecord.end_at!==void 0&&(assertItemMetadataCondition(typeof eventRecord.end_at=="string","event.end_at must be a string"),assertItemMetadataCondition(isTimestampLiteral(eventRecord.end_at),"event.end_at must be a valid ISO timestamp"),assertItemMetadataCondition(compareTimestampStrings(eventRecord.end_at,eventRecord.start_at)>0,"event.end_at must be after event.start_at")),assertEventStringFields(eventRecord),eventRecord.all_day!==void 0&&assertItemMetadataCondition(typeof eventRecord.all_day=="boolean","event.all_day must be a boolean"),assertEventRecurrence(eventRecord)}function assertCalendarEvents(record){const events=record.events;if(events!==void 0){assertItemMetadataCondition(Array.isArray(events),"events must be an array");for(const event of events)assertCalendarEventEntry(event)}}function assertOptionalStringFields(record){for(const fieldName of["source_type","source_owner","design","external_ref"]){const value=record[fieldName];value!==void 0&&assertItemMetadataCondition(typeof value=="string",`${fieldName} must be a string`)}}function assertTypeOptionsField(record){const typeOptions=record.type_options;if(typeOptions===void 0)return;const typeOptionsRecord=requireItemMetadataRecord(typeOptions,"type_options must be an object");for(const[optionKey,optionValue]of Object.entries(typeOptionsRecord))assertItemMetadataCondition(optionKey.trim().length>0,"type_options keys must be non-empty"),assertItemMetadataCondition(typeof optionValue=="string","type_options values must be strings"),assertItemMetadataCondition(optionValue.trim().length>0,"type_options values must be non-empty strings")}function coerceRuntimeItemMetadataFields(record,itemType,runtimeContext){if(runtimeContext?.fieldRegistry)for(const definition of runtimeContext.fieldRegistry.definitions){const fieldValue=record[definition.metadata_key];if(fieldValue===void 0){runtimeFieldRequiredForType(definition,itemType)&&validationError(`missing required schema field: ${definition.metadata_key}`);continue}try{record[definition.metadata_key]=coerceRuntimeFieldValue(definition,fieldValue,`metadata field "${definition.metadata_key}"`,"metadata")}catch(error){validationError(String(error?.message).replace(/^Invalid\s+/u,""))}}}function assertRuntimeUnknownItemMetadataFields(record,runtimeContext){if(!runtimeContext||runtimeContext.unknownFieldPolicy==="allow")return;const knownKeys=buildKnownItemMetadataKeys(runtimeContext),unknownKeys=Object.keys(record).filter(key=>!knownKeys.has(key)).sort((left,right)=>left.localeCompare(right));unknownKeys.length!==0&&(runtimeContext.unknownFieldPolicy==="reject"?validationError(`unknown schema fields are not allowed: ${unknownKeys.join(", ")}`):runtimeContext.onWarning?.(`item_unknown_schema_fields:${unknownKeys.join(",")}`))}function assertValidItemMetadata(itemMetadata,runtimeContext){const record=requireItemMetadataRecord(itemMetadata,"item metadata must be an object"),itemType=assertRequiredItemMetadataFields(record);assertStatusItemMetadataField(record,runtimeContext),assertPriorityAndTags(record),assertConfidenceItemMetadataField(record),assertSeverityItemMetadataField(record),assertRegressionItemMetadataField(record),assertTimestampField(record,"created_at"),assertTimestampField(record,"updated_at"),record.deadline!==void 0&&assertTimestampField(record,"deadline"),assertReminderEntries(record),assertCalendarEvents(record),assertOptionalTimestampString(record,"closed_at","closed_at"),assertOptionalTimestampString(record,"completed_at","completed_at"),assertOptionalStringFields(record),assertTypeOptionsField(record),coerceRuntimeItemMetadataFields(record,itemType,runtimeContext),assertRuntimeUnknownItemMetadataFields(record,runtimeContext)}function sortDependencies(values){if(!(!values||values.length===0))return[...values].map(value=>({id:value.id.trim(),kind:value.kind,created_at:value.created_at,author:value.author?.trim()||void 0,source_kind:value.source_kind?.trim()||void 0,author_source:value.author_source})).sort((a,b)=>{const byCreated=compareTimestampStrings(a.created_at,b.created_at);if(byCreated!==0)return byCreated;const byId=a.id.localeCompare(b.id);if(byId!==0)return byId;const byKind=a.kind.localeCompare(b.kind);return byKind!==0?byKind:(a.source_kind??"").localeCompare(b.source_kind??"")})}function sortLogValues(values){if(!(!values||values.length===0))return[...values].sort((a,b)=>{const byCreated=compareTimestampStrings(a.created_at,b.created_at);if(byCreated!==0)return byCreated;const byText=a.text.localeCompare(b.text);return byText!==0?byText:a.author.localeCompare(b.author)})}function sortReminders(values){if(!values||values.length===0)return;const normalized=[...values].map(value=>({at:value.at,text:value.text.trim()})).filter(value=>value.text.length>0).sort((a,b)=>{const byAt=compareTimestampStrings(a.at,b.at);return byAt!==0?byAt:a.text.localeCompare(b.text)});return normalized.length===0?void 0:normalized}function normalizeRecurrenceRule(value){if(!value)return;const normalizedFrequency=value.freq.trim().toLowerCase();if(!RECURRENCE_FREQUENCY_VALUES.includes(normalizedFrequency))return;const byWeekday=Array.from(new Set((value.by_weekday??[]).map(weekday=>weekday.trim().toLowerCase()).filter(weekday=>RECURRENCE_WEEKDAY_VALUES.includes(weekday)))).sort((a,b)=>weekdayOrderIndex(a)-weekdayOrderIndex(b)),byMonthDay=Array.from(new Set((value.by_month_day??[]).filter(day=>Number.isInteger(day)&&day>=1&&day<=31).map(day=>day))).sort((a,b)=>a-b),exdates=Array.from(new Set((value.exdates??[]).map(timestamp=>timestamp.trim()).filter(timestamp=>isTimestampLiteral(timestamp)))).sort((a,b)=>compareTimestampStrings(a,b)),normalized={freq:normalizedFrequency,interval:value.interval!==void 0&&value.interval>1?value.interval:void 0,count:value.count,until:value.until?.trim()||void 0,by_weekday:byWeekday.length>0?byWeekday:void 0,by_month_day:byMonthDay.length>0?byMonthDay:void 0,exdates:exdates.length>0?exdates:void 0};for(const[key,fieldValue]of Object.entries(normalized))fieldValue===void 0&&delete normalized[key];return normalized}function sortEvents(values){return!Array.isArray(values)||values.length===0?void 0:[...values].map(normalizeCalendarEvent).sort(compareCalendarEvents)}function normalizeCalendarEvent(value){const event={start_at:value.start_at,end_at:value.end_at||void 0,title:value.title?.trim()||void 0,description:value.description?.trim()||void 0,location:value.location?.trim()||void 0,all_day:value.all_day,timezone:value.timezone?.trim()||void 0,recurrence:normalizeRecurrenceRule(value.recurrence)};return deleteUndefinedFields(event),event}function compareCalendarEvents(a,b){return firstNonZeroComparison([compareTimestampStrings(a.start_at,b.start_at),(a.end_at??"").localeCompare(b.end_at??""),(a.title??"").localeCompare(b.title??""),+!!a.all_day-+!!b.all_day,(a.timezone??"").localeCompare(b.timezone??""),(a.location??"").localeCompare(b.location??""),(a.description??"").localeCompare(b.description??""),JSON.stringify(a.recurrence??{}).localeCompare(JSON.stringify(b.recurrence??{}))])}function normalizeFiles(values){if(!(!values||values.length===0))return values.map(value=>({path:normalizePathValue(value.path),scope:value.scope,note:value.note?.trim()||void 0}))}function normalizeTestRunSummaries(values){if(!values||values.length===0)return;const normalized=values.map(normalizeTestRunSummary).filter(value=>value.run_id.length>0&&value.started_at.length>0&&value.finished_at.length>0&&value.recorded_at.length>0).sort((a,b)=>firstNonZeroComparison([compareTimestampStrings(a.recorded_at,b.recorded_at),a.run_id.localeCompare(b.run_id),a.kind.localeCompare(b.kind)]));return normalized.length>0?normalized:void 0}function normalizeNonNegativeInteger(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0?Math.floor(value):void 0}function normalizePositiveInteger(value){return typeof value=="number"&&Number.isFinite(value)&&value>=1?Math.floor(value):void 0}function stringOrEmpty(value){return typeof value=="string"?value:""}function normalizeTestRunMeasurements(value){if(!Array.isArray(value))return;const normalized=value.filter(measurement=>measurement!==null&&typeof measurement=="object"&&typeof measurement.name=="string"&&measurement.name.trim().length>0&&typeof measurement.value=="number"&&Number.isFinite(measurement.value)&&typeof measurement.recorded_at=="string"&&measurement.recorded_at.trim().length>0).map(measurement=>({name:measurement.name.trim(),value:measurement.value,unit:typeof measurement.unit=="string"&&measurement.unit.trim()||void 0,threshold:typeof measurement.threshold=="number"&&Number.isFinite(measurement.threshold)?measurement.threshold:void 0,recorded_at:measurement.recorded_at.trim()})),deduplicated=[...new Map(normalized.map(measurement=>[measurement.name,measurement])).values()].sort((left,right)=>left.name.localeCompare(right.name)).slice(0,32);return deduplicated.length>0?deduplicated:void 0}function normalizeTestRunEnum(value,allowedValues){return typeof value=="string"&&allowedValues.has(value)?value:void 0}function normalizeTestRunExecutions(values){if(!Array.isArray(values))return;const executions=values.filter(execution=>execution&&typeof execution.command=="string"&&execution.command.trim().length>0).slice(0,32).map(execution=>({command:execution.command.trim(),requested_pm_context_mode:normalizeTestRunEnum(execution.requested_pm_context_mode,LINKED_TEST_PM_CONTEXT_MODE_VALUES),pm_context_mode:normalizeTestRunEnum(execution.pm_context_mode,LINKED_TEST_PM_CONTEXT_MODE_VALUES),workspace_context_mode:normalizeTestRunEnum(execution.workspace_context_mode,LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES),trust_reason:normalizeTestRunEnum(execution.trust_reason,LINKED_TEST_TRUST_REASON_VALUES)}));return executions.length>0?executions:void 0}function normalizeTestRunSummary(value){const runId=typeof value.run_id=="string"?value.run_id.trim():"",kind=value.kind==="test"||value.kind==="test-all"?value.kind:"test",status=ITEM_TEST_RUN_STATUS_VALUES.has(value.status)?value.status:"failed",summary={run_id:runId,kind,status,started_at:stringOrEmpty(value.started_at),finished_at:stringOrEmpty(value.finished_at),recorded_at:stringOrEmpty(value.recorded_at),attempt:normalizePositiveInteger(value.attempt),resumed_from:value.resumed_from?.trim()||void 0,passed:normalizeNonNegativeInteger(value.passed)??0,failed:normalizeNonNegativeInteger(value.failed)??0,skipped:normalizeNonNegativeInteger(value.skipped)??0,items:normalizeNonNegativeInteger(value.items),linked_tests:normalizeNonNegativeInteger(value.linked_tests),fail_on_skipped_triggered:value.fail_on_skipped_triggered===!0?!0:void 0,measurements:normalizeTestRunMeasurements(value.measurements),executions:normalizeTestRunExecutions(value.executions)};return deleteUndefinedFields(summary),summary}function sortTests(values){if(!(!Array.isArray(values)||values.length===0))return values.map(normalizeLinkedTest)}function normalizeTrimmedStringList(value){if(!Array.isArray(value))return;const normalized=[...new Set(value.filter(entry=>typeof entry=="string").map(entry=>entry.trim()).filter(entry=>entry.length>0))].sort((a,b)=>a.localeCompare(b));return normalized.length>0?normalized:void 0}function isPlainObjectRecord(value){if(!value||typeof value!="object"||Array.isArray(value))return!1;const prototype=Object.getPrototypeOf(value);return prototype===Object.prototype||prototype===null}function isUnsafeObjectKey(key){return key==="__proto__"||key==="constructor"||key==="prototype"}function normalizeStringRecord(value){if(!isPlainObjectRecord(value))return;const entries=Object.entries(value).map(([key,recordValue])=>[key.trim(),String(recordValue).trim()]).filter(([key,recordValue])=>key.length>0&&!isUnsafeObjectKey(key)&&recordValue.length>0).sort(([left],[right])=>left.localeCompare(right));return entries.length>0?Object.fromEntries(entries):void 0}function normalizeNumericRecord(value){if(!isPlainObjectRecord(value))return;const entries=Object.entries(value).map(([key,recordValue])=>[key.trim(),Number(recordValue)]).filter(([key,recordValue])=>key.length>0&&!isUnsafeObjectKey(key)&&Number.isFinite(recordValue)).sort(([left],[right])=>left.localeCompare(right));return entries.length>0?Object.fromEntries(entries):void 0}function normalizeLinkedTestContextMode(value){const normalized=value?.trim().toLowerCase();if(!(!normalized||!LINKED_TEST_PM_CONTEXT_MODE_VALUES.has(normalized)))return normalized}function normalizeLinkedTestWorkspaceContextMode(value){const normalized=value?.trim().toLowerCase();if(!(!normalized||!LINKED_TEST_WORKSPACE_CONTEXT_MODE_VALUES.has(normalized)))return normalized}function normalizeLinkedTestProvenance(value,invalid){if(invalid===!0)return{provenance_invalid:!0};if(value===void 0)return{};if(!isPlainObjectRecord(value))return{provenance_invalid:!0};const author=trimStringOrUndefined(value.author),createdAt=trimStringOrUndefined(value.created_at),sourceKind=value.source_kind;return!author||!createdAt||!isTimestampLiteral(createdAt)||sourceKind!=="local_mutation"&&sourceKind!=="merge_union"?{provenance_invalid:!0}:{provenance:{author,created_at:createdAt,source_kind:sourceKind,source_ref:trimStringOrUndefined(value.source_ref)}}}function normalizeLinkedTest(value){const test={command:value.command?.trim()||void 0,path:value.path?normalizePathValue(value.path):void 0,scope:value.scope,timeout_seconds:typeof value.timeout_seconds=="number"&&Number.isFinite(value.timeout_seconds)&&value.timeout_seconds>0?value.timeout_seconds:void 0,pm_context_mode:normalizeLinkedTestContextMode(value.pm_context_mode),workspace_context_mode:normalizeLinkedTestWorkspaceContextMode(value.workspace_context_mode),...normalizeLinkedTestProvenance(value.provenance,value.provenance_invalid),env_set:normalizeStringRecord(value.env_set),env_clear:normalizeTrimmedStringList(value.env_clear),shared_host_safe:value.shared_host_safe===!0?!0:void 0,assert_stdout_contains:normalizeTrimmedStringList(value.assert_stdout_contains),assert_stdout_regex:normalizeTrimmedStringList(value.assert_stdout_regex),assert_stderr_contains:normalizeTrimmedStringList(value.assert_stderr_contains),assert_stderr_regex:normalizeTrimmedStringList(value.assert_stderr_regex),assert_stdout_min_lines:normalizeNonNegativeInteger(value.assert_stdout_min_lines),assert_json_field_equals:normalizeStringRecord(value.assert_json_field_equals),assert_json_field_gte:normalizeNumericRecord(value.assert_json_field_gte),note:value.note?.trim()||void 0};return deleteUndefinedFields(test),test}function sortDocs(values){if(!(!values||values.length===0))return[...values].map(value=>({path:normalizePathValue(value.path),scope:value.scope,note:value.note?.trim()||void 0})).sort((a,b)=>{const byScope=a.scope.localeCompare(b.scope);if(byScope!==0)return byScope;const byPath=a.path.localeCompare(b.path);return byPath!==0?byPath:(a.note??"").localeCompare(b.note??"")})}function trimStringOrUndefined(value){if(typeof value!="string")return;const trimmed=value.trim();return trimmed.length>0?trimmed:void 0}function normalizePlanStepLinks(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,id=trimStringOrUndefined(record.id),kind=trimStringOrUndefined(record.kind);if(!id||!kind)continue;const link={id,kind},note=trimStringOrUndefined(record.note);note&&(link.note=note),record.required_before_step===!0&&(link.required_before_step=!0),out.push(link)}return out.length>0?out:void 0}function normalizePlanStepFiles(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,path=trimStringOrUndefined(record.path);if(!path)continue;const file={path:normalizePathValue(path)};(record.scope==="project"||record.scope==="global")&&(file.scope=record.scope);const note=trimStringOrUndefined(record.note);note&&(file.note=note),out.push(file)}return out.length>0?out:void 0}function normalizePlanStepTests(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,command=trimStringOrUndefined(record.command),path=trimStringOrUndefined(record.path);if(!command&&!path)continue;const test={};command&&(test.command=command),path&&(test.path=normalizePathValue(path));const note=trimStringOrUndefined(record.note);note&&(test.note=note),out.push(test)}return out.length>0?out:void 0}function normalizePlanStepDocs(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,path=trimStringOrUndefined(record.path);if(!path)continue;const doc={path:normalizePathValue(path)};(record.scope==="project"||record.scope==="global")&&(doc.scope=record.scope);const note=trimStringOrUndefined(record.note);note&&(doc.note=note),out.push(doc)}return out.length>0?out:void 0}function normalizePlanStepEntry(entry){if(entry===null||typeof entry!="object")return;const record=entry,id=trimStringOrUndefined(record.id),title=trimStringOrUndefined(record.title),statusRaw=trimStringOrUndefined(record.status),status=statusRaw&&PLAN_STEP_STATUS_SET.has(statusRaw)?statusRaw:void 0,order=coerceFiniteNumber(record.order)??Number.NaN,created_at=typeof record.created_at=="string"?record.created_at:"",updated_at=typeof record.updated_at=="string"?record.updated_at:"";if(!id||!title||!status||!Number.isFinite(order)||!created_at||!updated_at)return;const step={id,order,title,status,created_at,updated_at};return applyPlanStepOptionalFields(step,record),step}function applyPlanStepOptionalFields(step,record){const stringFields=[["body","body"],["owner","owner"],["evidence","evidence"],["blocked_reason","blocked_reason"],["superseded_by","superseded_by"]];for(const[target,source]of stringFields){const value=trimStringOrUndefined(record[source]);value&&(step[target]=value)}const completedAt=typeof record.completed_at=="string"?record.completed_at:void 0;completedAt&&completedAt.length>0&&(step.completed_at=completedAt);const collectionFields=[["linked_items","linked_items",normalizePlanStepLinks],["files","files",normalizePlanStepFiles],["tests","tests",normalizePlanStepTests],["docs","docs",normalizePlanStepDocs]];for(const[target,source,normalize]of collectionFields){const value=normalize(record[source]);value&&(step[target]=value)}}function normalizePlanSteps(value){if(!Array.isArray(value))return;const out=value.flatMap(entry=>{const step=normalizePlanStepEntry(entry);return step?[step]:[]});return out.sort((left,right)=>left.order-right.order),out.length>0?out:void 0}function normalizePlanDecisions(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,ts=typeof record.ts=="string"?record.ts:"",author=typeof record.author=="string"?record.author:"",decision=trimStringOrUndefined(record.decision);if(!ts||!author||!decision)continue;const item={ts,author,decision},rationale=trimStringOrUndefined(record.rationale);rationale&&(item.rationale=rationale);const evidence=trimStringOrUndefined(record.evidence);evidence&&(item.evidence=evidence);const stepId=trimStringOrUndefined(record.step_id);stepId&&(item.step_id=stepId),out.push(item)}return out.length>0?out:void 0}function normalizePlanDiscoveries(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,ts=typeof record.ts=="string"?record.ts:"",author=typeof record.author=="string"?record.author:"",text=trimStringOrUndefined(record.text);if(!ts||!author||!text)continue;const item={ts,author,text},stepId=trimStringOrUndefined(record.step_id);stepId&&(item.step_id=stepId),out.push(item)}return out.length>0?out:void 0}function normalizePlanValidation(value){if(!Array.isArray(value))return;const out=[];for(const entry of value){if(entry===null||typeof entry!="object")continue;const record=entry,text=trimStringOrUndefined(record.text);if(!text)continue;const item={text},command=trimStringOrUndefined(record.command);command&&(item.command=command);const expected=trimStringOrUndefined(record.expected);expected&&(item.expected=expected),out.push(item)}return out.length>0?out:void 0}function normalizeTypeOptions(values){if(!values)return;const normalizedEntries=Object.entries(values).map(([key,value])=>[key.trim(),value.trim()]).filter(([key,value])=>key.length>0&&value.length>0).sort((left,right)=>left[0].localeCompare(right[0]));if(normalizedEntries.length!==0)return Object.fromEntries(normalizedEntries)}function normalizeBody(body){let start=0;for(;start<body.length&&body[start]===`
|
|
2
|
+
`;)start+=1;return body.slice(start).trimEnd()}function normalizeConfidenceValue(value){if(value===void 0)return;if(typeof value=="number")return value;const normalized=value.trim().toLowerCase();if(normalized==="med")return"medium";if(CONFIDENCE_TEXT_VALUES.includes(normalized))return normalized}function normalizeSeverityValue(value){if(value===void 0)return;const normalized=value.trim().toLowerCase();if(normalized==="med")return"medium";if(ISSUE_SEVERITY_VALUES.includes(normalized))return normalized}function emptyStringToUndefined(value){return value||void 0}function copyExtensionItemMetadataFields(normalized,source){const targetRecord=normalized,sourceRecord=source;for(const[key,value]of Object.entries(sourceRecord))isUnsafeObjectKey(key)||Object.prototype.hasOwnProperty.call(targetRecord,key)||value===void 0||(targetRecord[key]=value)}function coerceNormalizedRuntimeFields(normalized,runtimeContext){if(!runtimeContext?.fieldRegistry)return;const record=normalized;for(const definition of runtimeContext.fieldRegistry.definitions){const currentValue=record[definition.metadata_key];currentValue!==void 0&&(record[definition.metadata_key]=coerceRuntimeFieldValue(definition,currentValue,`metadata field "${definition.metadata_key}"`,"metadata"))}}function assertNormalizedUnknownFields(normalized,runtimeContext){if(!runtimeContext||runtimeContext.unknownFieldPolicy==="allow")return;const knownKeys=buildKnownItemMetadataKeys(runtimeContext),unknownKeys=Object.keys(normalized).filter(key=>!knownKeys.has(key)).sort((left,right)=>left.localeCompare(right));unknownKeys.length>0&&runtimeContext.unknownFieldPolicy==="reject"&&validationError(`unknown schema fields are not allowed: ${unknownKeys.join(", ")}`),unknownKeys.length>0&&runtimeContext.onWarning?.(`item_unknown_schema_fields:${unknownKeys.join(",")}`)}function normalizeItemMetadata(itemMetadata,options={}){const runtimeContext=resolveRuntimeSchemaValidationContext(options),normalizedStatus=normalizeStatusInput(itemMetadata.status,runtimeContext?.statusRegistry)??itemMetadata.status,tags=Array.from(new Set((Array.isArray(itemMetadata.tags)?itemMetadata.tags:[]).filter(tag=>typeof tag=="string").map(tag=>tag.trim().toLowerCase()).filter(Boolean))).sort((a,b)=>a.localeCompare(b)),normalized={id:itemMetadata.id,title:itemMetadata.title,description:itemMetadata.description,type:itemMetadata.type,pm_format_version:normalizeItemFormatVersion(itemMetadata.pm_format_version),source_type:trimStringOrUndefined(itemMetadata.source_type),type_options:normalizeTypeOptions(itemMetadata.type_options),status:normalizedStatus,priority:itemMetadata.priority,tags,created_at:itemMetadata.created_at,updated_at:itemMetadata.updated_at,dependencies:sortDependencies(itemMetadata.dependencies),comments:sortLogValues(itemMetadata.comments),notes:sortLogValues(itemMetadata.notes),learnings:sortLogValues(itemMetadata.learnings),files:normalizeFiles(itemMetadata.files),tests:sortTests(itemMetadata.tests),test_runs:normalizeTestRunSummaries(itemMetadata.test_runs),docs:sortDocs(itemMetadata.docs),deadline:emptyStringToUndefined(itemMetadata.deadline),reminders:sortReminders(itemMetadata.reminders),events:sortEvents(itemMetadata.events),closed_at:emptyStringToUndefined(itemMetadata.closed_at),completed_at:emptyStringToUndefined(itemMetadata.completed_at),assignee:trimStringOrUndefined(itemMetadata.assignee),claim_principal:trimStringOrUndefined(itemMetadata.claim_principal),source_owner:trimStringOrUndefined(itemMetadata.source_owner),author:emptyStringToUndefined(itemMetadata.author),estimated_minutes:itemMetadata.estimated_minutes,acceptance_criteria:itemMetadata.acceptance_criteria??void 0,design:itemMetadata.design??void 0,external_ref:itemMetadata.external_ref??void 0,definition_of_ready:trimStringOrUndefined(itemMetadata.definition_of_ready),order:itemMetadata.order,goal:trimStringOrUndefined(itemMetadata.goal),objective:trimStringOrUndefined(itemMetadata.objective),value:trimStringOrUndefined(itemMetadata.value),impact:trimStringOrUndefined(itemMetadata.impact),outcome:trimStringOrUndefined(itemMetadata.outcome),why_now:trimStringOrUndefined(itemMetadata.why_now),parent:trimStringOrUndefined(itemMetadata.parent),reviewer:trimStringOrUndefined(itemMetadata.reviewer),risk:itemMetadata.risk??void 0,confidence:normalizeConfidenceValue(itemMetadata.confidence),sprint:trimStringOrUndefined(itemMetadata.sprint),release:trimStringOrUndefined(itemMetadata.release),blocked_by:trimStringOrUndefined(itemMetadata.blocked_by),blocked_reason:trimStringOrUndefined(itemMetadata.blocked_reason),unblock_note:trimStringOrUndefined(itemMetadata.unblock_note),reporter:trimStringOrUndefined(itemMetadata.reporter),severity:normalizeSeverityValue(itemMetadata.severity),environment:trimStringOrUndefined(itemMetadata.environment),repro_steps:trimStringOrUndefined(itemMetadata.repro_steps),resolution:trimStringOrUndefined(itemMetadata.resolution),expected_result:trimStringOrUndefined(itemMetadata.expected_result),actual_result:trimStringOrUndefined(itemMetadata.actual_result),affected_version:trimStringOrUndefined(itemMetadata.affected_version),fixed_version:trimStringOrUndefined(itemMetadata.fixed_version),component:trimStringOrUndefined(itemMetadata.component),regression:itemMetadata.regression,customer_impact:trimStringOrUndefined(itemMetadata.customer_impact),close_reason:emptyStringToUndefined(itemMetadata.close_reason),plan_mode:trimStringOrUndefined(itemMetadata.plan_mode),plan_scope:trimStringOrUndefined(itemMetadata.plan_scope),plan_harness:trimStringOrUndefined(itemMetadata.plan_harness),plan_resume_context:trimStringOrUndefined(itemMetadata.plan_resume_context),plan_steps:normalizePlanSteps(itemMetadata.plan_steps),plan_decisions:normalizePlanDecisions(itemMetadata.plan_decisions),plan_discoveries:normalizePlanDiscoveries(itemMetadata.plan_discoveries),plan_validation:normalizePlanValidation(itemMetadata.plan_validation)};return copyExtensionItemMetadataFields(normalized,itemMetadata),coerceNormalizedRuntimeFields(normalized,runtimeContext),assertNormalizedUnknownFields(normalized,runtimeContext),deleteUndefinedFields(normalized),normalized}function orderItemMetadata(itemMetadata){return orderObject(itemMetadata,ITEM_METADATA_KEY_ORDER)}function findJsonObjectEnd(content){let depth=0,inString=!1,escaped=!1;for(let i=0;i<content.length;i+=1){const char=content[i];if(inString){if(escaped){escaped=!1;continue}if(char==="\\"){escaped=!0;continue}char==='"'&&(inString=!1);continue}if(char==='"'){inString=!0;continue}if(char==="{"){depth+=1;continue}if(char==="}"&&(depth-=1,depth===0))return i}return-1}function splitFrontMatter(content){if(!content.startsWith("{"))return{frontMatter:"",body:content};const end=findJsonObjectEnd(content);if(end<0)return{frontMatter:"",body:content};const frontMatter=content.slice(0,end+1),body=content.slice(end+1).replace(/^\r?\n+/,"");return{frontMatter,body}}function stripLeadingYamlDocument(content){const normalizedContent=content.charCodeAt(0)===65279?content.slice(1):content,opener=normalizedContent.match(/^[ \t]*---[ \t]*(?:\r?\n|$)/);if(!opener)return{content:normalizedContent,stripped:!1};let cursor=opener[0].length;for(;cursor<normalizedContent.length;){const nextNewline=normalizedContent.indexOf(`
|
|
3
|
+
`,cursor),lineEnd=nextNewline===-1?normalizedContent.length:nextNewline,line=normalizedContent.slice(cursor,lineEnd).replace(/\r$/,""),afterLine=nextNewline===-1?lineEnd:lineEnd+1;if(line.trim()==="---")return{content:normalizedContent.slice(afterLine).replace(/^\s+/,""),stripped:!0};cursor=afterLine}return{content:normalizedContent,stripped:!1}}function normalizeParsedItemMetadata(itemMetadata,options){return normalizeItemMetadata(itemMetadata,{...options,onWarning:void 0})}function parseJsonMarkdownItemDocument(content,runtimeContext,options={}){const normalized=stripLeadingYamlDocument(content);normalized.stripped&&options.onWarning?.("json_markdown_leading_yaml_frontmatter_ignored");const{frontMatter,body}=splitFrontMatter(normalized.content);frontMatter||(content.trimStart().startsWith("{")&&documentSyntaxError("json_markdown","JSON front matter is not valid JSON"),documentSyntaxError("json_markdown","JSON Markdown item document is missing JSON front matter"));let parsed;try{parsed=JSON.parse(frontMatter)}catch{documentSyntaxError("json_markdown","JSON front matter is not valid JSON")}return assertSupportedItemFormat(parsed,options.requireSupportedFormat),assertValidItemMetadata(parsed,runtimeContext),{metadata:normalizeParsedItemMetadata(parsed,options),body:normalizeBody(body)}}function parseToonItemDocument(content,runtimeContext,options={}){let parsed;try{parsed=decodeToonItemContent(content).value}catch{documentSyntaxError("toon","TOON item document is not valid TOON")}assertItemMetadataCondition(typeof parsed=="object"&&parsed!==null&&!Array.isArray(parsed),"TOON item document must be an object");const record=parsed;if(assertSupportedItemFormat(Object.prototype.hasOwnProperty.call(record,"front_matter")?record.front_matter:record,options.requireSupportedFormat),!REQUIRED_STRING_FIELDS.some(fieldName=>Object.prototype.hasOwnProperty.call(record,fieldName))&&!Object.prototype.hasOwnProperty.call(record,"front_matter")&&documentSyntaxError("toon","TOON input does not have the shape of an item document"),Object.prototype.hasOwnProperty.call(record,"front_matter"))return assertValidItemMetadata(record.front_matter,runtimeContext),assertItemMetadataCondition(record.body===void 0||typeof record.body=="string","TOON item document body must be a string"),{metadata:normalizeParsedItemMetadata(record.front_matter,options),body:normalizeBody(typeof record.body=="string"?record.body:"")};const{body,...itemMetadataRecord}=record;return assertItemMetadataCondition(body===void 0||typeof body=="string","TOON item document body must be a string"),assertValidItemMetadata(itemMetadataRecord,runtimeContext),{metadata:normalizeParsedItemMetadata(itemMetadataRecord,options),body:normalizeBody(typeof body=="string"?body:"")}}function serializeJsonMarkdownItemDocument(document,options={}){const normalizedMetadata=normalizeItemMetadata(document.metadata,options),orderedMetadata=orderItemMetadata(normalizedMetadata),serializedMetadata=JSON.stringify(orderedMetadata,null,2),normalizedBody=normalizeBody(document.body??"");return normalizedBody?`${serializedMetadata}
|
|
4
4
|
|
|
5
5
|
${normalizedBody}
|
|
6
6
|
`:`${serializedMetadata}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Host output controls shared by command execution and extension rendering. */
|
|
2
2
|
export interface OutputOptions {
|
|
3
|
-
/**
|
|
3
|
+
/** Select JSON explicitly; otherwise use the host default format. */
|
|
4
4
|
json?: boolean;
|
|
5
|
-
/**
|
|
5
|
+
/** Suppress process output while retaining the active command result. */
|
|
6
6
|
quiet?: boolean;
|
|
7
7
|
/** When true, mutation results drop the verbose changed_fields array (keeps changed_field_count). */
|
|
8
8
|
noChangedFields?: boolean;
|
|
@@ -30,20 +30,22 @@ export interface OutputOptions {
|
|
|
30
30
|
outputRowContract?: boolean;
|
|
31
31
|
/** Fallback output format used when callers do not provide an override. */
|
|
32
32
|
defaultOutputFormat?: "toon" | "json";
|
|
33
|
-
/**
|
|
33
|
+
/** Command identity used to resolve read contracts and extension overrides. */
|
|
34
34
|
command?: string;
|
|
35
|
-
/**
|
|
35
|
+
/** Positional arguments passed to the output service override. */
|
|
36
36
|
commandArgs?: string[];
|
|
37
|
-
/**
|
|
37
|
+
/** Command options merged with active invocation options for output contracts. */
|
|
38
38
|
commandOptions?: Record<string, unknown>;
|
|
39
|
-
/**
|
|
39
|
+
/** Tracker root supplied to the output service override. */
|
|
40
40
|
pmRoot?: string;
|
|
41
41
|
}
|
|
42
|
-
/**
|
|
42
|
+
/** Write stdout and return false when its consumer has closed the pipe. */
|
|
43
43
|
export declare function writeStdout(text: string): boolean;
|
|
44
|
-
/**
|
|
44
|
+
/** Write stderr and preserve diagnostic delivery failures in the process exit code. */
|
|
45
45
|
export declare function writeStderr(text: string): boolean;
|
|
46
|
-
|
|
46
|
+
/** Keep sparse presentation rules shared while allowing lean JSON to retain count aliases. */
|
|
47
|
+
declare function compactToonValue(value: unknown, omitDuplicateCountAliases?: boolean): unknown | undefined;
|
|
48
|
+
/** Render objects recursively and arrays through the standard TOON encoder. */
|
|
47
49
|
declare function renderToonValue(value: unknown, depth: number): string;
|
|
48
50
|
/**
|
|
49
51
|
* Render a result with pm's built-in JSON or TOON formatter without invoking
|
|
@@ -51,13 +53,13 @@ declare function renderToonValue(value: unknown, depth: number): string;
|
|
|
51
53
|
* so reported token cost describes the bytes the host emits by default.
|
|
52
54
|
*/
|
|
53
55
|
export declare function formatBuiltInOutput(result: unknown, format: "json" | "toon"): string;
|
|
54
|
-
/**
|
|
56
|
+
/** Resolve command ownership and suppression before projecting and rendering the result. */
|
|
55
57
|
export declare function formatOutput(result: unknown, options: OutputOptions): string;
|
|
56
|
-
/**
|
|
58
|
+
/** Apply declared exit codes and mutation projection before writing a nonquiet result. */
|
|
57
59
|
export declare function printResult(result: unknown, options: OutputOptions): void;
|
|
58
|
-
/**
|
|
60
|
+
/** Apply the error service override and emit one newline-terminated diagnostic. */
|
|
59
61
|
export declare function printError(message: string): void;
|
|
60
|
-
/**
|
|
62
|
+
/** Internal rendering seams retained for deterministic presentation regression tests. */
|
|
61
63
|
export declare const outputTestOnly: {
|
|
62
64
|
compactToonValue: typeof compactToonValue;
|
|
63
65
|
renderToonValue: typeof renderToonValue;
|
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="391a4170-d29a-5c61-a0db-05181ebb0239")}catch{}})();import{getActiveCommandContext,runActiveCommandOverride,runActiveRendererOverride,runActiveServiceOverrideSync,setActiveCommandResult}from"../extensions/index.js";import{EXIT_CODE}from"../shared/constants.js";import{isHostOutputSuppressed}from"./output-control.js";import{projectMutationResult}from"./mutation-projection.js";import{attachReadOutputContracts}from"../../sdk/context-intent-contracts.js";import{attachOutputTokenAccounting}from"../../sdk/output-token-accounting.js";import{propagateContextUsageServingReceipt}from"../../sdk/context-usage.js";import{isReadOutputBudgetExceeded,resolveReadOutputEncoding}from"../../sdk/read-output-contracts.js";import{encode as encodeToon}from"@toon-format/toon";import{encodePmTableRows}from"../../sdk/output/table-rows.js";const DECLARED_PROCESS_EXIT_CODES=new Set(Object.values(EXIT_CODE)),COLLECTION_COUNT_ALIASES=new Map([["notes_count","notes"],["tests_count","tests"]]),NATIVE_OUTPUT_MARKER="__pm_native_output";let streamErrorHandlersInstalled=!1;function isPlainObject(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function setActiveCommandResultOmitted(source){const omitted={read_output:{result_omitted:!0}};propagateContextUsageServingReceipt(source,omitted),setActiveCommandResult(omitted)}function setActiveCommandDeliveryResult(result,receiptSource,structuredDeliveryPreserved){if(structuredDeliveryPreserved){setActiveCommandResult(result);return}setActiveCommandResultOmitted(receiptSource)}function stripNativeOutputMarker(result){if(!isPlainObject(result)||result[NATIVE_OUTPUT_MARKER]!==!0)return result;const{[NATIVE_OUTPUT_MARKER]:_marker,...rest}=result;return rest}function isBrokenPipeError(error){return typeof error=="object"&&error!==null&&error.code==="EPIPE"}function markStdoutBrokenPipeExitCode(){(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS)&&(process.exitCode=EXIT_CODE.SUCCESS)}function markStderrBrokenPipeExitCode(){(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS)&&(process.exitCode=EXIT_CODE.GENERIC_FAILURE)}function markBrokenPipeExitCode(target){if(target==="stdout"){markStdoutBrokenPipeExitCode();return}markStderrBrokenPipeExitCode()}function handleUnhandledStreamError(error){const unhandled=error instanceof Error?error:new Error(String(error));setImmediate(()=>{throw unhandled})}function installStreamErrorHandlers(){streamErrorHandlersInstalled||(streamErrorHandlersInstalled=!0,process.stdout.on("error",error=>{if(isBrokenPipeError(error)){markBrokenPipeExitCode("stdout");return}handleUnhandledStreamError(error)}),process.stderr.on("error",error=>{if(isBrokenPipeError(error)){markBrokenPipeExitCode("stderr");return}handleUnhandledStreamError(error)}))}function writeToStream(target,text){installStreamErrorHandlers();try{return target==="stdout"?process.stdout.write(text):process.stderr.write(text),!0}catch(error){if(isBrokenPipeError(error))return markBrokenPipeExitCode(target),!1;throw error}}function writeStdout(text){return writeToStream("stdout",text)}function writeStderr(text){return writeToStream("stderr",text)}function renderScalar(value){return typeof value=="string"?JSON.stringify(value):typeof value=="number"||typeof value=="boolean"?String(value):value===null?"null":JSON.stringify(value)}function tabularObjectArray(value){const keys=Object.keys(value[0]);return keys.length>0&&value.every(entry=>Object.keys(entry).length===keys.length&&keys.every(key=>{if(!Object.hasOwn(entry,key))return!1;const cell=entry[key];return cell===null||typeof cell=="string"||typeof cell=="number"||typeof cell=="boolean"}))}function indentToon(encoded,depth){const indent=" ".repeat(depth);return encoded.split(`
|
|
2
2
|
`).map(line=>`${indent}${line}`).join(`
|
|
3
|
-
`)}function renderToonObjectEntry(key,entry,depth){const indent=" ".repeat(depth);
|
|
4
|
-
${renderToonValue(entry,depth+1)}`}function compactToonValue(value){if(value!=null){if(Array.isArray(value)){const compactedEntries=value.map(entry=>compactToonValue(entry)).filter(entry=>entry!==void 0);return compactedEntries.length>0?compactedEntries:void 0}if(isPlainObject(value)){const compacted={};for(const[key,entry]of
|
|
5
|
-
`),[firstLine,...rest]=lines;return rest.length===0?`${indent}- ${firstLine.trimStart()}`:`${indent}- ${firstLine.trimStart()}
|
|
6
|
-
${rest.join(`
|
|
7
|
-
`)}`}).join(`
|
|
8
|
-
`);if(isPlainObject(value)){const entries=Object.entries(value);return entries.length===0?"{}":entries.map(([key,entry])=>renderToonObjectEntry(key,entry,depth)).join(`
|
|
3
|
+
`)}function isNestedTableCandidateBounded(rows){const columns=new Set;let presentCells=0;for(const row of rows){const keys=Object.keys(row);presentCells+=keys.length;for(const key of keys)columns.add(key)}return rows.length*columns.size<=presentCells*2}function renderToonObjectEntry(key,entry,depth,allowNestedTable){const indent=" ".repeat(depth);if(!isPlainObject(entry)&&!Array.isArray(entry))return`${indent}${key}: ${renderScalar(entry)}`;if(Array.isArray(entry)){if(entry.length===0)return`${indent}${key}: []`;const expanded=indentToon(encodeToon({[key]:entry}),depth);if(allowNestedTable&&entry.length>=2&&entry.every(isPlainObject)&&!tabularObjectArray(entry)&&isNestedTableCandidateBounded(entry)){const table=encodePmTableRows(entry),tabular=indentToon(encodeToon({[key]:table.rows,[`${key}_encoding`]:table.encoding}),depth);if(Buffer.byteLength(tabular)<Buffer.byteLength(expanded))return tabular}return expanded}return isPlainObject(entry)&&Object.keys(entry).length===0?`${indent}${key}: {}`:`${indent}${key}:
|
|
4
|
+
${renderToonValue(entry,depth+1)}`}function compactToonValue(value,omitDuplicateCountAliases=!0){if(value!=null){if(Array.isArray(value)){const compactedEntries=value.map(entry=>compactToonValue(entry,omitDuplicateCountAliases)).filter(entry=>entry!==void 0);return compactedEntries.length>0?compactedEntries:void 0}if(isPlainObject(value)){const compacted={},entries=Object.entries(value).filter(([key,entry])=>{const canonicalCount=COLLECTION_COUNT_ALIASES.get(key);return!omitDuplicateCountAliases||canonicalCount===void 0||!isPlainObject(value.collection_counts)||entry!==value.collection_counts[canonicalCount]});for(const[key,entry]of entries){if(key==="omitted_field_groups"&&Array.isArray(entry)&&entry.length===0){compacted[key]=[];continue}const compactedEntry=compactToonValue(entry,omitDuplicateCountAliases);compactedEntry!==void 0&&(compacted[key]=compactedEntry)}return Object.keys(compacted).length>0?compacted:void 0}return value}}function renderToonValue(value,depth){const indent=" ".repeat(depth);if(Array.isArray(value))return value.length===0?"[]":indentToon(encodeToon(value),depth);if(isPlainObject(value)){const entries=Object.entries(value);return entries.length===0?"{}":entries.map(([key,entry])=>renderToonObjectEntry(key,entry,depth,!Object.hasOwn(value,`${key}_encoding`))).join(`
|
|
9
5
|
`)}return`${indent}${renderScalar(value)}`}function renderDefaultMarkdownResult(value){if(!isPlainObject(value)||value.output_default!=="markdown"||typeof value.view!="string"||!Array.isArray(value.events)||!Array.isArray(value.days))return null;const lines=[`# pm calendar (${value.view})`,""],summary=isPlainObject(value.summary)?value.summary:{};if(lines.push(`- events: ${String(summary.events??0)}`),lines.push(""),value.events.length===0)return lines.push("No calendar events matched the selected filters."),`${lines.join(`
|
|
10
6
|
`)}
|
|
11
7
|
`;for(const event of value.events){if(!isPlainObject(event))continue;const kind=typeof event.kind=="string"?event.kind:"event",title=typeof event.item_title=="string"?event.item_title:"",itemId=typeof event.item_id=="string"?event.item_id:"",reminderText=typeof event.reminder_text=="string"&&event.reminder_text.length>0?` ${event.reminder_text}`:"";lines.push(`- [${kind}] ${itemId} ${title}${reminderText}`.trim())}return`${lines.join(`
|
|
12
8
|
`)}
|
|
13
|
-
`}
|
|
9
|
+
`}const LEAN_READ_ENVELOPE_ECHO_KEYS=new Set(["filters","now","projection","sorting"]);function projectLeanJsonValue(value){const compacted=compactToonValue(value,!1);if(!isPlainObject(compacted)||!Array.isArray(compacted.items))return compacted??null;const projected=Object.fromEntries(Object.entries(compacted).filter(([key])=>!LEAN_READ_ENVELOPE_ECHO_KEYS.has(key)));return projected.has_more!==!0&&delete projected.next_cursor,projected}function projectLinkedTestEvidence(value,lean){if(!isPlainObject(value)||!Array.isArray(value.run_results)||!value.run_results.every(isPlainObject))return value;const rows=value.run_results,contexts=rows.map(row=>row.execution_context).filter(context=>context!==void 0),sharedContext=contexts.length===rows.length&&contexts.length>0&&contexts.every(context=>JSON.stringify(context)===JSON.stringify(contexts[0]))?contexts[0]:void 0,runResults=rows.map(row=>{const{execution_context:_executionContext,stdout,stderr,...rest}=row;return sharedContext===void 0?row:!lean||row.status!=="passed"?{...rest,stdout,stderr}:rest});return{...value,...sharedContext===void 0?{}:{execution_context:sharedContext},run_results:runResults}}function projectCompleteBriefList(value){if(!isPlainObject(value)||!Array.isArray(value.items)||Object.hasOwn(value,"details")||!isPlainObject(value.projection)||value.projection.mode!=="brief"||!isPlainObject(value.completeness)||value.completeness.status!=="complete"||[value.completeness.unreadable_item_count,value.completeness.unreadable_directory_count].some(count=>count!==0)||[value.has_more,value.truncated].some(flag=>flag!==!1)||value.count!==value.items.length||value.total!==value.count||!isPlainObject(value.omission_receipt)||JSON.stringify(value.omission_receipt.omitted_field_groups)!==JSON.stringify([{name:"full_item_fields",restore_with:"--full"}]))return value;const{total:_total,has_more:_hasMore,truncated:_truncated,next_cursor:_nextCursor,completeness:_completeness,projection:_projection,now:_now,omission_receipt:_omissions,sorting,...rest}=value;return{...rest,...isPlainObject(sorting)&&sorting.sort==="default"?{}:{sorting},details:"--full"}}function formatBuiltInOutput(result,format){if(format==="json")return`${JSON.stringify(result,null,2)}
|
|
14
10
|
`;const compactedToon=compactToonValue(projectCompleteBriefList(result));return compactedToon===void 0?`{}
|
|
15
11
|
`:`${renderToonValue(compactedToon,0)}
|
|
16
12
|
`}function resolveOutputService(effectiveResult,nativeOutput,options,format){const serviceOverride=nativeOutput?{handled:!1,result:effectiveResult,warnings:[]}:runActiveServiceOverrideSync("output_format",{command:options.command,args:options.commandArgs,command_options:options.commandOptions,global:{...options},pm_root:options.pmRoot,format,options:{...options},result:effectiveResult}),legacyPayloadEchoWarning=serviceOverride.warnings.find(warning=>warning.startsWith("extension_output_format_payload_echo_deprecated:"));return legacyPayloadEchoWarning!==void 0&&writeStderr(`Warning: ${legacyPayloadEchoWarning}. Returning context.payload now declines safely for compatibility; migrate the override to declineServiceOverride() or { handled: false }.
|
|
17
13
|
`),serviceOverride.handled&&typeof serviceOverride.result=="string"?{result:serviceOverride.result,rendered:serviceOverride.result.endsWith(`
|
|
18
14
|
`)?serviceOverride.result:`${serviceOverride.result}
|
|
19
|
-
`,structuredDeliveryPreserved:!1}:{result:serviceOverride.handled?serviceOverride.result:effectiveResult,rendered:null,structuredDeliveryPreserved:!serviceOverride.handled||isPlainObject(serviceOverride.result)}}function formatEffectiveOutput(effectiveResult,nativeOutput,options){const activeCommandContext=getActiveCommandContext(),command=options.command??activeCommandContext?.command,commandOptions={...activeCommandContext?.options,...options.commandOptions,...Object.fromEntries([["outputInclude",options.outputInclude],["outputLimit",options.outputLimit],["outputBudget",options.outputBudget],["outputFormat",options.outputFormat],["outputSession",options.outputSession],["outputCursor",options.outputCursor],["outputRowContract",options.outputRowContract]].filter(entry=>entry[1]!==void 0))},format=resolveReadOutputEncoding(command??"",commandOptions)??
|
|
15
|
+
`,structuredDeliveryPreserved:!1}:{result:serviceOverride.handled?serviceOverride.result:effectiveResult,rendered:null,structuredDeliveryPreserved:!serviceOverride.handled||isPlainObject(serviceOverride.result)}}function formatEffectiveOutput(effectiveResult,nativeOutput,options,defaultFormat){const activeCommandContext=getActiveCommandContext(),command=options.command??activeCommandContext?.command,commandOptions={...activeCommandContext?.options,...options.commandOptions,...Object.fromEntries([["outputInclude",options.outputInclude],["outputLimit",options.outputLimit],["outputBudget",options.outputBudget],["outputFormat",options.outputFormat],["outputSession",options.outputSession],["outputCursor",options.outputCursor],["outputRowContract",options.outputRowContract]].filter(entry=>entry[1]!==void 0))},format=resolveReadOutputEncoding(command??"",commandOptions)??defaultFormat,resolvedCommandOptions={...commandOptions,resolvedOutputFormat:format},effectiveOptions={...options,command,commandOptions:resolvedCommandOptions},service=resolveOutputService(effectiveResult,nativeOutput,effectiveOptions,format);if(service.rendered!==null)return setActiveCommandResultOmitted(effectiveResult),service.rendered;const outputResult=service.result;propagateContextUsageServingReceipt(effectiveResult,outputResult);const projectedOutputResult=command==="test"?projectLinkedTestEvidence(outputResult,options.lean===!0):outputResult,intentOutputResult=attachReadOutputContracts(command,resolvedCommandOptions,projectedOutputResult);isReadOutputBudgetExceeded(intentOutputResult)&&(process.exitCode||=EXIT_CODE.USAGE);let{structuredDeliveryPreserved}=service;const renderResolvedOutput=value=>{if(format==="toon"){const markdownDefault=renderDefaultMarkdownResult(value);if(markdownDefault!==null)return markdownDefault}const rendererOverride=nativeOutput?{rendered:null}:runActiveRendererOverride(format,value);return rendererOverride.rendered!==null?(structuredDeliveryPreserved=!1,rendererOverride.rendered.endsWith(`
|
|
20
16
|
`)?rendererOverride.rendered:`${rendererOverride.rendered}
|
|
21
|
-
`):format==="json"?formatBuiltInOutput(options.lean===!0?projectLeanJsonValue(value):value,"json"):formatBuiltInOutput(value,"toon")},accountedOutputResult=options.tokenAccounting===!0?attachOutputTokenAccounting(intentOutputResult,renderResolvedOutput):intentOutputResult,rendered=renderResolvedOutput(accountedOutputResult);return setActiveCommandDeliveryResult(accountedOutputResult,effectiveResult,options.quiet!==!0&&structuredDeliveryPreserved),rendered}function formatOutput(result,options){const commandOverride=runActiveCommandOverride(result),suppressedOutput=isHostOutputSuppressed(commandOverride.result)?commandOverride.result:null,
|
|
17
|
+
`):format==="json"?formatBuiltInOutput(options.lean===!0?projectLeanJsonValue(value):value,"json"):formatBuiltInOutput(value,"toon")},accountedOutputResult=options.tokenAccounting===!0?attachOutputTokenAccounting(intentOutputResult,renderResolvedOutput):intentOutputResult,rendered=renderResolvedOutput(accountedOutputResult);return setActiveCommandDeliveryResult(accountedOutputResult,effectiveResult,options.quiet!==!0&&structuredDeliveryPreserved),rendered}function formatOutput(result,options){const commandOverride=runActiveCommandOverride(result),suppressedOutput=isHostOutputSuppressed(commandOverride.result)?commandOverride.result:null,nativeResult=commandOverride.result,nativeOutput=isPlainObject(nativeResult)&&nativeResult[NATIVE_OUTPUT_MARKER]===!0,effectiveResult=suppressedOutput?suppressedOutput.result:stripNativeOutputMarker(commandOverride.result);if(setActiveCommandResult(effectiveResult),suppressedOutput)return setActiveCommandResultOmitted(effectiveResult),"";const defaultFormat=options.json===!0||options.json===void 0&&options.defaultOutputFormat==="json"?"json":"toon";return formatEffectiveOutput(effectiveResult,nativeOutput,options,defaultFormat)}function printResult(result,options){isPlainObject(result)&&Number.isInteger(result.exit_code)&&DECLARED_PROCESS_EXIT_CODES.has(Number(result.exit_code))&&(process.exitCode===void 0||process.exitCode===EXIT_CODE.SUCCESS)&&(process.exitCode=Number(result.exit_code));const projected=options.idOnly?projectMutationResult(result,{idOnly:!0}):options.fullChangedFields?result:options.noChangedFields?projectMutationResult(result,{changedFields:"compact"}):projectMutationResult(result,{compactEnvelope:!0}),rendered=formatOutput(projected,options);options.quiet||writeStdout(rendered)}function printError(message){const override=runActiveServiceOverrideSync("error_format",{message}),rendered=override.handled&&typeof override.result=="string"?override.result:message;writeStderr(rendered.endsWith(`
|
|
22
18
|
`)?rendered:`${rendered}
|
|
23
19
|
`)}const outputTestOnly={compactToonValue,renderToonValue};export{formatBuiltInOutput,formatOutput,outputTestOnly,printError,printResult,writeStderr,writeStdout};
|
|
24
20
|
//# sourceMappingURL=output.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type RuntimeFieldDefinitionResolved, type RuntimeFieldRegistry } from "./runtime-schema.js";
|
|
2
2
|
/** Implements read runtime field option value for the public runtime surface of this module. */
|
|
3
3
|
export declare function readRuntimeFieldOptionValue(options: Record<string, unknown>, definition: RuntimeFieldDefinitionResolved): unknown;
|
|
4
|
-
/**
|
|
5
|
-
export declare function coerceRuntimeFieldValue(definition: RuntimeFieldDefinitionResolved, rawValue: unknown, labelOverride?: string): unknown;
|
|
4
|
+
/** Validate a declared field; option arrays represent repeated flags, while metadata containers retain their exact shape. */
|
|
5
|
+
export declare function coerceRuntimeFieldValue(definition: RuntimeFieldDefinitionResolved, rawValue: unknown, labelOverride?: string, inputKind?: "option" | "metadata"): unknown;
|
|
6
6
|
/** Implements collect runtime create field values for the public runtime surface of this module. */
|
|
7
7
|
export declare function collectRuntimeCreateFieldValues(options: Record<string, unknown>, fieldRegistry: RuntimeFieldRegistry, itemTypeName: string | undefined): {
|
|
8
8
|
values: Record<string, unknown>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4d5692ce-ec33-5eb4-bd9b-7497ffe25b0e")}catch{}})();import{EXIT_CODE}from"../shared/constants.js";import{PmCliError}from"../shared/errors.js";import{stableStringify}from"../shared/serialization.js";import{isRfc3339DateTime}from"../shared/time.js";import{runtimeFieldOptionTarget}from"./runtime-schema.js";const MAX_VALUE_SCHEMA_DEPTH=16;function toCamelToken(value){const segments=value.trim().replaceAll(/[^A-Za-z0-9]+/g," ").split(/\s+/).filter(segment=>segment.length>0).map(segment=>segment.toLowerCase());if(segments.length===0)return value;const[first,...rest]=segments;return`${first}${rest.map(segment=>`${segment.slice(0,1).toUpperCase()}${segment.slice(1)}`).join("")}`}function resolveCandidateOptionKeys(definition){return[...new Set([runtimeFieldOptionTarget(definition),toCamelToken(definition.key),toCamelToken(definition.cli_flag),...definition.cli_aliases.map(alias=>toCamelToken(alias))])]}function readRuntimeFieldOptionValue(options,definition){for(const candidateKey of resolveCandidateOptionKeys(definition)){if(!Object.hasOwn(options,candidateKey))continue;const value=options[candidateKey];if(value!==void 0)return value}}function normalizeStringArrayValue(value){return Array.isArray(value)?value.flatMap(entry=>normalizeStringArrayValue(entry)).map(entry=>entry.trim()).filter(entry=>entry.length>0):typeof value=="string"?value.split(/[,\n|]/).map(entry=>entry.trim()).filter(entry=>entry.length>0):value==null?[]:[String(value).trim()].filter(entry=>entry.length>0)}function parseBooleanValue(raw,label){if(typeof raw=="boolean")return raw;if(typeof raw=="number"){if(raw===1)return!0;if(raw===0)return!1}if(typeof raw=="string"){const normalized=raw.trim().toLowerCase();if(normalized==="true"||normalized==="1"||normalized==="yes")return!0;if(normalized==="false"||normalized==="0"||normalized==="no")return!1}throw new PmCliError(`${label} must be one of true|false|1|0|yes|no`,EXIT_CODE.USAGE)}function parseNumberValue(raw,label){if(typeof raw=="number"&&Number.isFinite(raw))return raw;const candidate=typeof raw=="string"?raw.trim():String(raw),parsed=Number(candidate);if(!Number.isFinite(parsed))throw new PmCliError(`${label} must be a number`,EXIT_CODE.USAGE);return parsed}function parseJsonContainerValue(raw,label,expectedType){const parsed=typeof raw=="string"?(()=>{try{return JSON.parse(raw)}catch{return}})():raw;if(expectedType==="array"&&Array.isArray(parsed)||expectedType==="object"&&typeof parsed=="object"&&parsed!==null&&!Array.isArray(parsed))return parsed;throw new PmCliError(`${label} must be valid JSON ${expectedType}`,EXIT_CODE.USAGE)}function valueMatchesSchemaType(value,type){return type===void 0?!0:type==="array"?Array.isArray(value):type==="object"?typeof value=="object"&&value!==null&&!Array.isArray(value):typeof value===type}function runtimeFieldPrimitiveSchemaError(value,schema,path){if(schema.const!==void 0&&stableStringify(value)!==stableStringify(schema.const))return`${path} must equal ${stableStringify(schema.const)}`;if(schema.enum!==void 0&&!schema.enum.some(candidate=>stableStringify(candidate)===stableStringify(value)))return`${path} must be one of ${schema.enum.map(entry=>stableStringify(entry)).join("|")}`;if(!valueMatchesSchemaType(value,schema.type))return`${path} must match configured type ${String(schema.type)}`;if(typeof value=="string"){if(schema.min_length!==void 0&&value.length<schema.min_length)return`${path} must contain at least ${schema.min_length} characters`;if(schema.format==="date-time"&&!isRfc3339DateTime(value))return`${path} must be an RFC 3339 date-time`}}function runtimeFieldArraySchemaError(value,schema,path,depth){if(Array.isArray(value)){if(schema.min_items!==void 0&&value.length<schema.min_items)return`${path} must contain at least ${schema.min_items} items`;if(schema.items)for(const[index,entry]of value.entries()){const error=runtimeFieldSchemaError(entry,schema.items,`${path}[${index}]`,depth+1);if(error)return error}}}function runtimeFieldObjectSchemaError(value,schema,path,depth){if(typeof value!="object"||value===null||Array.isArray(value))return;const record=value;for(const key of schema.required??[])if(!Object.hasOwn(record,key))return`${path}.${key} is required`;for(const[key,entry]of Object.entries(record)){const propertySchema=schema.properties?.[key];if(!propertySchema){if(schema.additional_properties===!1)return`${path}.${key} is not allowed`;continue}const error=runtimeFieldSchemaError(entry,propertySchema,`${path}.${key}`,depth+1);if(error)return error}}function runtimeFieldSchemaError(value,schema,path,depth=0){if(depth>MAX_VALUE_SCHEMA_DEPTH)return`${path} value schema exceeds maximum depth`;const directError=runtimeFieldPrimitiveSchemaError(value,schema,path);if(directError)return directError;const arrayError=runtimeFieldArraySchemaError(value,schema,path,depth);if(arrayError)return arrayError;const objectError=runtimeFieldObjectSchemaError(value,schema,path,depth);if(objectError)return objectError;if(!schema.one_of)return;let matches=0;for(const candidate of schema.one_of)if(runtimeFieldSchemaError(value,candidate,path,depth+1)===void 0&&(matches+=1,matches>1))break;return matches===1?void 0:`${path} must match exactly one configured schema variant`}function validateRuntimeFieldValue(definition,value,label){if(!definition.value_schema||value===void 0)return value;const error=runtimeFieldSchemaError(value,definition.value_schema,label);if(error)throw new PmCliError(error,EXIT_CODE.USAGE);return value}function coerceRuntimeContainerValue(definition,rawValue,label,inputKind){const raw=inputKind==="option"&&Array.isArray(rawValue)?rawValue[rawValue.length-1]:rawValue;if(raw!==void 0)return validateRuntimeFieldValue(definition,parseJsonContainerValue(raw,label,definition.type),label)}function coerceRuntimeFieldValue(definition,rawValue,labelOverride,inputKind="option"){const label=labelOverride??`--${definition.cli_flag}`;if(definition.type==="array"||definition.type==="object")return coerceRuntimeContainerValue(definition,rawValue,label,inputKind);if(definition.repeatable||definition.type==="string_array"){const values=normalizeStringArrayValue(rawValue);return definition.type==="number"?validateRuntimeFieldValue(definition,values.map(value=>parseNumberValue(value,label)),label):definition.type==="boolean"?validateRuntimeFieldValue(definition,values.map(value=>parseBooleanValue(value,label)),label):validateRuntimeFieldValue(definition,values,label)}const scalarRaw=Array.isArray(rawValue)?rawValue[rawValue.length-1]:rawValue;if(scalarRaw!==void 0)return definition.type==="number"?validateRuntimeFieldValue(definition,parseNumberValue(scalarRaw,label),label):definition.type==="boolean"?validateRuntimeFieldValue(definition,parseBooleanValue(scalarRaw,label),label):validateRuntimeFieldValue(definition,typeof scalarRaw=="string"?scalarRaw:String(scalarRaw),label)}function shouldRequireFieldOnCreate(definition,itemTypeName){return!definition.required&&!definition.required_on_create?!1:definition.required_types.length===0?!0:itemTypeName?definition.required_types.map(value=>value.toLowerCase()).includes(itemTypeName.trim().toLowerCase()):!1}function collectRuntimeCreateFieldValues(options,fieldRegistry,itemTypeName){const values={},missingRequiredFlags=[];for(const definition of fieldRegistry.command_to_fields.get("create")??[]){const rawValue=readRuntimeFieldOptionValue(options,definition);if(rawValue===void 0){shouldRequireFieldOnCreate(definition,itemTypeName)&&missingRequiredFlags.push(`--${definition.cli_flag}`);continue}values[definition.metadata_key]=coerceRuntimeFieldValue(definition,rawValue)}return{values,missing_required_flags:[...new Set(missingRequiredFlags)].sort((left,right)=>left.localeCompare(right))}}function collectRuntimeUpdateFieldValues(options,fieldRegistry,commands=["update"]){const values={},definitions=(commands??["update"]).flatMap(command=>fieldRegistry.command_to_fields.get(command)??[]),seen=new Set;for(const definition of definitions){const rawValue=readRuntimeFieldOptionValue(options,definition);rawValue!==void 0&&(seen.has(definition.metadata_key)||(seen.add(definition.metadata_key),values[definition.metadata_key]=coerceRuntimeFieldValue(definition,rawValue)))}return values}export{coerceRuntimeFieldValue,collectRuntimeCreateFieldValues,collectRuntimeUpdateFieldValues,readRuntimeFieldOptionValue};
|
|
2
2
|
//# sourceMappingURL=runtime-field-values.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="12ee7de1-dff4-53f1-8d0d-d8b1c1ebea42")}catch{}})();import fs from"node:fs/promises";import path from"node:path";import{runActiveOnWriteHooks}from"../extensions/index.js";import{readFileIfExists,removeFileIfExists,writeFileAtomic}from"../fs/fs-utils.js";import{parseItemDocument,serializeItemDocument}from"../item/item-format.js";import{TYPE_TO_FOLDER}from"../shared/constants.js";import{getItemFormatFromPath,getItemPath}from"./paths.js";function alternateItemFormat(_targetFormat){return"json_markdown"}function normalizeRelativePath(pmRoot,absolutePath){return path.relative(pmRoot,absolutePath).replaceAll("\\","/")}function errorSummary(error){return String(error).replaceAll(/[^a-zA-Z0-9._-]+/g,"_").slice(0,120)}async function assertLegacyAlternateSafeToRemove(sourcePath,alternatePath,schema){sourcePath!==alternatePath&&parseItemDocument(await fs.readFile(alternatePath,"utf8"),{format:"json_markdown",requireSupportedFormat:!0,schema})}async function migrateItemFilesToFormat(pmRoot,targetFormat,op="item_format:migrate",typeToFolder=TYPE_TO_FOLDER,schema){if(targetFormat!=="toon")throw new Error("Only toon item-format migration targets are supported. Markdown item files are legacy read-only input.");const migratedIds=new Set,removedPaths=new Set,warnings=[];let scanned=0;const alternateFormat=alternateItemFormat(targetFormat),typeEntries=Object.entries(typeToFolder);for(const[itemType,folder]of typeEntries){const directoryPath=path.join(pmRoot,folder);let files=[];try{files=await fs.readdir(directoryPath)}catch{continue}const variantsById=new Map;for(const file of files){const absolutePath=path.join(directoryPath,file),itemFormat=getItemFormatFromPath(absolutePath);if(!itemFormat)continue;const extension=path.extname(file),itemId=file.slice(0,file.length-extension.length).trim();if(itemId.length===0)continue;const entry=variantsById.get(itemId)??{};entry[itemFormat]=absolutePath,variantsById.set(itemId,entry)}const itemIds=[...variantsById.keys()].sort((left,right)=>left.localeCompare(right));for(const itemId of itemIds){const variants=variantsById.get(itemId);scanned+=1;const alternatePath=variants[alternateFormat];if(!alternatePath)continue;const sourcePath=variants[targetFormat]??alternatePath,sourceFormat=sourcePath===variants[targetFormat]?targetFormat:alternateFormat;try{const sourceRaw=await fs.readFile(sourcePath,"utf8"),parsedDocument=parseItemDocument(sourceRaw,{format:sourceFormat,requireSupportedFormat:!0,schema,onWarning:warning=>warnings.push(`item_format_migration_parse_warning:${itemId}:${warning}`)});await assertLegacyAlternateSafeToRemove(sourcePath,alternatePath,schema);const targetPath=getItemPath(pmRoot,itemType,itemId,targetFormat,typeToFolder),serializedTarget=serializeItemDocument(parsedDocument,{format:targetFormat,schema});await readFileIfExists(targetPath)!==serializedTarget&&(await writeFileAtomic(targetPath,serializedTarget),warnings.push(...await runActiveOnWriteHooks({path:targetPath,scope:"project",op})),migratedIds.add(itemId)),await removeFileIfExists(alternatePath),removedPaths.add(normalizeRelativePath(pmRoot,alternatePath)),warnings.push(...await runActiveOnWriteHooks({path:alternatePath,scope:"project",op:`${op}:remove`})),migratedIds.add(itemId)}catch(error){warnings.push(`item_format_migration_skipped:${normalizeRelativePath(pmRoot,sourcePath)}:${errorSummary(error)}`)}}}return{target_format:targetFormat,scanned,migrated:[...migratedIds].sort((left,right)=>left.localeCompare(right)),removed:[...removedPaths].sort((left,right)=>left.localeCompare(right)),warnings}}export{migrateItemFilesToFormat};
|
|
2
2
|
//# sourceMappingURL=item-format-migration.js.map
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { DatabaseSync } from "node:sqlite";
|
|
2
2
|
import type { ItemMetadata, LinkedFile, LinkScope } from "../../types/index.js";
|
|
3
|
+
import { loadDatabaseSync, loadStableDatabaseSync } from "./sqlite-runtime.js";
|
|
3
4
|
type DatabaseSyncConstructor = typeof DatabaseSync;
|
|
4
|
-
declare function loadDatabaseSync(loadModule: (specifier: string) => unknown): DatabaseSyncConstructor | null;
|
|
5
|
-
declare function loadStableDatabaseSync(nodeVersion: string, loadModule: (specifier: string) => unknown): DatabaseSyncConstructor | null;
|
|
6
5
|
/** One light-metadata row projected into the persistent query index. */
|
|
7
6
|
export interface ItemMetadataQueryIndexRow {
|
|
8
7
|
/** Tracker-relative authoritative item path. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
1
|
+
(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="84a3dae8-69b6-589d-a8ec-11f77c1d103a")}catch{}})();import fs from"node:fs/promises";import path from"node:path";import{randomUUID}from"node:crypto";import{createRequire}from"node:module";import{loadDatabaseSync,loadStableDatabaseSync}from"./sqlite-runtime.js";const QUERY_INDEX_FILENAME="metadata-query-index.sqlite",QUERY_INDEX_VERSION="5";let RuntimeDatabaseSync;function resolveDatabaseSync(){return RuntimeDatabaseSync!==void 0||(RuntimeDatabaseSync=loadStableDatabaseSync(process.versions.node,createRequire(import.meta.url))),RuntimeDatabaseSync}function normalizeIndexWindowValue(value,fallback){return Math.max(0,Math.floor(value===void 0?fallback:value))}function queryIndexPath(pmRoot){return path.join(pmRoot,"runtime",QUERY_INDEX_FILENAME)}function createSchema(database){database.exec(`
|
|
2
2
|
PRAGMA foreign_keys = ON;
|
|
3
3
|
PRAGMA journal_mode = OFF;
|
|
4
4
|
PRAGMA synchronous = OFF;
|