@unbrained/pm-cli 2026.10.9 → 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 +19 -0
- package/dist/cli/register-mutation.js +2 -2
- package/dist/cli-bundle/bundle-manifest.json +115 -115
- package/dist/cli-bundle/chunks/{chunk-P5NS7EFC.js → chunk-2JYTSTQP.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ZNXRGATT.js → chunk-BXSXT5Z6.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-QQHNXCO3.js → chunk-ESRACL6K.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5MOFELIF.js → chunk-K2UTE75T.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-55MK3QQM.js → chunk-KNW3RSLS.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-MEWBSWE3.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-KOGF6O6W.js → chunk-OBLO45UM.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-XW3BLWFF.js → chunk-RBPOO46D.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-E4XR5LKU.js → chunk-RUT3CCAG.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-CPZOW6L2.js → chunk-S445XEYT.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5NR6TDYB.js → chunk-SSY4OSJR.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5TCQ5J3V.js → chunk-YMLF6QT7.js} +75 -75
- package/dist/cli-bundle/chunks/{chunk-NIF7JOPW.js → chunk-ZWRLAOA4.js} +2 -2
- package/dist/cli-bundle/chunks/{register-list-query-2YOWMNWY.js → register-list-query-T6BOR67M.js} +2 -2
- package/dist/cli-bundle/chunks/register-mutation-6NXR7SAJ.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-BMK65YM3.js → register-operations-PDOBQZUJ.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-24TFFK6N.js → register-setup-MAYFPKBX.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-362645PL.js → chunk-52UJEHEV.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-EZ4367G4.js → chunk-EIOQNLBQ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-SAN3KPX4.js → chunk-GVGFUD52.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-DSLNUL2Q.js → chunk-JGFSSR3G.js} +16 -16
- package/dist/cli-bundle/focused-chunks/{chunk-IARAEFMA.js → chunk-KNJR2WUO.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-MJQ253F3.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-MCVWZUGK.js → chunk-SIEGIPNT.js} +28 -28
- package/dist/cli-bundle/main.js +2 -2
- package/dist/cli-bundle/sdk-contracts.js +1 -1
- package/dist/cli-bundle/sdk-core.js +1 -1
- 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 +51 -51
- 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/item/item-format.d.ts +2 -0
- package/dist/core/item/item-format.js +3 -3
- 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-store.js +1 -1
- 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/public-surface.json +1 -1
- package/dist/sdk/structured-mutations.d.ts +5 -1
- package/dist/sdk/structured-mutations.js +1 -1
- package/docs/QUALITY_EVIDENCE.md +52 -1
- package/docs/RELEASE_RELIABILITY.md +54 -3
- package/docs/SDK.md +16 -2
- package/docs/TESTING.md +36 -0
- 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-N7GKWO4G.js +0 -2
- package/dist/cli-bundle/chunks/register-mutation-ILOWFMTV.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-2ATAD56F.js +0 -2
|
@@ -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
|
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,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]="5dd36511-d680-55ce-b535-5c1fbfaf63ec")}catch{}})();import fs from"node:fs/promises";import{buildDeletedItemError}from"../history/tombstone.js";import{normalizeHistoryOperationForWrite}from"../history/operation-contract.js";import{enforceWorkflowMutation}from"../policy/workflow-policy-store.js";import{recordItemMetadataEnumeration}from"./item-metadata-read-work.js";import path from"node:path";import{getActiveExtensionRegistrations,projectAfterCommandItemSnapshot,recordAfterCommandAffectedItem,runActiveOnReadHooks,runActiveBeforeMutationHooks,runActiveOnWriteHooks,runActiveServiceOverride}from"../extensions/index.js";import{collectRegisteredItemFieldNames}from"../extensions/item-fields.js";import{EMPTY_CANONICAL_DOCUMENT,EXIT_CODE,TYPE_TO_FOLDER}from"../shared/constants.js";import{PmCliError}from"../shared/errors.js";import{levenshteinDistanceWithinLimit}from"../shared/levenshtein.js";import{appendHistoryEntry,createHistoryEntry}from"../history/history.js";import{enforceHistoryStreamPolicyForItem}from"../history/history-stream-policy.js";import{canonicalDocument,parseItemDocument,serializeItemDocument}from"../item/item-format.js";import{resolveItemTypeRegistry}from"../item/type-registry.js";import{acquireLock}from"../lock/lock.js";import{writeFileAtomic}from"../fs/fs-utils.js";import{isUtf8}from"node:buffer";import{normalizeItemId,normalizeRawItemId}from"../item/id.js";import{acquireItemMetadataDerivedIndexLock,listAllDocumentCandidatesCached,listAllDocumentsCached,listAllDocumentsCachedLight,refreshItemMetadataDerivedIndex}from"./item-metadata-cache.js";import{getHistoryPath,getItemPath,ITEM_FILE_EXTENSIONS}from"./paths.js";import{resolveGovernanceKnobs}from"./settings.js";import{assertReadableTrackerRoot}from"./tracker-preflight.js";import{resolveClaimPrincipal}from"../shared/author.js";import{nowIso}from"../shared/time.js";async function fileExists(targetPath){try{return await fs.access(targetPath),!0}catch{return!1}}function isErrno(error,code){return typeof error=="object"&&error!==null&&"code"in error&&error.code===code}function appendWarning(warnings,warning){warnings&&(warnings.includes(warning)||warnings.push(warning))}function resolveActiveExtensionFieldNames(explicit){return explicit??collectRegisteredItemFieldNames(getActiveExtensionRegistrations())}function resolveItemFormatSearchOrder(preferredFormat){return preferredFormat==="toon"?["toon","json_markdown"]:preferredFormat==="json_markdown"?["json_markdown","toon"]:["toon","json_markdown"]}async function locateItem(pmRoot,rawId,idPrefix="pm-",preferredFormat,typeToFolder=TYPE_TO_FOLDER){const trimmedRawId=rawId.trim(),exactRawId=trimmedRawId.startsWith("#")?trimmedRawId.slice(1):trimmedRawId;if(exactRawId.length===0)return null;const normalizedId=normalizeItemId(rawId,idPrefix),rawNormalizedId=normalizeRawItemId(rawId),candidateIds=[...new Set([exactRawId,normalizedId,rawNormalizedId])].filter(candidateId=>candidateId.length>0),entries=Object.entries(typeToFolder),searchOrder=resolveItemFormatSearchOrder(preferredFormat);for(const candidateId of candidateIds){const matches=new Map;for(const[type]of entries)for(const itemFormat of searchOrder){const itemPath=getItemPath(pmRoot,type,candidateId,itemFormat,typeToFolder);await fileExists(itemPath)&&matches.set(itemPath,matches.get(itemPath)??{id:candidateId,type,itemPath,item_format:itemFormat})}if(matches.size>1){const paths=[...matches.keys()].map(itemPath=>path.relative(pmRoot,itemPath).split(path.sep).join("/")).sort();throw new PmCliError(`Item ${candidateId} has ambiguous identity across ${paths.join(", ")}. Preserve both documents and inspect pm ops validate --check-storage-integrity before resolving the collision.`,EXIT_CODE.CONFLICT,{code:"item_identity_ambiguous",item_id:candidateId,paths})}for(const match of matches.values())return match}return null}async function readLocatedItem(item,options={}){const snapshot=await readLocatedItemSnapshot(item,options);if(snapshot.error!==null)throw snapshot.error;return{raw:snapshot.raw,document:snapshot.document}}async function readLocatedItemSnapshot(item,options={}){const bytes=await fs.readFile(item.itemPath);if(!isUtf8(bytes))throw new PmCliError("Item contains invalid UTF-8; preserve a binary backup before recovering it.",EXIT_CODE.CONFLICT,{code:"item_document_encoding_invalid",item_id:item.id,item_path:item.itemPath,byte_length:bytes.length,empty:!1});const raw=bytes.toString("utf8");await runActiveOnReadHooks({path:item.itemPath,scope:"project"});let document;try{document=parseItemDocument(raw,{format:item.item_format,schema:options.schema,extensionFieldNames:resolveActiveExtensionFieldNames(options.extensionFieldNames),onWarning:warning=>appendWarning(options.warnings,warning)})}catch(error){if(error instanceof PmCliError&&error.code==="item_document_invalid")return{raw,document:null,error:new PmCliError(`Cannot read ${item.id} at ${item.itemPath}${bytes.length===0?" (zero-length file)":""}: ${error.message}`,error.exitCode,{...error.context,item_id:item.id,item_path:item.itemPath,byte_length:bytes.length,empty:bytes.length===0,nextSteps:[`Run pm history ${item.id} --full, then pm restore ${item.id} <version> to recover a recorded state.`]})};throw error}return{raw,document,error:null}}async function listAllItemMetadata(pmRoot,preferredFormat,typeToFolder=TYPE_TO_FOLDER,warnings,schema){await assertReadableTrackerRoot(pmRoot);const documents=await listAllDocumentsCached(pmRoot,preferredFormat,typeToFolder,warnings,schema);return recordItemMetadataEnumeration(documents.length),documents.map(document=>document.metadata)}async function listAllItemMetadataLight(pmRoot,preferredFormat,typeToFolder=TYPE_TO_FOLDER,warnings,schema){await assertReadableTrackerRoot(pmRoot);const documents=await listAllDocumentsCachedLight(pmRoot,preferredFormat,typeToFolder,warnings,schema);return recordItemMetadataEnumeration(documents.length),documents.map(document=>document.metadata)}async function listAllItemMetadataWithBody(pmRoot,preferredFormat,typeToFolder=TYPE_TO_FOLDER,warnings,schema,options={}){await assertReadableTrackerRoot(pmRoot);const candidates=await listAllDocumentCandidatesCached(pmRoot,preferredFormat,typeToFolder,warnings,schema,{includeBody:!0,forceSourceScan:options.forceSourceScan});return recordItemMetadataEnumeration(candidates.length),candidates.map(candidate=>({...candidate.metadata,body:candidate.body}))}function createMutationGuardSdk(params){return{async get(id){const located=await locateItem(params.pmRoot,id,params.settings.id_prefix,params.settings.item_format,params.typeToFolder);if(!located)return null;const{document}=await readLocatedItem(located,{schema:params.settings.schema});return{item:document.metadata,body:document.body}},list:()=>listAllItemMetadata(params.pmRoot,params.settings.item_format,params.typeToFolder,void 0,params.settings.schema)}}async function listKnownItemIds(pmRoot,typeToFolder){const folders=new Set(Object.values(typeToFolder)),allIds=[];return await Promise.all([...folders].map(async folder=>{try{const entries=await fs.readdir(path.join(pmRoot,folder));for(const entry of entries)for(const ext of ITEM_FILE_EXTENSIONS)if(entry.toLowerCase().endsWith(ext)){allIds.push(entry.slice(0,-ext.length));break}}catch{}})),allIds}async function buildDidYouMeanSuggestions(pmRoot,badId,idPrefix,typeToFolder){const normalized=normalizeItemId(badId,idPrefix),ids=await listKnownItemIds(pmRoot,typeToFolder);if(ids.length===0)return[];const limit=Math.max(3,Math.floor(normalized.length/2));return ids.map(id=>({id,distance:levenshteinDistanceWithinLimit(id,normalized,limit)})).filter(entry=>entry.distance!==null).sort((left,right)=>left.distance-right.distance).slice(0,3).map(entry=>entry.id)}async function buildItemNotFoundError(pmRoot,badId,idPrefix,typeToFolder){const deleted=await buildDeletedItemError(pmRoot,badId,idPrefix);if(deleted)return deleted;const suggestions=await buildDidYouMeanSuggestions(pmRoot,badId,idPrefix,typeToFolder),nextSteps=["Confirm the active --path/PM_PATH scope, then retry with a valid id."];return suggestions.length>0&&nextSteps.unshift(`Did you mean one of: ${suggestions.join(", ")}?`),new PmCliError(`Item ${badId} not found`,EXIT_CODE.NOT_FOUND,{nextSteps})}function bypassesAssigneeConflict(op,bypassAssigneeConflict){return op==="claim"||bypassAssigneeConflict===!0&&(op==="comment_add"||op==="comment_edit"||op==="comment_delete"||op==="note_add"||op==="learning_add"||op==="release"||op==="update"||op==="update_ownership_bypass"||op==="update_audit")}async function prepareLockedItem(params){const typeToFolder=params.typeToFolder??resolveItemTypeRegistry(params.settings,getActiveExtensionRegistrations()).type_to_folder,located=await locateItem(params.pmRoot,params.id,params.settings.id_prefix,params.settings.item_format,typeToFolder);if(!located)throw await buildItemNotFoundError(params.pmRoot,params.id,params.settings.id_prefix,typeToFolder);const releaseLock=await acquireLock(params.pmRoot,located.id,params.settings.locks.ttl_seconds,params.author,!!params.force,params.settings.governance.force_required_for_stale_lock,params.settings.locks.wait_ms);try{const warnings=[],{raw:originalRaw,document}=await readLocatedItem(located,{schema:params.settings.schema,extensionFieldNames:params.extensionFieldNames,warnings}),assigned=document.metadata.assignee?.trim(),assignedPrincipal=document.metadata.claim_principal?.trim()||assigned,callerPrincipal=resolveClaimPrincipal(params.author),governance=resolveGovernanceKnobs(params.settings);if(assigned&&assignedPrincipal!==callerPrincipal&&!params.force&&!bypassesAssigneeConflict(params.op,params.bypassAssigneeConflict)){if(governance.ownership_enforcement==="strict")throw new PmCliError(`Item ${located.id} is assigned to ${assigned}. Use --force to override.`,EXIT_CODE.CONFLICT);governance.ownership_enforcement==="warn"&&warnings.push(`ownership_warning:assignee_conflict:${located.id}:${assigned}`)}return{typeToFolder,located,originalRaw,document,warnings,releaseLock}}catch(error){throw await releaseLock(),error}}function resolveItemStoreWriteOverride(serviceWriteOverride,targetItemPath,serializedAfter){if(!serviceWriteOverride.handled||typeof serviceWriteOverride.result!="object"||serviceWriteOverride.result===null)return{effectiveTargetItemPath:targetItemPath,effectiveSerializedAfter:serializedAfter,skipItemWrite:!1};const overrideRecord=serviceWriteOverride.result;return{effectiveTargetItemPath:typeof overrideRecord.target_item_path=="string"&&overrideRecord.target_item_path.trim().length>0?overrideRecord.target_item_path:targetItemPath,effectiveSerializedAfter:typeof overrideRecord.contents=="string"?overrideRecord.contents:serializedAfter,skipItemWrite:overrideRecord.skip_write===!0}}async function rollbackMutatedItemWrite(params){if(!params.skipItemWrite){if(params.effectiveTargetItemPath!==params.originalItemPath){await writeFileAtomic(params.originalItemPath,params.originalRaw),await fs.rm(params.effectiveTargetItemPath,{force:!0});return}await writeFileAtomic(params.originalItemPath,params.originalRaw)}}async function mutateItemWithDeferredHistoryContext(params){normalizeHistoryOperationForWrite(params.op);const prepared=await prepareLockedItem({pmRoot:params.pmRoot,settings:params.settings,id:params.id,op:params.op,author:params.author,force:params.force,bypassAssigneeConflict:params.bypassAssigneeConflict,extensionFieldNames:params.extensionFieldNames,typeToFolder:params.typeToFolder}),{typeToFolder,located,originalRaw,document,warnings:parseWarnings,releaseLock}=prepared;try{const beforeDocument=canonicalDocument(document,{schema:params.settings.schema,extensionFieldNames:params.extensionFieldNames}),mutableDocument=canonicalDocument(structuredClone(document),{schema:params.settings.schema,extensionFieldNames:params.extensionFieldNames}),mutation=await params.mutate(mutableDocument);if(params.skipNoop===!0&&mutation.changedFields.length===0)return{item:beforeDocument.metadata,body:beforeDocument.body,changedFields:[],warnings:[...parseWarnings,...mutation.warnings??[]]};const historyContext=params.resolveHistoryContext?.();mutableDocument.metadata.updated_at=nowIso();const afterDocument=canonicalDocument(mutableDocument,{schema:params.settings.schema,extensionFieldNames:params.extensionFieldNames}),workflowPolicy=await enforceWorkflowMutation({pmRoot:params.pmRoot,settings:params.settings,operation:params.op,author:params.author,before:beforeDocument,after:afterDocument});await runActiveBeforeMutationHooks({pm_root:params.pmRoot,operation:params.op,before:beforeDocument,after:afterDocument,changed_fields:mutation.changedFields,sdk:createMutationGuardSdk({pmRoot:params.pmRoot,settings:params.settings,typeToFolder})});const historyPolicy=await enforceHistoryStreamPolicyForItem({pmRoot:params.pmRoot,settings:params.settings,itemId:located.id,commandLabel:params.op}),targetItemFormat="toon",serializedAfter=serializeItemDocument(afterDocument,{format:targetItemFormat,schema:params.settings.schema,extensionFieldNames:params.extensionFieldNames}),targetItemPath=getItemPath(params.pmRoot,afterDocument.metadata.type,located.id,targetItemFormat,typeToFolder),historyPath=getHistoryPath(params.pmRoot,located.id),serviceWriteOverride=await runActiveServiceOverride("item_store_write",{op:params.op,pm_root:params.pmRoot,item_id:located.id,source_item_path:located.itemPath,target_item_path:targetItemPath,history_path:historyPath,item_format:targetItemFormat,before:beforeDocument,after:afterDocument,contents:serializedAfter}),{effectiveTargetItemPath,effectiveSerializedAfter,skipItemWrite}=resolveItemStoreWriteOverride(serviceWriteOverride,targetItemPath,serializedAfter),releaseDerivedIndexLock=await acquireItemMetadataDerivedIndexLock(params.pmRoot,params.author);let derivedIndexWarnings=[];try{skipItemWrite||await writeFileAtomic(effectiveTargetItemPath,effectiveSerializedAfter),!skipItemWrite&&effectiveTargetItemPath!==located.itemPath&&await fs.rm(located.itemPath);const entry=createHistoryEntry({nowIso:afterDocument.metadata.updated_at,author:params.author,op:params.op,before:beforeDocument,after:afterDocument,message:params.message,context:workflowPolicy.decisions.length===0?historyContext:{...historyContext,workflow_policies:workflowPolicy.decisions}});try{await appendHistoryEntry(historyPath,entry)}catch(error){throw await rollbackMutatedItemWrite({skipItemWrite,effectiveTargetItemPath,originalItemPath:located.itemPath,originalRaw}),error}skipItemWrite||(derivedIndexWarnings=await refreshItemMetadataDerivedIndex({pmRoot:params.pmRoot,preferredFormat:params.settings.item_format,typeToFolder,schema:params.settings.schema,itemPath:effectiveTargetItemPath,previousItemPath:located.itemPath,document:afterDocument}))}finally{await releaseDerivedIndexLock()}const hookWarnings=[...await runActiveOnWriteHooks({path:effectiveTargetItemPath,scope:"project",op:params.op,item_id:afterDocument.metadata.id,item_type:afterDocument.metadata.type,before:beforeDocument,after:afterDocument,changed_fields:mutation.changedFields}),...await runActiveOnWriteHooks({path:historyPath,scope:"project",op:`${params.op}:history`,item_id:afterDocument.metadata.id,item_type:afterDocument.metadata.type,before:beforeDocument,after:afterDocument,changed_fields:mutation.changedFields})];return recordAfterCommandAffectedItem({id:afterDocument.metadata.id,op:params.op,item_type:afterDocument.metadata.type,previous_status:beforeDocument.metadata.status,status:afterDocument.metadata.status,previous:projectAfterCommandItemSnapshot(beforeDocument.metadata,mutation.changedFields),current:projectAfterCommandItemSnapshot(afterDocument.metadata,mutation.changedFields),changed_fields:mutation.changedFields}),{item:afterDocument.metadata,body:afterDocument.body,changedFields:mutation.changedFields,warnings:[...parseWarnings,...mutation.warnings??[],...workflowPolicy.warnings,...historyPolicy.warnings,...serviceWriteOverride.warnings,...derivedIndexWarnings,...hookWarnings]}}finally{await releaseLock()}}async function mutateItemWithHistoryContext(params){const{historyContext,...mutationParams}=params;return mutateItemWithDeferredHistoryContext({...mutationParams,resolveHistoryContext:()=>historyContext})}async function mutateItemWithHistoryContextResolver(params){return mutateItemWithDeferredHistoryContext(params)}async function mutateItem(params){return mutateItemWithDeferredHistoryContext(params)}const itemStoreTestOnly={appendWarning,bypassesAssigneeConflict,buildDidYouMeanSuggestions,isErrno};async function deleteItem(params){const prepared=await prepareLockedItem({pmRoot:params.pmRoot,settings:params.settings,id:params.id,op:"delete",author:params.author,force:params.force}),{located,originalRaw,document,warnings:parseWarnings,releaseLock}=prepared;try{const extensionFieldNames=resolveActiveExtensionFieldNames(void 0),beforeDocument=canonicalDocument(document,{schema:params.settings.schema,extensionFieldNames}),workflowPolicy=await enforceWorkflowMutation({pmRoot:params.pmRoot,settings:params.settings,operation:"delete",author:params.author,before:beforeDocument,after:null,dryRun:params.dryRun});await runActiveBeforeMutationHooks({pm_root:params.pmRoot,operation:"delete",before:beforeDocument,after:null,changed_fields:["deleted"],sdk:createMutationGuardSdk({pmRoot:params.pmRoot,settings:params.settings,typeToFolder:prepared.typeToFolder})});const historyPolicy=await enforceHistoryStreamPolicyForItem({pmRoot:params.pmRoot,settings:params.settings,itemId:located.id,commandLabel:"delete"}),deletionTimestamp=nowIso(),tombstoneDocument=EMPTY_CANONICAL_DOCUMENT,historyEntry=createHistoryEntry({nowIso:deletionTimestamp,author:params.author,op:"delete",before:beforeDocument,after:tombstoneDocument,message:params.message,context:workflowPolicy.decisions.length===0?void 0:{workflow_policies:workflowPolicy.decisions}}),historyPath=getHistoryPath(params.pmRoot,located.id),serviceDeleteOverride=await runActiveServiceOverride("item_store_delete",{op:"delete",pm_root:params.pmRoot,item_id:located.id,item_path:located.itemPath,history_path:historyPath,before:beforeDocument});let effectiveItemPath=located.itemPath,skipDelete=!1;if(serviceDeleteOverride.handled&&typeof serviceDeleteOverride.result=="object"&&serviceDeleteOverride.result!==null){const overrideRecord=serviceDeleteOverride.result;typeof overrideRecord.item_path=="string"&&overrideRecord.item_path.trim().length>0&&(effectiveItemPath=overrideRecord.item_path),overrideRecord.skip_delete===!0&&(skipDelete=!0)}if(params.dryRun===!0)return{item:beforeDocument.metadata,changedFields:["deleted"],targetPath:effectiveItemPath,warnings:[...parseWarnings,...workflowPolicy.warnings,...historyPolicy.warnings,...serviceDeleteOverride.warnings]};const releaseDerivedIndexLock=await acquireItemMetadataDerivedIndexLock(params.pmRoot,params.author);let derivedIndexWarnings=[];try{skipDelete||await fs.rm(effectiveItemPath);try{await appendHistoryEntry(historyPath,historyEntry)}catch(error){throw skipDelete||await writeFileAtomic(effectiveItemPath,originalRaw),error}skipDelete||(derivedIndexWarnings=await refreshItemMetadataDerivedIndex({pmRoot:params.pmRoot,preferredFormat:params.settings.item_format,typeToFolder:prepared.typeToFolder,schema:params.settings.schema,itemPath:effectiveItemPath,document:null}))}finally{await releaseDerivedIndexLock()}const hookWarnings=[...await runActiveOnWriteHooks({path:effectiveItemPath,scope:"project",op:"delete",item_id:beforeDocument.metadata.id,item_type:beforeDocument.metadata.type,before:beforeDocument,after:tombstoneDocument,changed_fields:["deleted"]}),...await runActiveOnWriteHooks({path:historyPath,scope:"project",op:"delete:history",item_id:beforeDocument.metadata.id,item_type:beforeDocument.metadata.type,before:beforeDocument,after:tombstoneDocument,changed_fields:["deleted"]})];return recordAfterCommandAffectedItem({id:beforeDocument.metadata.id,op:"delete",item_type:beforeDocument.metadata.type,previous_status:beforeDocument.metadata.status,previous:projectAfterCommandItemSnapshot(beforeDocument.metadata,Object.keys(beforeDocument.metadata)),changed_fields:["deleted"]}),{item:beforeDocument.metadata,changedFields:["deleted"],warnings:[...parseWarnings,...workflowPolicy.warnings,...historyPolicy.warnings,...serviceDeleteOverride.warnings,...derivedIndexWarnings,...hookWarnings]}}finally{await releaseLock()}}export{buildItemNotFoundError,createMutationGuardSdk,deleteItem,itemStoreTestOnly,listAllItemMetadata,listAllItemMetadataLight,listAllItemMetadataWithBody,locateItem,mutateItem,mutateItemWithHistoryContext,mutateItemWithHistoryContextResolver,readLocatedItem,readLocatedItemSnapshot};
|
|
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]="ce5fc177-192a-5efe-a65f-59f0fc0bea42")}catch{}})();import fs from"node:fs/promises";import{buildDeletedItemError}from"../history/tombstone.js";import{normalizeHistoryOperationForWrite}from"../history/operation-contract.js";import{enforceWorkflowMutation}from"../policy/workflow-policy-store.js";import{recordItemMetadataEnumeration}from"./item-metadata-read-work.js";import path from"node:path";import{getActiveExtensionRegistrations,projectAfterCommandItemSnapshot,recordAfterCommandAffectedItem,runActiveOnReadHooks,runActiveBeforeMutationHooks,runActiveOnWriteHooks,runActiveServiceOverride}from"../extensions/index.js";import{collectRegisteredItemFieldNames}from"../extensions/item-fields.js";import{EMPTY_CANONICAL_DOCUMENT,EXIT_CODE,TYPE_TO_FOLDER}from"../shared/constants.js";import{PmCliError}from"../shared/errors.js";import{levenshteinDistanceWithinLimit}from"../shared/levenshtein.js";import{appendHistoryEntry,createHistoryEntry}from"../history/history.js";import{enforceHistoryStreamPolicyForItem}from"../history/history-stream-policy.js";import{canonicalDocument,parseItemDocument,serializeItemDocument}from"../item/item-format.js";import{resolveItemTypeRegistry}from"../item/type-registry.js";import{acquireLock}from"../lock/lock.js";import{writeFileAtomic}from"../fs/fs-utils.js";import{isUtf8}from"node:buffer";import{normalizeItemId,normalizeRawItemId}from"../item/id.js";import{acquireItemMetadataDerivedIndexLock,listAllDocumentCandidatesCached,listAllDocumentsCached,listAllDocumentsCachedLight,refreshItemMetadataDerivedIndex}from"./item-metadata-cache.js";import{getHistoryPath,getItemPath,ITEM_FILE_EXTENSIONS}from"./paths.js";import{resolveGovernanceKnobs}from"./settings.js";import{assertReadableTrackerRoot}from"./tracker-preflight.js";import{resolveClaimPrincipal}from"../shared/author.js";import{nowIso}from"../shared/time.js";async function fileExists(targetPath){try{return await fs.access(targetPath),!0}catch{return!1}}function isErrno(error,code){return typeof error=="object"&&error!==null&&"code"in error&&error.code===code}function appendWarning(warnings,warning){warnings&&(warnings.includes(warning)||warnings.push(warning))}function resolveActiveExtensionFieldNames(explicit){return explicit??collectRegisteredItemFieldNames(getActiveExtensionRegistrations())}function resolveItemFormatSearchOrder(preferredFormat){return preferredFormat==="toon"?["toon","json_markdown"]:preferredFormat==="json_markdown"?["json_markdown","toon"]:["toon","json_markdown"]}async function locateItem(pmRoot,rawId,idPrefix="pm-",preferredFormat,typeToFolder=TYPE_TO_FOLDER){const trimmedRawId=rawId.trim(),exactRawId=trimmedRawId.startsWith("#")?trimmedRawId.slice(1):trimmedRawId;if(exactRawId.length===0)return null;const normalizedId=normalizeItemId(rawId,idPrefix),rawNormalizedId=normalizeRawItemId(rawId),candidateIds=[...new Set([exactRawId,normalizedId,rawNormalizedId])].filter(candidateId=>candidateId.length>0),entries=Object.entries(typeToFolder),searchOrder=resolveItemFormatSearchOrder(preferredFormat);for(const candidateId of candidateIds){const matches=new Map;for(const[type]of entries)for(const itemFormat of searchOrder){const itemPath=getItemPath(pmRoot,type,candidateId,itemFormat,typeToFolder);await fileExists(itemPath)&&matches.set(itemPath,matches.get(itemPath)??{id:candidateId,type,itemPath,item_format:itemFormat})}if(matches.size>1){const paths=[...matches.keys()].map(itemPath=>path.relative(pmRoot,itemPath).split(path.sep).join("/")).sort();throw new PmCliError(`Item ${candidateId} has ambiguous identity across ${paths.join(", ")}. Preserve both documents and inspect pm ops validate --check-storage-integrity before resolving the collision.`,EXIT_CODE.CONFLICT,{code:"item_identity_ambiguous",item_id:candidateId,paths})}for(const match of matches.values())return match}return null}async function readLocatedItem(item,options={}){const snapshot=await readLocatedItemSnapshot(item,options);if(snapshot.error!==null)throw snapshot.error;return{raw:snapshot.raw,document:snapshot.document}}async function readLocatedItemSnapshot(item,options={}){const bytes=await fs.readFile(item.itemPath);if(!isUtf8(bytes))throw new PmCliError("Item contains invalid UTF-8; preserve a binary backup before recovering it.",EXIT_CODE.CONFLICT,{code:"item_document_encoding_invalid",item_id:item.id,item_path:item.itemPath,byte_length:bytes.length,empty:!1});const raw=bytes.toString("utf8");await runActiveOnReadHooks({path:item.itemPath,scope:"project"});let document;try{document=parseItemDocument(raw,{format:item.item_format,requireSupportedFormat:!0,schema:options.schema,extensionFieldNames:resolveActiveExtensionFieldNames(options.extensionFieldNames),onWarning:warning=>appendWarning(options.warnings,warning)})}catch(error){if(error instanceof PmCliError&&error.code==="item_format_version_unsupported")throw new PmCliError(`Item ${item.id}: ${error.message}`,error.exitCode,{...error.context,item_id:item.id,item_path:item.itemPath});if(error instanceof PmCliError&&error.code==="item_document_invalid")return{raw,document:null,error:new PmCliError(`Cannot read ${item.id} at ${item.itemPath}${bytes.length===0?" (zero-length file)":""}: ${error.message}`,error.exitCode,{...error.context,item_id:item.id,item_path:item.itemPath,byte_length:bytes.length,empty:bytes.length===0,nextSteps:[`Run pm history ${item.id} --full, then pm restore ${item.id} <version> to recover a recorded state.`]})};throw error}return{raw,document,error:null}}async function listAllItemMetadata(pmRoot,preferredFormat,typeToFolder=TYPE_TO_FOLDER,warnings,schema){await assertReadableTrackerRoot(pmRoot);const documents=await listAllDocumentsCached(pmRoot,preferredFormat,typeToFolder,warnings,schema);return recordItemMetadataEnumeration(documents.length),documents.map(document=>document.metadata)}async function listAllItemMetadataLight(pmRoot,preferredFormat,typeToFolder=TYPE_TO_FOLDER,warnings,schema){await assertReadableTrackerRoot(pmRoot);const documents=await listAllDocumentsCachedLight(pmRoot,preferredFormat,typeToFolder,warnings,schema);return recordItemMetadataEnumeration(documents.length),documents.map(document=>document.metadata)}async function listAllItemMetadataWithBody(pmRoot,preferredFormat,typeToFolder=TYPE_TO_FOLDER,warnings,schema,options={}){await assertReadableTrackerRoot(pmRoot);const candidates=await listAllDocumentCandidatesCached(pmRoot,preferredFormat,typeToFolder,warnings,schema,{includeBody:!0,forceSourceScan:options.forceSourceScan});return recordItemMetadataEnumeration(candidates.length),candidates.map(candidate=>({...candidate.metadata,body:candidate.body}))}function createMutationGuardSdk(params){return{async get(id){const located=await locateItem(params.pmRoot,id,params.settings.id_prefix,params.settings.item_format,params.typeToFolder);if(!located)return null;const{document}=await readLocatedItem(located,{schema:params.settings.schema});return{item:document.metadata,body:document.body}},list:()=>listAllItemMetadata(params.pmRoot,params.settings.item_format,params.typeToFolder,void 0,params.settings.schema)}}async function listKnownItemIds(pmRoot,typeToFolder){const folders=new Set(Object.values(typeToFolder)),allIds=[];return await Promise.all([...folders].map(async folder=>{try{const entries=await fs.readdir(path.join(pmRoot,folder));for(const entry of entries)for(const ext of ITEM_FILE_EXTENSIONS)if(entry.toLowerCase().endsWith(ext)){allIds.push(entry.slice(0,-ext.length));break}}catch{}})),allIds}async function buildDidYouMeanSuggestions(pmRoot,badId,idPrefix,typeToFolder){const normalized=normalizeItemId(badId,idPrefix),ids=await listKnownItemIds(pmRoot,typeToFolder);if(ids.length===0)return[];const limit=Math.max(3,Math.floor(normalized.length/2));return ids.map(id=>({id,distance:levenshteinDistanceWithinLimit(id,normalized,limit)})).filter(entry=>entry.distance!==null).sort((left,right)=>left.distance-right.distance).slice(0,3).map(entry=>entry.id)}async function buildItemNotFoundError(pmRoot,badId,idPrefix,typeToFolder){const deleted=await buildDeletedItemError(pmRoot,badId,idPrefix);if(deleted)return deleted;const suggestions=await buildDidYouMeanSuggestions(pmRoot,badId,idPrefix,typeToFolder),nextSteps=["Confirm the active --path/PM_PATH scope, then retry with a valid id."];return suggestions.length>0&&nextSteps.unshift(`Did you mean one of: ${suggestions.join(", ")}?`),new PmCliError(`Item ${badId} not found`,EXIT_CODE.NOT_FOUND,{nextSteps})}function bypassesAssigneeConflict(op,bypassAssigneeConflict){return op==="claim"||bypassAssigneeConflict===!0&&(op==="comment_add"||op==="comment_edit"||op==="comment_delete"||op==="note_add"||op==="learning_add"||op==="release"||op==="update"||op==="update_ownership_bypass"||op==="update_audit")}async function prepareLockedItem(params){const typeToFolder=params.typeToFolder??resolveItemTypeRegistry(params.settings,getActiveExtensionRegistrations()).type_to_folder,located=await locateItem(params.pmRoot,params.id,params.settings.id_prefix,params.settings.item_format,typeToFolder);if(!located)throw await buildItemNotFoundError(params.pmRoot,params.id,params.settings.id_prefix,typeToFolder);const releaseLock=await acquireLock(params.pmRoot,located.id,params.settings.locks.ttl_seconds,params.author,!!params.force,params.settings.governance.force_required_for_stale_lock,params.settings.locks.wait_ms);try{const warnings=[],{raw:originalRaw,document}=await readLocatedItem(located,{schema:params.settings.schema,extensionFieldNames:params.extensionFieldNames,warnings}),assigned=document.metadata.assignee?.trim(),assignedPrincipal=document.metadata.claim_principal?.trim()||assigned,callerPrincipal=resolveClaimPrincipal(params.author),governance=resolveGovernanceKnobs(params.settings);if(assigned&&assignedPrincipal!==callerPrincipal&&!params.force&&!bypassesAssigneeConflict(params.op,params.bypassAssigneeConflict)){if(governance.ownership_enforcement==="strict")throw new PmCliError(`Item ${located.id} is assigned to ${assigned}. Use --force to override.`,EXIT_CODE.CONFLICT);governance.ownership_enforcement==="warn"&&warnings.push(`ownership_warning:assignee_conflict:${located.id}:${assigned}`)}return{typeToFolder,located,originalRaw,document,warnings,releaseLock}}catch(error){throw await releaseLock(),error}}function resolveItemStoreWriteOverride(serviceWriteOverride,targetItemPath,serializedAfter){if(!serviceWriteOverride.handled||typeof serviceWriteOverride.result!="object"||serviceWriteOverride.result===null)return{effectiveTargetItemPath:targetItemPath,effectiveSerializedAfter:serializedAfter,skipItemWrite:!1};const overrideRecord=serviceWriteOverride.result;return{effectiveTargetItemPath:typeof overrideRecord.target_item_path=="string"&&overrideRecord.target_item_path.trim().length>0?overrideRecord.target_item_path:targetItemPath,effectiveSerializedAfter:typeof overrideRecord.contents=="string"?overrideRecord.contents:serializedAfter,skipItemWrite:overrideRecord.skip_write===!0}}async function rollbackMutatedItemWrite(params){if(!params.skipItemWrite){if(params.effectiveTargetItemPath!==params.originalItemPath){await writeFileAtomic(params.originalItemPath,params.originalRaw),await fs.rm(params.effectiveTargetItemPath,{force:!0});return}await writeFileAtomic(params.originalItemPath,params.originalRaw)}}async function mutateItemWithDeferredHistoryContext(params){normalizeHistoryOperationForWrite(params.op);const prepared=await prepareLockedItem({pmRoot:params.pmRoot,settings:params.settings,id:params.id,op:params.op,author:params.author,force:params.force,bypassAssigneeConflict:params.bypassAssigneeConflict,extensionFieldNames:params.extensionFieldNames,typeToFolder:params.typeToFolder}),{typeToFolder,located,originalRaw,document,warnings:parseWarnings,releaseLock}=prepared;try{const beforeDocument=canonicalDocument(document,{schema:params.settings.schema,extensionFieldNames:params.extensionFieldNames}),mutableDocument=canonicalDocument(structuredClone(document),{schema:params.settings.schema,extensionFieldNames:params.extensionFieldNames}),mutation=await params.mutate(mutableDocument);if(params.skipNoop===!0&&mutation.changedFields.length===0)return{item:beforeDocument.metadata,body:beforeDocument.body,changedFields:[],warnings:[...parseWarnings,...mutation.warnings??[]]};const historyContext=params.resolveHistoryContext?.();mutableDocument.metadata.updated_at=nowIso();const afterDocument=canonicalDocument(mutableDocument,{schema:params.settings.schema,extensionFieldNames:params.extensionFieldNames}),workflowPolicy=await enforceWorkflowMutation({pmRoot:params.pmRoot,settings:params.settings,operation:params.op,author:params.author,before:beforeDocument,after:afterDocument});await runActiveBeforeMutationHooks({pm_root:params.pmRoot,operation:params.op,before:beforeDocument,after:afterDocument,changed_fields:mutation.changedFields,sdk:createMutationGuardSdk({pmRoot:params.pmRoot,settings:params.settings,typeToFolder})});const historyPolicy=await enforceHistoryStreamPolicyForItem({pmRoot:params.pmRoot,settings:params.settings,itemId:located.id,commandLabel:params.op}),targetItemFormat="toon",serializedAfter=serializeItemDocument(afterDocument,{format:targetItemFormat,schema:params.settings.schema,extensionFieldNames:params.extensionFieldNames}),targetItemPath=getItemPath(params.pmRoot,afterDocument.metadata.type,located.id,targetItemFormat,typeToFolder),historyPath=getHistoryPath(params.pmRoot,located.id),serviceWriteOverride=await runActiveServiceOverride("item_store_write",{op:params.op,pm_root:params.pmRoot,item_id:located.id,source_item_path:located.itemPath,target_item_path:targetItemPath,history_path:historyPath,item_format:targetItemFormat,before:beforeDocument,after:afterDocument,contents:serializedAfter}),{effectiveTargetItemPath,effectiveSerializedAfter,skipItemWrite}=resolveItemStoreWriteOverride(serviceWriteOverride,targetItemPath,serializedAfter),releaseDerivedIndexLock=await acquireItemMetadataDerivedIndexLock(params.pmRoot,params.author);let derivedIndexWarnings=[];try{skipItemWrite||await writeFileAtomic(effectiveTargetItemPath,effectiveSerializedAfter),!skipItemWrite&&effectiveTargetItemPath!==located.itemPath&&await fs.rm(located.itemPath);const entry=createHistoryEntry({nowIso:afterDocument.metadata.updated_at,author:params.author,op:params.op,before:beforeDocument,after:afterDocument,message:params.message,context:workflowPolicy.decisions.length===0?historyContext:{...historyContext,workflow_policies:workflowPolicy.decisions}});try{await appendHistoryEntry(historyPath,entry)}catch(error){throw await rollbackMutatedItemWrite({skipItemWrite,effectiveTargetItemPath,originalItemPath:located.itemPath,originalRaw}),error}skipItemWrite||(derivedIndexWarnings=await refreshItemMetadataDerivedIndex({pmRoot:params.pmRoot,preferredFormat:params.settings.item_format,typeToFolder,schema:params.settings.schema,itemPath:effectiveTargetItemPath,previousItemPath:located.itemPath,document:afterDocument}))}finally{await releaseDerivedIndexLock()}const hookWarnings=[...await runActiveOnWriteHooks({path:effectiveTargetItemPath,scope:"project",op:params.op,item_id:afterDocument.metadata.id,item_type:afterDocument.metadata.type,before:beforeDocument,after:afterDocument,changed_fields:mutation.changedFields}),...await runActiveOnWriteHooks({path:historyPath,scope:"project",op:`${params.op}:history`,item_id:afterDocument.metadata.id,item_type:afterDocument.metadata.type,before:beforeDocument,after:afterDocument,changed_fields:mutation.changedFields})];return recordAfterCommandAffectedItem({id:afterDocument.metadata.id,op:params.op,item_type:afterDocument.metadata.type,previous_status:beforeDocument.metadata.status,status:afterDocument.metadata.status,previous:projectAfterCommandItemSnapshot(beforeDocument.metadata,mutation.changedFields),current:projectAfterCommandItemSnapshot(afterDocument.metadata,mutation.changedFields),changed_fields:mutation.changedFields}),{item:afterDocument.metadata,body:afterDocument.body,changedFields:mutation.changedFields,warnings:[...parseWarnings,...mutation.warnings??[],...workflowPolicy.warnings,...historyPolicy.warnings,...serviceWriteOverride.warnings,...derivedIndexWarnings,...hookWarnings]}}finally{await releaseLock()}}async function mutateItemWithHistoryContext(params){const{historyContext,...mutationParams}=params;return mutateItemWithDeferredHistoryContext({...mutationParams,resolveHistoryContext:()=>historyContext})}async function mutateItemWithHistoryContextResolver(params){return mutateItemWithDeferredHistoryContext(params)}async function mutateItem(params){return mutateItemWithDeferredHistoryContext(params)}const itemStoreTestOnly={appendWarning,bypassesAssigneeConflict,buildDidYouMeanSuggestions,isErrno};async function deleteItem(params){const prepared=await prepareLockedItem({pmRoot:params.pmRoot,settings:params.settings,id:params.id,op:"delete",author:params.author,force:params.force}),{located,originalRaw,document,warnings:parseWarnings,releaseLock}=prepared;try{const extensionFieldNames=resolveActiveExtensionFieldNames(void 0),beforeDocument=canonicalDocument(document,{schema:params.settings.schema,extensionFieldNames}),workflowPolicy=await enforceWorkflowMutation({pmRoot:params.pmRoot,settings:params.settings,operation:"delete",author:params.author,before:beforeDocument,after:null,dryRun:params.dryRun});await runActiveBeforeMutationHooks({pm_root:params.pmRoot,operation:"delete",before:beforeDocument,after:null,changed_fields:["deleted"],sdk:createMutationGuardSdk({pmRoot:params.pmRoot,settings:params.settings,typeToFolder:prepared.typeToFolder})});const historyPolicy=await enforceHistoryStreamPolicyForItem({pmRoot:params.pmRoot,settings:params.settings,itemId:located.id,commandLabel:"delete"}),deletionTimestamp=nowIso(),tombstoneDocument=EMPTY_CANONICAL_DOCUMENT,historyEntry=createHistoryEntry({nowIso:deletionTimestamp,author:params.author,op:"delete",before:beforeDocument,after:tombstoneDocument,message:params.message,context:workflowPolicy.decisions.length===0?void 0:{workflow_policies:workflowPolicy.decisions}}),historyPath=getHistoryPath(params.pmRoot,located.id),serviceDeleteOverride=await runActiveServiceOverride("item_store_delete",{op:"delete",pm_root:params.pmRoot,item_id:located.id,item_path:located.itemPath,history_path:historyPath,before:beforeDocument});let effectiveItemPath=located.itemPath,skipDelete=!1;if(serviceDeleteOverride.handled&&typeof serviceDeleteOverride.result=="object"&&serviceDeleteOverride.result!==null){const overrideRecord=serviceDeleteOverride.result;typeof overrideRecord.item_path=="string"&&overrideRecord.item_path.trim().length>0&&(effectiveItemPath=overrideRecord.item_path),overrideRecord.skip_delete===!0&&(skipDelete=!0)}if(params.dryRun===!0)return{item:beforeDocument.metadata,changedFields:["deleted"],targetPath:effectiveItemPath,warnings:[...parseWarnings,...workflowPolicy.warnings,...historyPolicy.warnings,...serviceDeleteOverride.warnings]};const releaseDerivedIndexLock=await acquireItemMetadataDerivedIndexLock(params.pmRoot,params.author);let derivedIndexWarnings=[];try{skipDelete||await fs.rm(effectiveItemPath);try{await appendHistoryEntry(historyPath,historyEntry)}catch(error){throw skipDelete||await writeFileAtomic(effectiveItemPath,originalRaw),error}skipDelete||(derivedIndexWarnings=await refreshItemMetadataDerivedIndex({pmRoot:params.pmRoot,preferredFormat:params.settings.item_format,typeToFolder:prepared.typeToFolder,schema:params.settings.schema,itemPath:effectiveItemPath,document:null}))}finally{await releaseDerivedIndexLock()}const hookWarnings=[...await runActiveOnWriteHooks({path:effectiveItemPath,scope:"project",op:"delete",item_id:beforeDocument.metadata.id,item_type:beforeDocument.metadata.type,before:beforeDocument,after:tombstoneDocument,changed_fields:["deleted"]}),...await runActiveOnWriteHooks({path:historyPath,scope:"project",op:"delete:history",item_id:beforeDocument.metadata.id,item_type:beforeDocument.metadata.type,before:beforeDocument,after:tombstoneDocument,changed_fields:["deleted"]})];return recordAfterCommandAffectedItem({id:beforeDocument.metadata.id,op:"delete",item_type:beforeDocument.metadata.type,previous_status:beforeDocument.metadata.status,previous:projectAfterCommandItemSnapshot(beforeDocument.metadata,Object.keys(beforeDocument.metadata)),changed_fields:["deleted"]}),{item:beforeDocument.metadata,changedFields:["deleted"],warnings:[...parseWarnings,...workflowPolicy.warnings,...historyPolicy.warnings,...serviceDeleteOverride.warnings,...derivedIndexWarnings,...hookWarnings]}}finally{await releaseLock()}}export{buildItemNotFoundError,createMutationGuardSdk,deleteItem,itemStoreTestOnly,listAllItemMetadata,listAllItemMetadataLight,listAllItemMetadataWithBody,locateItem,mutateItem,mutateItemWithHistoryContext,mutateItemWithHistoryContextResolver,readLocatedItem,readLocatedItemSnapshot};
|
|
2
2
|
//# sourceMappingURL=item-store.js.map
|