@unbrained/pm-cli 2026.10.10 → 2026.10.12
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 +1 -36
- package/CHANGELOG.md +31 -4
- package/dist/cli/commander-usage.d.ts +5 -5
- package/dist/cli/commander-usage.js +3 -3
- package/dist/cli/error-guidance.d.ts +2 -0
- package/dist/cli/error-guidance.js +2 -2
- package/dist/cli/help-json-payload.js +1 -1
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +4 -4
- package/dist/cli/register-operations.d.ts +9 -4
- package/dist/cli/register-operations.js +1 -1
- package/dist/cli-bundle/bundle-manifest.json +1 -382
- package/dist/cli-bundle/chunks/{chunk-2JYTSTQP.js → chunk-3LQTJN4J.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-YMLF6QT7.js → chunk-6PZPUJW3.js} +28 -28
- package/dist/cli-bundle/chunks/{chunk-RUT3CCAG.js → chunk-B465HPS5.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ESRACL6K.js → chunk-DT3KUUKY.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-SSY4OSJR.js → chunk-GUVKPOY6.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-ILQEZ4Y6.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-RBPOO46D.js → chunk-JRRXWH5B.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-MEWBSWE3.js → chunk-LH5QDBMN.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-KNW3RSLS.js → chunk-M5NDSW6E.js} +30 -30
- package/dist/cli-bundle/chunks/{chunk-K2UTE75T.js → chunk-MHPU2LDF.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-OBLO45UM.js → chunk-QM3M7GB5.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-S445XEYT.js → chunk-UABZJXIS.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ZWRLAOA4.js → chunk-X2I2EEAS.js} +2 -2
- package/dist/cli-bundle/chunks/{register-list-query-T6BOR67M.js → register-list-query-OR33UEML.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-6NXR7SAJ.js → register-mutation-R34EJ3NH.js} +2 -2
- package/dist/cli-bundle/chunks/register-operations-UHSMEHSF.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-MAYFPKBX.js → register-setup-5E3PT22L.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-SIEGIPNT.js → chunk-7QIZB2F2.js} +7 -7
- package/dist/cli-bundle/focused-chunks/{chunk-PLTTMQAW.js → chunk-AJG3DBXR.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-AXBO53EQ.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-W5AE7GKZ.js → chunk-CYEZLKLL.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-PBCYGO7X.js → chunk-FXRWJEQ5.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-GVGFUD52.js → chunk-IKJFAU32.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-DMSADMEU.js → chunk-OGOLIS5R.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-PPH5N26M.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-WAOXID5J.js → chunk-RNAWRTQV.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-B3YW6H2I.js → chunk-RZVNGUT7.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-52UJEHEV.js → chunk-SV6YYZLR.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-EIOQNLBQ.js → chunk-TS46OZD5.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-KNJR2WUO.js → chunk-VBTLX5SN.js} +62 -62
- package/dist/cli-bundle/focused-chunks/{chunk-JGFSSR3G.js → chunk-YCOJLIDI.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-YDJT33JU.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-AU6VJGTY.js → chunk-Z4T3637Y.js} +2 -2
- package/dist/cli-bundle/main.js +22 -22
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +1 -1
- package/dist/cli-bundle/sdk-core.js +31 -31
- 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 +24 -24
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +9 -9
- package/dist/core/history/event-classification.d.ts +1 -1
- package/dist/core/history/event-classification.js +1 -1
- package/dist/core/item/item-format.d.ts +2 -0
- package/dist/core/item/item-format.js +2 -2
- package/dist/core/telemetry/runtime.d.ts +1 -1
- package/dist/core/telemetry/runtime.js +2 -2
- package/dist/core/test/background-runs.d.ts +1 -0
- package/dist/core/test/background-runs.js +2 -2
- package/dist/sdk/agent/command-suggestions.d.ts +2 -0
- package/dist/sdk/agent/command-suggestions.js +1 -1
- package/dist/sdk/cli-contracts/flag-contracts.js +1 -1
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -1
- package/dist/sdk/cli-contracts/grammar-contracts.js +1 -1
- package/dist/sdk/cli-contracts/registration-helpers.d.ts +1 -4
- package/dist/sdk/cli-contracts/registration-helpers.js +1 -1
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -1
- package/dist/sdk/cli-contracts/tool-schema.d.ts +1 -1
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1
- package/dist/sdk/core.d.ts +1 -0
- package/dist/sdk/core.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
- package/dist/sdk/governance/artifact-ledgers.d.ts +59 -0
- package/dist/sdk/governance/artifact-ledgers.js +2 -0
- package/dist/sdk/governance.d.ts +1 -0
- package/dist/sdk/governance.js +1 -1
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/test/batch.js +1 -1
- package/dist/sdk/test/command-args.d.ts +4 -0
- package/dist/sdk/test/command-args.js +2 -0
- package/dist/sdk/test/entry.d.ts +3 -0
- package/dist/sdk/test/entry.js +1 -1
- package/dist/sdk/test/execution.d.ts +15 -4
- package/dist/sdk/test/execution.js +2 -2
- package/dist/sdk/test/prerequisites.d.ts +6 -0
- package/dist/sdk/test/prerequisites.js +2 -0
- package/dist/sdk/test/trust.js +1 -1
- package/dist/sdk/test/update.d.ts +55 -0
- package/dist/sdk/test/update.js +2 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.js +1 -1
- package/docs/LINKED_TEST_EDITS.md +79 -0
- package/docs/RELEASE_LEDGER_RECONCILIATION.md +148 -0
- package/docs/RELEASE_RELIABILITY.md +4 -0
- package/docs/RELEASING.md +53 -13
- package/docs/SDK.md +178 -636
- package/docs/SDK_EVIDENCE_TRACEABILITY.md +4 -0
- package/docs/TESTING.md +13 -0
- package/docs/agent-task-token-baseline.json +1 -292
- package/docs/agent-task-transcripts.json +1 -478
- package/docs/ecosystem-review-2026-09-28.json +1 -2866
- package/docs/examples/policy-restricted-extension/manifest.json +1 -22
- package/docs/examples/policy-restricted-extension/package.json +1 -8
- package/docs/examples/sdk-agent-environment/package.json +1 -8
- package/docs/examples/sdk-app-embedding/package.json +1 -9
- package/docs/examples/sdk-contract-consumer/package.json +1 -11
- package/docs/examples/sdk-custom-tool/package.json +1 -13
- package/docs/examples/starter-extension/manifest.json +1 -33
- package/docs/examples/starter-extension/package.json +1 -10
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +2 -2
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +8 -3
- package/docs/performance/corpus-shape-comparison.json +1 -108
- package/docs/performance/latest-scale-report.json +1 -418
- package/docs/performance/runner-qualification.md +36 -0
- package/docs/performance/scale-100k-report.json +1 -418
- package/docs/schemas/extension-manifest.schema.json +1 -165
- package/marketplace.json +1 -36
- package/package.json +1 -1
- package/packages/pm-beads/extensions/beads/manifest.json +1 -28
- package/packages/pm-beads/extensions/beads/package.json +1 -3
- package/packages/pm-beads/package.json +1 -50
- package/packages/pm-calendar/extensions/calendar/manifest.json +1 -22
- package/packages/pm-calendar/extensions/calendar/package.json +1 -3
- package/packages/pm-calendar/package.json +1 -51
- package/packages/pm-command-kit/extensions/command-kit/manifest.json +1 -22
- package/packages/pm-command-kit/extensions/command-kit/package.json +1 -3
- package/packages/pm-command-kit/package.json +1 -53
- package/packages/pm-digital-twin/extensions/digital-twin/manifest.json +1 -19
- package/packages/pm-digital-twin/extensions/digital-twin/package.json +1 -3
- package/packages/pm-digital-twin/package.json +1 -58
- package/packages/pm-governance-audit/extensions/governance-audit/manifest.json +1 -19
- package/packages/pm-governance-audit/extensions/governance-audit/package.json +1 -3
- package/packages/pm-governance-audit/package.json +1 -55
- package/packages/pm-guide-shell/extensions/guide-shell/manifest.json +1 -22
- package/packages/pm-guide-shell/extensions/guide-shell/package.json +1 -3
- package/packages/pm-guide-shell/package.json +1 -52
- package/packages/pm-kanban/extensions/kanban/manifest.json +1 -19
- package/packages/pm-kanban/extensions/kanban/package.json +1 -3
- package/packages/pm-kanban/package.json +1 -57
- package/packages/pm-lifecycle-hooks/extensions/lifecycle-hooks/manifest.json +1 -19
- package/packages/pm-lifecycle-hooks/extensions/lifecycle-hooks/package.json +1 -3
- package/packages/pm-lifecycle-hooks/package.json +1 -52
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/manifest.json +1 -29
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/package.json +1 -3
- package/packages/pm-linked-test-adapters/package.json +1 -53
- package/packages/pm-search-advanced/extensions/search-advanced/manifest.json +1 -29
- package/packages/pm-search-advanced/extensions/search-advanced/package.json +1 -3
- package/packages/pm-search-advanced/package.json +1 -54
- package/packages/pm-templates/extensions/templates/manifest.json +1 -22
- package/packages/pm-templates/extensions/templates/package.json +1 -3
- package/packages/pm-templates/package.json +1 -50
- package/packages/pm-todos/extensions/todos/manifest.json +1 -29
- package/packages/pm-todos/extensions/todos/package.json +1 -3
- package/packages/pm-todos/package.json +1 -51
- package/packages/pm-vcs/extensions/vcs/manifest.json +1 -19
- package/packages/pm-vcs/extensions/vcs/package.json +1 -3
- package/packages/pm-vcs/package.json +1 -55
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -25
- package/plugins/pm-claude/.mcp.json +1 -8
- package/plugins/pm-claude/hooks/hooks.json +1 -17
- package/plugins/pm-claude/package.json +1 -9
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -45
- package/plugins/pm-codex/.mcp.json +1 -11
- package/plugins/pm-codex/mcp.json +1 -11
- package/plugins/pm-codex/package.json +1 -9
- package/plugins/pm-codex/plugin.json +1 -45
- package/runtime-dependencies.json +1 -512
- package/dist/cli-bundle/chunks/chunk-BXSXT5Z6.js +0 -2
- package/dist/cli-bundle/chunks/register-operations-PDOBQZUJ.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-2CJWTLQG.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-MJQ253F3.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-WOEZJUA2.js +0 -2
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { GlobalOptions } from "../../core/shared/command-types.js";
|
|
2
|
+
import type { LinkedTest } from "../../types/index.js";
|
|
3
|
+
import type { TestCommandOptions } from "./execution.js";
|
|
4
|
+
/** Unambiguous selector evaluated against the current locked collection. */
|
|
5
|
+
export type LinkedTestUpdateSelector = {
|
|
6
|
+
index: number;
|
|
7
|
+
} | {
|
|
8
|
+
command: string;
|
|
9
|
+
} | {
|
|
10
|
+
path: string;
|
|
11
|
+
};
|
|
12
|
+
/** Explicit metadata values; null removes an optional value without replacing other fields. */
|
|
13
|
+
export type LinkedTestMetadataPatch = {
|
|
14
|
+
[K in keyof Omit<LinkedTest, "command" | "provenance" | "provenance_invalid" | "updated_by" | "updated_at">]?: K extends "scope" ? LinkedTest[K] : LinkedTest[K] | null;
|
|
15
|
+
};
|
|
16
|
+
/** One metadata revision with ordinary mutation ownership and history controls. */
|
|
17
|
+
export interface UpdateLinkedTestOptions {
|
|
18
|
+
/** Current entry identity or one-based list position. */
|
|
19
|
+
selector: LinkedTestUpdateSelector;
|
|
20
|
+
/** Fields to change; command and provenance cannot be replaced. */
|
|
21
|
+
patch: LinkedTestMetadataPatch;
|
|
22
|
+
/** Explicit author override, otherwise the configured or detected identity. */
|
|
23
|
+
author?: string;
|
|
24
|
+
/** Explanation retained on the single history event. */
|
|
25
|
+
message?: string;
|
|
26
|
+
/** Explicit ownership override. */
|
|
27
|
+
force?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/** Receipt identifying the edited entry and semantically changed metadata. */
|
|
30
|
+
export interface UpdateLinkedTestResult {
|
|
31
|
+
/** Successful mutation or unchanged retry. */
|
|
32
|
+
ok: true;
|
|
33
|
+
/** Owning item ID. */
|
|
34
|
+
id: string;
|
|
35
|
+
/** Current ordered linked-test collection. */
|
|
36
|
+
tests: LinkedTest[];
|
|
37
|
+
/** Whether authoritative state changed. */
|
|
38
|
+
changed: boolean;
|
|
39
|
+
/** Current collection size. */
|
|
40
|
+
count: number;
|
|
41
|
+
/** One-based position of the selected entry. */
|
|
42
|
+
updated_index: number;
|
|
43
|
+
/** Explicit metadata keys whose normalized values changed. */
|
|
44
|
+
updated_fields: string[];
|
|
45
|
+
}
|
|
46
|
+
/** Resolve transport edit flags without accepting ambiguous selectors or implicit replacement. */
|
|
47
|
+
export declare function parseLinkedTestUpdateOptions(options: {
|
|
48
|
+
update?: string;
|
|
49
|
+
updateIndex?: string | number;
|
|
50
|
+
setJson?: string;
|
|
51
|
+
}): Pick<UpdateLinkedTestOptions, "selector" | "patch"> | undefined;
|
|
52
|
+
/** Keep metadata editing a separate atomic operation from execution or other collection changes. */
|
|
53
|
+
export declare function assertLinkedTestEditUsage(options: TestCommandOptions): void;
|
|
54
|
+
/** Patch one linked-test entry atomically, keeping ordering and original command provenance. */
|
|
55
|
+
export declare function updateLinkedTest(id: string, options: UpdateLinkedTestOptions, global?: GlobalOptions): Promise<UpdateLinkedTestResult>;
|
|
@@ -0,0 +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]="cfcc5f4f-caf0-5a2e-8a9d-219c3afb5d2d")}catch{}})();import{getActiveExtensionRegistrations}from"../../core/extensions/index.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{normalizeLinkedTest}from"../../core/item/item-format.js";import{parseOnlyIndexValue}from"../../core/test/run-selectors.js";import{resolveAuthor}from"../../core/shared/author.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{stableValueEquals}from"../../core/shared/serialization.js";import{nowIso}from"../../core/shared/time.js";import{mutateItemWithHistoryContextResolver}from"../../core/store/item-store.js";import{resolvePmRoot}from"../../core/store/paths.js";import{readSettings}from"../../core/store/settings.js";import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{assertLinkedTestContext,STRUCTURED_LINKED_TEST_KEYS}from"./entry.js";import{parseLinkedTestJsonEntries}from"./parsers.js";function parseLinkedTestUpdateOptions(options){if(options.update===void 0&&options.updateIndex===void 0&&options.setJson===void 0)return;if(options.update===void 0==(options.updateIndex===void 0)||options.setJson===void 0)throw new PmCliError("Use exactly one --update or --update-index with --set-json",EXIT_CODE.USAGE);let patch;try{patch=JSON.parse(options.setJson)}catch{throw new PmCliError("--set-json must contain a JSON object with explicit linked-test metadata fields",EXIT_CODE.USAGE)}if(options.updateIndex!==void 0)return{selector:{index:parseOnlyIndexValue(options.updateIndex,"--update-index")},patch};const value=options.update,prefix=/^(command|path)=/u.exec(value);return{selector:prefix?.[1]==="path"?{path:value.slice(prefix[0].length)}:{command:prefix?value.slice(prefix[0].length):value},patch}}function assertLinkedTestEditUsage(options){if([options.list,options.run,options.progress,options.timeout!==void 0,options.acknowledgeLinkedTests,options.metricBelow!==void 0,options.metricDiff!==void 0,(options.add?.length??0)>0,(options.addJson?.length??0)>0,(options.remove?.length??0)>0,(options.removeIndex?.length??0)>0].some(Boolean))throw new PmCliError("Edit linked-test metadata separately from listing, additions, removals, execution options, metric filters and trust acknowledgement",EXIT_CODE.USAGE)}function selectIndex(tests,selector){if(typeof selector!="object"||selector===null||Array.isArray(selector))throw new PmCliError("Select one linked test by index, command, or path",EXIT_CODE.USAGE);const keys=Object.keys(selector);if(keys.length!==1||!["index","command","path"].includes(keys[0]))throw new PmCliError("Select one linked test by index, command, or path",EXIT_CODE.USAGE);if("index"in selector){const index=parseOnlyIndexValue(selector.index,"--update-index");if(index<=tests.length)return index-1}else{const key="command"in selector?"command":"path",value="command"in selector?selector.command:selector.path;if(typeof value!="string"||value.trim().length===0)throw new PmCliError("Linked-test selector must be a non-empty command or path",EXIT_CODE.USAGE);const matches=tests.flatMap((test,index)=>test[key]===value?[index]:[]);if(matches.length===1)return matches[0];if(matches.length>1)throw new PmCliError(`Linked-test selector is ambiguous; matching indexes: ${matches.map(index=>index+1).join(", ")}`,EXIT_CODE.USAGE,{code:"linked_test_update_ambiguous",required:"List linked tests and select one current --update-index."})}throw new PmCliError("No linked test matched the update selector",EXIT_CODE.NOT_FOUND,{code:"linked_test_update_no_match",required:"List linked tests and select a current command, path, or --update-index."})}function applyPatch(test,patch){if(typeof patch!="object"||patch===null||Array.isArray(patch))throw new PmCliError("Linked-test metadata patch must be a JSON object",EXIT_CODE.USAGE);const keys=Object.keys(patch);if(keys.length===0||keys.some(key=>!STRUCTURED_LINKED_TEST_KEYS.includes(key)||["command","cmd","timeout"].includes(key)))throw new PmCliError("Patch explicit linked-test metadata fields; command, aliases and provenance cannot be edited",EXIT_CODE.USAGE);if(patch.scope===null)throw new PmCliError("scope is required and cannot be cleared",EXIT_CODE.USAGE);const metadata=Object.fromEntries(Object.entries(test).filter(([key])=>STRUCTURED_LINKED_TEST_KEYS.includes(key))),parsed=normalizeLinkedTest(parseLinkedTestJsonEntries(JSON.stringify({...metadata,command:test.command??"legacy-path-only",...Object.fromEntries(Object.entries(patch).map(([key,value])=>[key,value===null?void 0:value]))}),"--set-json")[0]);assertLinkedTestContext(parsed);const fields=keys.filter(key=>!stableValueEquals(test[key],parsed[key])),next={...test};for(const key of fields){const value=parsed[key];Object.assign(next,{[key]:value}),value===void 0&&delete next[key]}if(!next.command?.trim()&&!next.path?.trim())throw new PmCliError("Linked-test entry must retain a command or path",EXIT_CODE.USAGE);return{test:next,fields}}async function updateLinkedTest(id,options,global2={}){const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot),author=resolveAuthor(options.author,settings.author_default),typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());let updatedIndex=0,updatedFields=[];const result=await mutateItemWithHistoryContextResolver({pmRoot,settings,id,author,op:"tests_update",message:options.message,force:options.force,skipNoop:!0,typeToFolder:typeRegistry.type_to_folder,resolveHistoryContext:()=>({linked_test_update:{index:updatedIndex,fields:updatedFields}}),mutate(document){const tests2=document.metadata.tests??[],index=selectIndex(tests2,options.selector),patch=applyPatch(tests2[index],options.patch);return updatedIndex=index+1,updatedFields=patch.fields,patch.fields.length===0?{changedFields:[]}:(document.metadata.tests=tests2.map((test,position)=>position===index?{...patch.test,updated_by:author,updated_at:nowIso()}:test),{changedFields:["tests"]})}}),tests=result.item.tests;return{ok:!0,id:result.item.id,tests,count:tests.length,changed:result.changedFields.length>0,updated_index:updatedIndex,updated_fields:updatedFields}}export{assertLinkedTestEditUsage,parseLinkedTestUpdateOptions,updateLinkedTest};
|
|
2
|
+
//# sourceMappingURL=update.js.map
|
package/dist/types.d.ts
CHANGED
|
@@ -195,6 +195,10 @@ export interface LinkedTest {
|
|
|
195
195
|
provenance?: LinkedTestProvenance;
|
|
196
196
|
/** Explicit fail-closed marker retained when stored provenance is malformed. */
|
|
197
197
|
provenance_invalid?: true;
|
|
198
|
+
/** Author of the most recent explicit metadata edit; creation provenance is retained. */
|
|
199
|
+
updated_by?: string;
|
|
200
|
+
/** ISO timestamp of the most recent explicit metadata edit. */
|
|
201
|
+
updated_at?: string;
|
|
198
202
|
/** Value that configures or reports env set for this contract. */
|
|
199
203
|
env_set?: Record<string, string>;
|
|
200
204
|
/** Value that configures or reports env clear for this contract. */
|
package/dist/types.js
CHANGED
|
@@ -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]="d293b107-03ce-51f2-8ade-8a9f0ec0b4db")}catch{}})();const BUILTIN_ITEM_TYPE_VALUES=["Epic","Feature","Task","Chore","Issue","Decision","Event","Reminder","Milestone","Meeting","Plan"],ITEM_TYPE_VALUES=BUILTIN_ITEM_TYPE_VALUES,STATUS_VALUES=["draft","open","in_progress","blocked","closed","canceled"],RUNTIME_STATUS_ROLE_VALUES=["draft","active","blocked","terminal","terminal_done","terminal_canceled","default_open","default_close","default_cancel"],RUNTIME_FIELD_TYPE_VALUES=["string","number","boolean","string_array","array","object"],RUNTIME_FIELD_COMMAND_VALUES=["create","update","update_many","list","search","calendar","context"],RUNTIME_UNKNOWN_FIELD_POLICY_VALUES=["allow","warn","reject"],DEPENDENCY_KIND_VALUES=["blocks","parent","child","parent_child","child_of","related","related_to","discovered_from","blocked_by","incident_from","epic","implements","recurs_from","supersedes","task","verifies"],SCOPE_VALUES=["project","global"],RISK_VALUES=["low","medium","high","critical"],ISSUE_SEVERITY_VALUES=["low","medium","high","critical"],CONFIDENCE_TEXT_VALUES=["low","medium","high"],ITEM_FORMAT_VALUES=["toon","json_markdown"],SPRINT_RELEASE_FORMAT_POLICY_VALUES=["warn","strict_error"],PARENT_REFERENCE_POLICY_VALUES=["warn","strict_error"],VALIDATE_METADATA_PROFILE_VALUES=["core","strict","custom"],GOVERNANCE_PRESET_VALUES=["minimal","default","strict","custom"],GOVERNANCE_OWNERSHIP_ENFORCEMENT_VALUES=["none","warn","strict"],GOVERNANCE_CREATE_MODE_DEFAULT_VALUES=["progressive","strict"],GOVERNANCE_CLOSE_VALIDATION_DEFAULT_VALUES=["off","warn","strict"],GOVERNANCE_WORKFLOW_ENFORCEMENT_VALUES=["off","warn","strict"],GOVERNANCE_DUPLICATE_DETECTION_MODE_VALUES=["off","advisory","strict"],VALIDATE_METADATA_REQUIRED_FIELD_VALUES=["author","acceptance_criteria","estimated_minutes","close_reason","reviewer","risk","confidence","sprint","release"],RECURRENCE_FREQUENCY_VALUES=["daily","weekly","monthly","yearly"],RECURRENCE_WEEKDAY_VALUES=["mon","tue","wed","thu","fri","sat","sun"];function weekdayOrderIndex(value){return RECURRENCE_WEEKDAY_VALUES.indexOf(value)}const PLAN_MODE_VALUES=["draft","research","review","approved","executing","paused","completed","superseded"],PLAN_STEP_STATUS_VALUES=["pending","in_progress","completed","blocked","skipped","superseded"],PLAN_HARNESS_VALUES=["codex","claude-code","cursor","generic"],PLAN_STEP_LINK_KIND_VALUES=["related","blocks","blocked_by","depends_on","discovered_from","implements","recurs_from","verifies","supersedes"],CONTEXT_DEPTH_VALUES=["brief","standard","deep","full"],CONTEXT_SECTION_VALUES=["hierarchy","activity","progress","recently_created","unparented","blockers","files","workload","staleness","tests"];export{BUILTIN_ITEM_TYPE_VALUES,CONFIDENCE_TEXT_VALUES,CONTEXT_DEPTH_VALUES,CONTEXT_SECTION_VALUES,DEPENDENCY_KIND_VALUES,GOVERNANCE_CLOSE_VALIDATION_DEFAULT_VALUES,GOVERNANCE_CREATE_MODE_DEFAULT_VALUES,GOVERNANCE_DUPLICATE_DETECTION_MODE_VALUES,GOVERNANCE_OWNERSHIP_ENFORCEMENT_VALUES,GOVERNANCE_PRESET_VALUES,GOVERNANCE_WORKFLOW_ENFORCEMENT_VALUES,ISSUE_SEVERITY_VALUES,ITEM_FORMAT_VALUES,ITEM_TYPE_VALUES,PARENT_REFERENCE_POLICY_VALUES,PLAN_HARNESS_VALUES,PLAN_MODE_VALUES,PLAN_STEP_LINK_KIND_VALUES,PLAN_STEP_STATUS_VALUES,RECURRENCE_FREQUENCY_VALUES,RECURRENCE_WEEKDAY_VALUES,RISK_VALUES,RUNTIME_FIELD_COMMAND_VALUES,RUNTIME_FIELD_TYPE_VALUES,RUNTIME_STATUS_ROLE_VALUES,RUNTIME_UNKNOWN_FIELD_POLICY_VALUES,SCOPE_VALUES,SPRINT_RELEASE_FORMAT_POLICY_VALUES,STATUS_VALUES,VALIDATE_METADATA_PROFILE_VALUES,VALIDATE_METADATA_REQUIRED_FIELD_VALUES,weekdayOrderIndex};
|
|
2
2
|
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Linked-test metadata edits and configuration refusals
|
|
2
|
+
|
|
3
|
+
Trackers: [pm-9djr6d](../.agents/pm/tasks/pm-9djr6d.toon),
|
|
4
|
+
[pm-gh1440](../.agents/pm/issues/pm-gh1440.toon).
|
|
5
|
+
|
|
6
|
+
Correct a linked test without removing and re-adding it:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pm test <item-id> --list
|
|
10
|
+
pm test <item-id> --update-index 1 --set-json '{"note":"Verified coverage gate","timeout_seconds":900}'
|
|
11
|
+
pm test <item-id> --update 'command=node scripts/check.mjs' --set-json '{"note":"Updated evidence"}'
|
|
12
|
+
pm test <item-id> --update 'path=tests/check.mjs' --set-json '{"note":null}'
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Each edit patches only explicit metadata fields. The entry keeps its position,
|
|
16
|
+
command and original `provenance`; changed entries gain `updated_by` and
|
|
17
|
+
`updated_at`. An unchanged normalized retry writes no item or history bytes.
|
|
18
|
+
One `tests_update` history event carries field-level patches plus the edited
|
|
19
|
+
index and metadata field names in `context.linked_test_update`.
|
|
20
|
+
|
|
21
|
+
Use `null` to clear an optional field, such as a note, path or timeout. Scope is
|
|
22
|
+
required and cannot be cleared. Every entry must retain a nonblank command or path:
|
|
23
|
+
replace a path-only entry's path rather than clearing its last identity.
|
|
24
|
+
Unknown fields, command changes, provenance
|
|
25
|
+
changes and editor-stamp overrides are refused. To change the command, remove
|
|
26
|
+
and add it through the ordinary provenance-recording workflow. Editing context
|
|
27
|
+
or environment controls changes the clone-local trust fingerprint, so any prior
|
|
28
|
+
acknowledgment must be reviewed again.
|
|
29
|
+
|
|
30
|
+
Exactly one selector must match the current collection under the item lock.
|
|
31
|
+
Absent selectors and ambiguous command/path matches refuse the whole edit and
|
|
32
|
+
retain authoritative bytes; ambiguity names matching indexes. An index addresses
|
|
33
|
+
the current list position. Durable metadata-fragment references remain tracked
|
|
34
|
+
separately by [pm-gh1381](../.agents/pm/features/pm-gh1381.toon).
|
|
35
|
+
Apply edits separately from listing, additions, removals, execution options,
|
|
36
|
+
measurements, metric filters and trust acknowledgment. Run-level `--timeout`
|
|
37
|
+
and `--progress` are refused on edits; change stored `timeout_seconds` in the
|
|
38
|
+
metadata patch when needed. `--list` remains a separate read-only operation.
|
|
39
|
+
|
|
40
|
+
The public SDK owns the same operation:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { updateLinkedTest } from "@unbrained/pm-cli/sdk/core";
|
|
44
|
+
|
|
45
|
+
const receipt = await updateLinkedTest(itemId, {
|
|
46
|
+
selector: { command: "node scripts/check.mjs" },
|
|
47
|
+
patch: { note: "Verified coverage gate", timeout_seconds: 900 },
|
|
48
|
+
}, { path: trackerRoot });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The aggregate SDK exports the same function. `PmClient.run("test", ...)` and the MCP `test`
|
|
52
|
+
action accept `update` or `updateIndex` with `setJson`, matching CLI flags. The
|
|
53
|
+
receipt exposes `updated_index`, `updated_fields`, and `changed`.
|
|
54
|
+
For extension-owned item types, fields or mutation hooks, wrap a direct primitive
|
|
55
|
+
with `runWithActiveExtensions({ cwd: projectRoot }, callback)` as described in
|
|
56
|
+
[SDK transaction composition](SDK.md#schema-evolution-and-workspace-history).
|
|
57
|
+
The `PmClient` action dispatcher owns this scope automatically.
|
|
58
|
+
|
|
59
|
+
Linked-test mutations through `test`, `create`, `update` and the SDK refuse
|
|
60
|
+
`pm_context_mode=none` unless the stored `workspace_context_mode` is `isolated`
|
|
61
|
+
or `snapshot`. For example:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pm test <item-id> --add-json '{"command":"node scripts/self-isolated-check.mjs","pm_context_mode":"none","workspace_context_mode":"isolated"}'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The refusal code is `linked_test_context_invalid` and includes a concrete recovery
|
|
68
|
+
example. Legacy invalid records remain readable. Running such a record returns
|
|
69
|
+
`status: refused`, `failure_category: config_refusal`, and `exit_code: null`;
|
|
70
|
+
the command never runs. The item, aggregate and background run remain unsuccessful.
|
|
71
|
+
Actual child-process failures retain their observed exit code and ordinary
|
|
72
|
+
execution failure category.
|
|
73
|
+
|
|
74
|
+
SDK consumers with exhaustive `TestRunResult.status` or failure-category switches
|
|
75
|
+
must handle `refused` and `config_refusal`. Treat a refusal as an unsuccessful
|
|
76
|
+
gate, and display its recovery message; `exit_code: null` means no subprocess ran.
|
|
77
|
+
Context mismatches and a missing required PM assertion also use this result.
|
|
78
|
+
The `TestRunResult.exit_code` type now allows null, and `TestCommandOptions` and
|
|
79
|
+
`TestResult` include the optional editor flags and receipt fields described above.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Full-history release reconciliation
|
|
2
|
+
|
|
3
|
+
Owner: [pm-q91qyd](../.agents/pm/issues/pm-q91qyd.toon).
|
|
4
|
+
Upstream trigger evidence: [pm-prrlce](../.agents/pm/issues/pm-prrlce.toon).
|
|
5
|
+
|
|
6
|
+
The Release Reliability workflow compares every dated section in the
|
|
7
|
+
package-generated changelog, every release tag advertised by `origin`, and
|
|
8
|
+
every version in anonymous public npm metadata. It runs on the existing daily
|
|
9
|
+
schedule and completion triggers, even when a rolling reliability report fails.
|
|
10
|
+
Its separate `release-ledgers-<run>-<attempt>` artifact contains the complete
|
|
11
|
+
input inventories, counts, findings and exception dispositions for offline replay.
|
|
12
|
+
|
|
13
|
+
Missing public registry versions are declared-but-undelivered releases. Missing
|
|
14
|
+
changelog sections are delivered-but-undocumented releases. A tag missing its
|
|
15
|
+
section is tagged-but-unsectioned; an identity can belong to several classes.
|
|
16
|
+
Every missing ledger appears explicitly in the report, without counting one
|
|
17
|
+
identity several times or dropping overlapping classes.
|
|
18
|
+
The `classes` object names these three populations separately; `findings`
|
|
19
|
+
retains one row per discrepant identity.
|
|
20
|
+
|
|
21
|
+
The first complete census on 2026-10-10 found 14 discrepant identities among
|
|
22
|
+
143 sections, 151 tags and 143 public versions. The exact historical signatures
|
|
23
|
+
and their individual dispositions are recorded in
|
|
24
|
+
[the reviewed exception policy](../config/release-ledger-exceptions.json).
|
|
25
|
+
Unpublished historical preparations are retained as abandoned publications;
|
|
26
|
+
historical documentation gaps remain visible without inventing shipped content.
|
|
27
|
+
These are explicit exceptions, not claims that the three historical sets agree.
|
|
28
|
+
No tag is deleted and no old artifact is published by this reporting path.
|
|
29
|
+
|
|
30
|
+
An exception matches one identity and one exact missing-ledger signature.
|
|
31
|
+
Additional missing evidence invalidates it. Correcting a historical gap makes
|
|
32
|
+
its exception stale and requires removing or revising that policy entry in a
|
|
33
|
+
reviewed change. A new discrepancy or stale exception fails the report.
|
|
34
|
+
Empty total inventories, incomplete populations, duplicate identities, malformed
|
|
35
|
+
remote output, registry failures and missing exception evidence refuse evaluation.
|
|
36
|
+
|
|
37
|
+
The registry request uses the same public npm metadata surface as release
|
|
38
|
+
acceptance, with explicit public registry selection, empty user/global
|
|
39
|
+
configuration and a fresh temporary cache. It runs outside the checkout and
|
|
40
|
+
removes inherited npm authentication/configuration. The report never archives
|
|
41
|
+
credentials, command output or environment values.
|
|
42
|
+
On Windows the collector invokes `cmd.exe` explicitly for npm's `.cmd` launcher.
|
|
43
|
+
The package name must satisfy the restricted registry identity grammar before
|
|
44
|
+
any child starts; the remaining arguments are fixed. Required Windows acceptance
|
|
45
|
+
executes real Git and public npm requests from paths containing spaces and `&`,
|
|
46
|
+
first proves that direct `npm.cmd` execution fails, then verifies the complete
|
|
47
|
+
inventory and temporary-directory cleanup through the repaired launcher.
|
|
48
|
+
No `shell: true` argument-array fallback or resource ceiling increase is used.
|
|
49
|
+
The parser supports npm 11's object and npm 12's single-result array, with
|
|
50
|
+
[captured public npm 12 metadata](../tests/fixtures/release-ledgers/npm-view-12.json)
|
|
51
|
+
as its format regression. Multiple package results refuse evaluation.
|
|
52
|
+
|
|
53
|
+
To run the actual collector after building:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
RELEASE_LEDGERS_OUTPUT=/absolute/report.json node --input-type=module -e '
|
|
57
|
+
import { main } from "./scripts/release/collect-release-ledgers.mjs";
|
|
58
|
+
const report = main();
|
|
59
|
+
console.log(JSON.stringify({ok:report.ok,counts:report.counts,findings:report.findings}));
|
|
60
|
+
process.exitCode = report.ok ? 0 : 1;
|
|
61
|
+
'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Packages and non-release projects can use the same pure SDK primitive with
|
|
65
|
+
their own named artifact inventories and decision references:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { reconcileArtifactLedgers } from "@unbrained/pm-cli/sdk/governance";
|
|
69
|
+
|
|
70
|
+
const report = reconcileArtifactLedgers([
|
|
71
|
+
{ name: "declared", complete: true, identities: ["artifact-1"] },
|
|
72
|
+
{ name: "delivered", complete: true, identities: ["artifact-1"] },
|
|
73
|
+
]);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`ArtifactLedgerSnapshot`, `ArtifactLedgerException`, `ArtifactLedgerFinding`
|
|
77
|
+
and `ArtifactLedgerReport` describe this harness-independent contract.
|
|
78
|
+
The evaluator performs no filesystem, clock or network operations and preserves
|
|
79
|
+
caller inputs. For offline replay, feed the saved `snapshots` and `exceptions`
|
|
80
|
+
back into `reconcileArtifactLedgers`.
|
|
81
|
+
|
|
82
|
+
## Tag-carried trigger declarations
|
|
83
|
+
|
|
84
|
+
New preparations create annotated tags whose bounded JSON message binds the
|
|
85
|
+
declared upstream event/origin, repository, run/attempt, reviewed source commit
|
|
86
|
+
and prepared target commit. Before publication, the Release workflow checks
|
|
87
|
+
the tag's peeled commit and source ancestry and compares the source declaration
|
|
88
|
+
with the exact GitHub run attempt, including repository, event, source SHA,
|
|
89
|
+
the producer workflow path and declared Auto Release run name. It independently
|
|
90
|
+
fetches the repository's default branch and requires the source run's branch to
|
|
91
|
+
match it. Auto Release uploads an immutable producer binding before pushing;
|
|
92
|
+
publication independently downloads that run attempt's artifact and compares
|
|
93
|
+
the exact tag name, target commit, tag object and canonical declaration. Missing,
|
|
94
|
+
expired, ambiguous or mismatched evidence stops publication; the artifact is
|
|
95
|
+
retained for 90 days. The verifier never assumes the default branch is named
|
|
96
|
+
`main`.
|
|
97
|
+
|
|
98
|
+
The separate `release-publication-origin-<run>-<attempt>` artifact retains the
|
|
99
|
+
tag-object SHA, upstream declaration, independent verification result and the
|
|
100
|
+
current publication/recovery trigger. An operator recovering a dispatcher
|
|
101
|
+
release therefore retains both origins. A rejected atomic push after sealing
|
|
102
|
+
refuses to rebase into a different target; a new preparation must establish a
|
|
103
|
+
new independent binding. Local preparation remains supported without pushing;
|
|
104
|
+
local `--push` refuses before Git inspection or release-asset mutation.
|
|
105
|
+
|
|
106
|
+
Historical lightweight tags and unrelated legacy annotations stay explicitly
|
|
107
|
+
unattributed only when publication matches the repository, tag name and exact
|
|
108
|
+
content-addressed object in the
|
|
109
|
+
[frozen pre-rollout inventory](../config/release-tag-legacy.json). That reviewed
|
|
110
|
+
inventory identifies all 152 origin tag objects observed before this rollout;
|
|
111
|
+
it is not extended automatically. Unknown lightweight tags, unrelated new
|
|
112
|
+
annotations and rewritten historical objects stop before publication, including
|
|
113
|
+
operator recovery. A missing or unreadable inventory fails closed. No origin is
|
|
114
|
+
inferred from a tag-push event or actor. Local preparation records an operator
|
|
115
|
+
declaration but hosted publication refuses it without a hosted producer.
|
|
116
|
+
Tag objects are content-addressed evidence; this does not assert that GitHub
|
|
117
|
+
release/tag immutability policy has been enabled.
|
|
118
|
+
|
|
119
|
+
The downstream tag-push workflow's run name still names `tag_push`; its verified
|
|
120
|
+
upstream origin lives in the summary and artifact. The remaining run-name and
|
|
121
|
+
operator-only manual follow-up contracts retain their existing owners
|
|
122
|
+
[pm-prrlce](../.agents/pm/issues/pm-prrlce.toon) and
|
|
123
|
+
[pm-uenmu9](../.agents/pm/issues/pm-uenmu9.toon). The one-automatic-release-per-UTC-day
|
|
124
|
+
guard and exact-tag recovery semantics are unchanged.
|
|
125
|
+
|
|
126
|
+
## Installed acceptance path cost
|
|
127
|
+
|
|
128
|
+
Owner: [pm-release-acceptance-path-cost](../.agents/pm/issues/pm-release-acceptance-path-cost.toon).
|
|
129
|
+
|
|
130
|
+
The disposable installed-consumer layout uses concise directory names because
|
|
131
|
+
`init` repeats its workspace path throughout its complete JSON guidance. Long
|
|
132
|
+
macOS temporary ancestry previously made an otherwise valid public artifact
|
|
133
|
+
exceed the raw 12,000-character init ceiling. Shorter private paths retain every
|
|
134
|
+
output field, lifecycle assertion, deadline and ceiling. The
|
|
135
|
+
[captured public output regression](../tests/fixtures/release-acceptance/README.md)
|
|
136
|
+
checks the raw cost for independent control/candidate local npm, global npm and
|
|
137
|
+
Bun layouts; actual installed sessions remain separate acceptance evidence.
|
|
138
|
+
|
|
139
|
+
## Publication metadata weight
|
|
140
|
+
|
|
141
|
+
Owner: [pm-998juj](../.agents/pm/tasks/pm-998juj.toon).
|
|
142
|
+
|
|
143
|
+
The publication stage compacts first-party JSON while leaving checkout files
|
|
144
|
+
readable and third-party runtime files unchanged. Every parsed value must survive
|
|
145
|
+
serialization exactly; invalid JSON and lossy representations, including negative
|
|
146
|
+
zero or overflowing numbers, stop packing. Real tarball regressions verify nested
|
|
147
|
+
extension data, Unicode, escaped text and the runtime ledger. Both committed size
|
|
148
|
+
profiles, required files and source-map exclusions remain enforced.
|
|
@@ -34,6 +34,10 @@ by release preparation, not the inferred cron occurrence. A delayed run cannot
|
|
|
34
34
|
backdate a tag. Reporting never creates, retargets, retries, or publishes a tag.
|
|
35
35
|
The unchanged [release recovery rules](RELEASING.md#failure-handling) apply.
|
|
36
36
|
|
|
37
|
+
The independent [full-history ledger report](RELEASE_LEDGER_RECONCILIATION.md)
|
|
38
|
+
also reconciles public registry versions, release tags and generated sections.
|
|
39
|
+
It preserves every historical exception and fails on new or changed drift.
|
|
40
|
+
|
|
37
41
|
## Evidence and denominator
|
|
38
42
|
|
|
39
43
|
The collector paginates Auto Release runs over an explicit half-open UTC window
|
package/docs/RELEASING.md
CHANGED
|
@@ -148,8 +148,13 @@ configuration belong in private operator documentation.
|
|
|
148
148
|
- protected-branch pushes require `RELEASE_PAT`; Auto Release fails fast before the expensive release gates when `push=true`, `dry_run=false`, and that secret is not configured
|
|
149
149
|
- release reliability gating requires `SENTRY_PERSONAL_ADMIN_TOKEN` for issue-threshold checks; Auto Release fails before creating the version commit/tag when the token is missing and `push=true`, while sourcemap upload remains optional through `SENTRY_AUTH_TOKEN`
|
|
150
150
|
- after creating and pushing a new tag, auto-release waits for the tag-push `.github/workflows/release.yml` run to finish instead of dispatching a second publish workflow
|
|
151
|
-
- scheduled
|
|
152
|
-
|
|
151
|
+
- native scheduled and declared morning-dispatcher failures open or update the
|
|
152
|
+
same daily blocker with trigger origin, preflight state (`push`, `dry_run`,
|
|
153
|
+
`release_pat_configured`, and `sentry_personal_admin_token_configured`) and
|
|
154
|
+
detected cause. Successful automatic recovery closes it only after exact
|
|
155
|
+
publication verification; operator dispatch does not manage this lifecycle.
|
|
156
|
+
This behavior is tracked by [pm-automatic-release-alerts](../.agents/pm/tasks/pm-automatic-release-alerts.toon).
|
|
157
|
+
- when either automatic origin fails across multiple UTC days, auto-release supersedes a stale open blocker with a fresh current-day blocker so same-day retry detection follows the latest automatic failure
|
|
153
158
|
- closing the exact bot-created `Auto Release blocked: scheduled run failed`
|
|
154
159
|
issue as a maintainer or agent records a same-day retry marker, then either
|
|
155
160
|
retries preparation when no tag exists or watches an active exact-tag Release
|
|
@@ -172,6 +177,17 @@ Pipeline entrypoint:
|
|
|
172
177
|
node scripts/release/run-release-pipeline.mjs
|
|
173
178
|
```
|
|
174
179
|
|
|
180
|
+
Tracked by [pm-prrlce](../.agents/pm/issues/pm-prrlce.toon): hosted preparation
|
|
181
|
+
uses `--push --defer-push` to write an exact producer binding. Auto Release uploads
|
|
182
|
+
`release-producer-binding-<attempt>` before verifying and atomically pushing its
|
|
183
|
+
prepared refs. Publication independently fetches the verified run's artifact and
|
|
184
|
+
compares the tag name, target commit, tag object and declaration. Missing, expired,
|
|
185
|
+
ambiguous or mismatched evidence fails closed; artifact retention is 90 days.
|
|
186
|
+
A branch advance after sealing refuses publication rather than rebasing into a
|
|
187
|
+
different target. Local `--push` refuses before Git inspection or asset mutation;
|
|
188
|
+
local preparation without pushing remains supported. Historical admission remains
|
|
189
|
+
limited to the reviewed exact-object inventory.
|
|
190
|
+
|
|
175
191
|
The pipeline performs:
|
|
176
192
|
|
|
177
193
|
1. change detection + one-release-per-day guard
|
|
@@ -421,14 +437,28 @@ maintainer supplies
|
|
|
421
437
|
pair that acknowledgement with migration guidance, compatible extension
|
|
422
438
|
version bounds where applicable, and the next eligible date-based release.
|
|
423
439
|
|
|
424
|
-
5.
|
|
440
|
+
5. Land the implementation through a reviewed pull request, then use hosted
|
|
441
|
+
preparation for publication.
|
|
442
|
+
|
|
443
|
+
Local preparation without `--push` is a diagnostic preview. Its local producer
|
|
444
|
+
declaration cannot authorize publication. Once the reviewed implementation is on
|
|
445
|
+
`main`, dispatch the existing Auto Release workflow from that default branch:
|
|
425
446
|
|
|
426
447
|
```bash
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
git push origin v<version>
|
|
448
|
+
gh workflow run auto-release.yml --ref main \
|
|
449
|
+
-f push=true -f dry_run=false -f telemetry_mode=off -f trigger_origin=operator
|
|
430
450
|
```
|
|
431
451
|
|
|
452
|
+
Hosted preparation runs the mandatory gates, creates the version commit and
|
|
453
|
+
annotated tag, and seals their exact producer binding in an immutable artifact
|
|
454
|
+
before verifying and atomically pushing either ref. It waits for the single
|
|
455
|
+
tag-driven Release workflow to publish and accept that exact package. Do not push
|
|
456
|
+
locally prepared tags or invoke `npm publish` separately.
|
|
457
|
+
|
|
458
|
+
If today's immutable tag already exists, use the exact-tag recovery procedure
|
|
459
|
+
below. A local diagnostic tag does not prove hosted preparation or publication;
|
|
460
|
+
never move a published tag or mint a second automatic version for the same UTC day.
|
|
461
|
+
|
|
432
462
|
## GitHub Workflow
|
|
433
463
|
|
|
434
464
|
`.github/workflows/release.yml` runs on `v*.*.*` tags and handles:
|
|
@@ -454,7 +484,11 @@ git push origin v<version>
|
|
|
454
484
|
- a base npm pack dry run, optional Sentry debug-ID injection, a second
|
|
455
485
|
`sentry-injected` packlist budget over the exact publishable bytes, and only
|
|
456
486
|
then optional Sentry release metadata/upload/finalization and the npx tarball
|
|
457
|
-
smoke test
|
|
487
|
+
smoke test. Sentry release metadata and sourcemaps are uploaded only from
|
|
488
|
+
tag sources. Recovery of an already-published version from reviewed `main`
|
|
489
|
+
preserves that version's existing Sentry commits and sourcemaps; local debug-ID
|
|
490
|
+
injection still validates the candidate artifact budget without changing the
|
|
491
|
+
published release's symbolication data.
|
|
458
492
|
- generated release notes from changelog plus sanitized tracker metadata. The
|
|
459
493
|
tracker read projects only release-relevant fields and explicitly removes row
|
|
460
494
|
and token limits. The generator validates the completeness receipt before
|
|
@@ -563,12 +597,18 @@ Use the npm registry package for maintainer global updates. Do not use `npm inst
|
|
|
563
597
|
ordinal recovery version. Rerun `.github/workflows/release.yml` with
|
|
564
598
|
`workflow_dispatch` and `tag=v<version>` (or close the current bot-created
|
|
565
599
|
blocker once to trigger the guarded exact-run recovery). The workflow skips
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
600
|
+
npm publication for a version visible to its isolated anonymous probe, keeping
|
|
601
|
+
reviewed dispatch-time `main`. A definitive missing-version response can pin
|
|
602
|
+
source to the immutable tag only after admission reads complete workflow and
|
|
603
|
+
job inventories, validates totals and unique identities, and checks matching
|
|
604
|
+
attempts. Prior successful `Publish to npm` evidence refuses
|
|
605
|
+
publication while metadata is unavailable: acceptance can precede visibility.
|
|
606
|
+
Unavailable, malformed, incomplete or inconsistent evidence also refuses it.
|
|
607
|
+
Only the executing attempt is excluded; its earlier attempts remain checked.
|
|
608
|
+
This admission check also runs before first publication, using reviewed
|
|
609
|
+
controls retained outside recovery checkout. Push and dispatch publishers
|
|
610
|
+
share exact-tag concurrency. See [pm-publication-acceptance-fence](../.agents/pm/issues/pm-publication-acceptance-fence.toon).
|
|
611
|
+
A never-published tag then reapplies the version guard, installs the managed
|
|
572
612
|
changelog extension, regenerates the package changelog with the tagged
|
|
573
613
|
checkout's canonical policy under a tracked-path mutation guard, and permits
|
|
574
614
|
first publication only from that tagged source. Ordinary tag-push releases
|