@unbrained/pm-cli 2026.10.15 → 2026.10.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +45 -0
- package/dist/cli/extension-command-options.d.ts +3 -1
- package/dist/cli/extension-command-options.js +1 -1
- package/dist/cli/help-content.js +2 -2
- package/dist/cli/register-list-query.js +2 -2
- package/dist/cli/register-mutation.js +2 -2
- package/dist/cli/register-operations.js +1 -1
- package/dist/cli/register-structured-mutation.d.ts +0 -5
- package/dist/cli/register-structured-mutation.js +1 -1
- package/dist/cli/runtime/invocation-options.js +1 -1
- package/dist/cli-bundle/bundle-manifest.json +1 -1
- package/dist/cli-bundle/chunks/{chunk-7VHINXZP.js → chunk-4GA4MUTE.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-RJ5N44WY.js → chunk-4V6ONLI6.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-LNKLQYBG.js → chunk-6VZKYJW7.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-7PATQWTH.js +20 -0
- package/dist/cli-bundle/chunks/chunk-7WIEAGDS.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-52EZH2QQ.js → chunk-AETP4JEM.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-WBBW3WQX.js → chunk-FIJOSX2C.js} +28 -28
- package/dist/cli-bundle/chunks/chunk-LUKVNL72.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-NC3QVGDD.js → chunk-OJ77ZQN3.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-PYRREEUB.js +30 -0
- package/dist/cli-bundle/chunks/chunk-RHQJ6VWC.js +237 -0
- package/dist/cli-bundle/chunks/{chunk-N56CAQBU.js → chunk-RNABUEFB.js} +52 -52
- package/dist/cli-bundle/chunks/chunk-TO6CIV4C.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-JGKTOBVB.js → chunk-ZZED447K.js} +4 -4
- package/dist/cli-bundle/chunks/{register-list-query-FKKFQ66D.js → register-list-query-PUCVYYBD.js} +7 -7
- package/dist/cli-bundle/chunks/register-mutation-GGGVBXD5.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-GEQ2H7PS.js → register-operations-NRZ6Q4QE.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-PSJTQBBO.js → register-setup-MV3P3YSF.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-2MPQUMTF.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-H3P77KVU.js → chunk-5UKCSZWT.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-4KQFMOM7.js → chunk-A4ZHHTEX.js} +5 -5
- package/dist/cli-bundle/focused-chunks/{chunk-5OO54BIV.js → chunk-B4YLP5ZB.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-BFEMT5U3.js +20 -0
- package/dist/cli-bundle/focused-chunks/{chunk-THYQR3ON.js → chunk-FW7CSSKL.js} +61 -61
- package/dist/cli-bundle/focused-chunks/{chunk-3RNUMVK4.js → chunk-HYPRPSYD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-FQKPOZKS.js → chunk-IRVL4UXR.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-Q4VNCTR2.js → chunk-L55KQ2KT.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-52I2SNKJ.js → chunk-MASIOFPG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-RJ3EIHDU.js +26 -0
- package/dist/cli-bundle/focused-chunks/chunk-SEL4Z2OO.js +167 -0
- package/dist/cli-bundle/focused-chunks/{chunk-TYLG5VEB.js → chunk-TB7F4FCR.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-KIIFVULU.js → chunk-TZUIBG3P.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-N6FUKTZS.js → chunk-Z7YIFCNE.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-5KRACGBK.js → chunk-ZDBS2DCT.js} +3 -3
- package/dist/cli-bundle/main.js +27 -27
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +23 -23
- 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 +55 -54
- 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 +7 -7
- package/dist/core/extensions/extension-types.d.ts +15 -0
- package/dist/core/extensions/extension-types.js +1 -1
- package/dist/core/extensions/flag-value-types.d.ts +16 -0
- package/dist/core/extensions/flag-value-types.js +1 -1
- package/dist/core/extensions/registration-contracts.js +1 -1
- package/dist/core/history/event-index.d.ts +8 -1
- package/dist/core/history/event-index.js +19 -18
- package/dist/core/item/item-format.js +3 -3
- package/dist/core/lock/lock.d.ts +8 -1
- package/dist/core/lock/lock.js +3 -3
- package/dist/core/output/mutation-projection.d.ts +0 -21
- package/dist/core/output/mutation-projection.js +1 -1
- package/dist/core/output/output.js +2 -2
- package/dist/core/schema/type-workflows.d.ts +1 -1
- package/dist/core/schema/type-workflows.js +1 -1
- package/dist/core/shared/text-normalization.d.ts +2 -0
- package/dist/core/shared/text-normalization.js +1 -1
- package/dist/core/store/item-mutation-precondition.d.ts +11 -0
- package/dist/core/store/item-mutation-precondition.js +2 -0
- package/dist/core/store/item-store.js +1 -1
- package/dist/core/store/paths.js +1 -1
- package/dist/core/telemetry/policy.d.ts +2 -0
- package/dist/core/telemetry/policy.js +1 -1
- package/dist/core/telemetry/runtime.d.ts +5 -3
- package/dist/core/telemetry/runtime.js +3 -3
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/tool-definitions.js +1 -1
- package/dist/sdk/cli-contracts/agent-output-contracts.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/registration-helpers.d.ts +1 -1
- package/dist/sdk/cli-contracts/registration-helpers.js +1 -1
- package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1
- package/dist/sdk/context-intent-contracts.js +1 -1
- package/dist/sdk/core.d.ts +2 -1
- 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/health/projection.d.ts +37 -0
- package/dist/sdk/governance/health/projection.js +2 -0
- package/dist/sdk/governance/health.d.ts +7 -18
- package/dist/sdk/governance/health.js +2 -2
- package/dist/sdk/guide-topics.js +1 -1
- package/dist/sdk/index.d.ts +2 -1
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/item-transaction.d.ts +72 -9
- package/dist/sdk/item-transaction.js +1 -1
- package/dist/sdk/lifecycle/claim.d.ts +15 -1
- package/dist/sdk/lifecycle/claim.js +1 -1
- package/dist/sdk/lifecycle/close.d.ts +2 -8
- package/dist/sdk/lifecycle/close.js +1 -1
- package/dist/sdk/lifecycle/core-item-fields.d.ts +6 -0
- package/dist/sdk/lifecycle/core-item-fields.js +2 -0
- package/dist/sdk/lifecycle/mcp-actions.js +1 -1
- package/dist/sdk/lifecycle/mutation-option-validation.d.ts +2 -0
- package/dist/sdk/lifecycle/mutation-option-validation.js +2 -0
- package/dist/sdk/lifecycle/release-handoff.d.ts +12 -0
- package/dist/sdk/lifecycle/release-handoff.js +2 -0
- package/dist/sdk/lifecycle/structured-mutation-plan.d.ts +33 -0
- package/dist/sdk/lifecycle/structured-mutation-plan.js +2 -0
- package/dist/sdk/lifecycle/task-composition.d.ts +2 -2
- package/dist/sdk/lifecycle/task-composition.js +1 -1
- package/dist/sdk/lifecycle/update.d.ts +3 -11
- package/dist/sdk/lifecycle/update.js +1 -1
- package/dist/sdk/lifecycle/workflow-transition.d.ts +13 -0
- package/dist/sdk/lifecycle/workflow-transition.js +2 -0
- package/dist/sdk/lifecycle-policy.d.ts +12 -2
- package/dist/sdk/lifecycle-policy.js +1 -1
- package/dist/sdk/mutation-events.js +1 -1
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query/list.d.ts +2 -0
- package/dist/sdk/query/list.js +1 -1
- package/dist/sdk/read-output-budget.js +1 -1
- package/dist/sdk/runtime-input.js +1 -1
- package/dist/sdk/runtime-primitives.d.ts +1 -1
- package/dist/sdk/runtime-primitives.js +1 -1
- package/dist/sdk/runtime.d.ts +8 -8
- package/dist/sdk/runtime.js +1 -1
- package/dist/sdk/structured-mutations.d.ts +52 -1
- package/dist/sdk/structured-mutations.js +1 -1
- package/dist/sdk/workspace-transaction.js +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/docs/AGENT_GUIDE.md +33 -4
- package/docs/CLOSE_EVIDENCE_RECOVERY.md +16 -7
- package/docs/COMMANDS.md +111 -10
- package/docs/CONFIGURATION.md +22 -1
- package/docs/DEVELOPMENT_DEPENDENCY_SECURITY.md +22 -3
- package/docs/ECOSYSTEM_PLANNING_REVIEW.md +5 -1
- package/docs/EXTENSIONS.md +1 -1
- package/docs/OUTPUT_PROJECTION_CONTRACTS.md +10 -0
- package/docs/RELEASING.md +8 -1
- package/docs/SDK.md +114 -2
- package/docs/SDK_CONTEXT_COORDINATION.md +71 -7
- package/docs/SDK_STORAGE_LIFECYCLE.md +24 -2
- package/docs/TESTING.md +23 -0
- package/docs/examples/ci/github-actions-pm-extension-gate.yml +1 -1
- package/docs/examples/ci/gitlab-ci-pm-extension-gate.yml +1 -1
- package/docs/examples/ci/jenkins-pm-extension-gate.Jenkinsfile +1 -1
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +1 -1
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +16 -3
- package/marketplace.json +1 -1
- package/node_modules/@opentelemetry/core/package.json +2 -1
- package/node_modules/@opentelemetry/instrumentation/package.json +2 -1
- package/node_modules/@opentelemetry/resources/package.json +2 -1
- package/node_modules/@opentelemetry/sdk-trace/package.json +2 -1
- package/node_modules/@opentelemetry/sdk-trace-base/package.json +2 -1
- package/node_modules/@sentry/core/build/cjs/client.js +5 -4
- package/node_modules/@sentry/core/build/cjs/tracing/ai/gen-ai-attributes.js +0 -4
- package/node_modules/@sentry/core/build/cjs/tracing/ai/utils.js +33 -23
- package/node_modules/@sentry/core/build/cjs/tracing/anthropic-ai/index.js +7 -6
- package/node_modules/@sentry/core/build/cjs/tracing/anthropic-ai/streaming.js +3 -1
- package/node_modules/@sentry/core/build/cjs/tracing/google-genai/index.js +13 -14
- package/node_modules/@sentry/core/build/cjs/tracing/google-genai/streaming.js +6 -1
- package/node_modules/@sentry/core/build/cjs/tracing/langchain/utils.js +71 -21
- package/node_modules/@sentry/core/build/cjs/tracing/langgraph/utils.js +23 -33
- package/node_modules/@sentry/core/build/cjs/tracing/openai/streaming.js +6 -0
- package/node_modules/@sentry/core/build/cjs/tracing/openai/utils.js +11 -0
- package/node_modules/@sentry/core/build/cjs/tracing/workers-ai/utils.js +1 -1
- package/node_modules/@sentry/core/build/cjs/utils/eventUtils.js +4 -0
- package/node_modules/@sentry/core/build/cjs/utils/prepareEvent.js +2 -2
- package/node_modules/@sentry/core/build/cjs/utils/version.js +1 -1
- package/node_modules/@sentry/core/build/esm/client.js +6 -5
- package/node_modules/@sentry/core/build/esm/package.json +1 -1
- package/node_modules/@sentry/core/build/esm/tracing/ai/gen-ai-attributes.js +1 -3
- package/node_modules/@sentry/core/build/esm/tracing/ai/utils.js +34 -24
- package/node_modules/@sentry/core/build/esm/tracing/anthropic-ai/index.js +8 -7
- package/node_modules/@sentry/core/build/esm/tracing/anthropic-ai/streaming.js +3 -1
- package/node_modules/@sentry/core/build/esm/tracing/google-genai/index.js +15 -16
- package/node_modules/@sentry/core/build/esm/tracing/google-genai/streaming.js +6 -1
- package/node_modules/@sentry/core/build/esm/tracing/langchain/utils.js +73 -24
- package/node_modules/@sentry/core/build/esm/tracing/langgraph/utils.js +24 -34
- package/node_modules/@sentry/core/build/esm/tracing/openai/streaming.js +6 -0
- package/node_modules/@sentry/core/build/esm/tracing/openai/utils.js +11 -0
- package/node_modules/@sentry/core/build/esm/tracing/workers-ai/utils.js +2 -2
- package/node_modules/@sentry/core/build/esm/utils/eventUtils.js +4 -1
- package/node_modules/@sentry/core/build/esm/utils/prepareEvent.js +2 -2
- package/node_modules/@sentry/core/build/esm/utils/version.js +1 -1
- package/node_modules/@sentry/core/build/types/tracing/ai/utils.d.ts +3 -7
- package/node_modules/@sentry/core/build/types/tracing/anthropic-ai/types.d.ts +2 -2
- package/node_modules/@sentry/core/build/types/tracing/langchain/types.d.ts +15 -0
- package/node_modules/@sentry/core/build/types/tracing/langchain/utils.d.ts +1 -0
- package/node_modules/@sentry/core/build/types/tracing/langgraph/utils.d.ts +2 -0
- package/node_modules/@sentry/core/build/types/tracing/openai/types.d.ts +2 -0
- package/node_modules/@sentry/core/build/types/utils/eventUtils.d.ts +2 -1
- package/node_modules/@sentry/core/build/types-ts3.8/tracing/ai/utils.d.ts +3 -7
- package/node_modules/@sentry/core/build/types-ts3.8/tracing/anthropic-ai/types.d.ts +2 -2
- package/node_modules/@sentry/core/build/types-ts3.8/tracing/langchain/types.d.ts +15 -0
- package/node_modules/@sentry/core/build/types-ts3.8/tracing/langchain/utils.d.ts +1 -0
- package/node_modules/@sentry/core/build/types-ts3.8/tracing/langgraph/utils.d.ts +2 -0
- package/node_modules/@sentry/core/build/types-ts3.8/tracing/openai/types.d.ts +2 -0
- package/node_modules/@sentry/core/build/types-ts3.8/utils/eventUtils.d.ts +2 -1
- package/node_modules/@sentry/core/package.json +1 -1
- package/node_modules/@sentry/node/build/esm/package.json +1 -1
- package/node_modules/@sentry/node/package.json +5 -5
- package/node_modules/@sentry/node-core/build/cjs/integrations/anr/index.js +1 -1
- package/node_modules/@sentry/node-core/build/cjs/integrations/local-variables/local-variables-async.js +1 -1
- package/node_modules/@sentry/node-core/build/esm/integrations/anr/index.js +1 -1
- package/node_modules/@sentry/node-core/build/esm/integrations/anr/worker-script.js +2 -2
- package/node_modules/@sentry/node-core/build/esm/integrations/local-variables/local-variables-async.js +1 -1
- package/node_modules/@sentry/node-core/build/esm/integrations/local-variables/worker-script.js +1 -1
- package/node_modules/@sentry/node-core/build/esm/package.json +1 -1
- package/node_modules/@sentry/node-core/package.json +10 -4
- package/node_modules/@sentry/opentelemetry/build/esm/package.json +1 -1
- package/node_modules/@sentry/opentelemetry/package.json +5 -2
- package/node_modules/@sentry/server-utils/build/THIRD-PARTY-LICENSES.txt +55 -55
- package/node_modules/@sentry/server-utils/build/esm/package.json +1 -1
- package/node_modules/@sentry/server-utils/package.json +2 -2
- package/node_modules/@toon-format/toon/README.md +10 -41
- package/node_modules/@toon-format/toon/dist/index.d.mts +12 -36
- package/node_modules/@toon-format/toon/dist/index.mjs +134 -202
- package/node_modules/@toon-format/toon/package.json +2 -2
- package/node_modules/debug/package.json +3 -0
- package/node_modules/fdir/package.json +3 -0
- package/node_modules/has-flag/index.d.ts +39 -0
- package/node_modules/has-flag/index.js +8 -0
- package/node_modules/has-flag/license +9 -0
- package/node_modules/has-flag/package.json +46 -0
- package/node_modules/has-flag/readme.md +89 -0
- package/node_modules/supports-color/browser.js +5 -0
- package/node_modules/supports-color/index.js +135 -0
- package/node_modules/supports-color/license +9 -0
- package/node_modules/supports-color/package.json +53 -0
- package/node_modules/supports-color/readme.md +76 -0
- package/package.json +5 -4
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/package.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/pm-codex/package.json +1 -1
- package/plugins/pm-codex/plugin.json +1 -1
- package/runtime-dependencies.json +1 -1
- package/dist/cli-bundle/chunks/chunk-7OEGNA4X.js +0 -20
- package/dist/cli-bundle/chunks/chunk-EMEEHV2Y.js +0 -2
- package/dist/cli-bundle/chunks/chunk-JSUJWIHQ.js +0 -30
- package/dist/cli-bundle/chunks/chunk-VIMQCFCK.js +0 -2
- package/dist/cli-bundle/chunks/chunk-X2H6UR26.js +0 -236
- package/dist/cli-bundle/chunks/register-mutation-EWMMVZJB.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-5TBAVZDR.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-HTA3TNC3.js +0 -26
- package/dist/cli-bundle/focused-chunks/chunk-JKBH7YGX.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-PDYE7QDX.js +0 -166
- package/docs/ecosystem-review-2026-09-28.json +0 -1
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# Recovering missing close evidence
|
|
2
2
|
|
|
3
|
-
Tracked by [pm-ub1ott](../.agents/pm/issues/pm-ub1ott.toon)
|
|
3
|
+
Tracked by [pm-ub1ott](../.agents/pm/issues/pm-ub1ott.toon) and
|
|
4
|
+
[pm-gh1464](../.agents/pm/issues/pm-gh1464.toon).
|
|
4
5
|
|
|
5
6
|
`pm close --validate-close warn` can close an item while reporting missing
|
|
6
7
|
resolution, expected outcome, or actual outcome. Its SDK result and compact CLI
|
|
7
|
-
output
|
|
8
|
-
`
|
|
8
|
+
output include an optional `follow_up` with `kind: complete_close_evidence`,
|
|
9
|
+
`missing`, `suggested_command`, and `suggested_command_args` when evidence is
|
|
10
|
+
incomplete. The close succeeded; do not retry it. The argument vector selects
|
|
9
11
|
the same tracker and uses `pm update` to add only the missing evidence fields.
|
|
10
|
-
Use `
|
|
12
|
+
Use `follow_up.suggested_command_args` as the authoritative argument vector. Replace
|
|
11
13
|
each `<value>` with the observed outcome before executing it; retain its tracker
|
|
12
14
|
selection and only the flags it supplies for missing fields. Do not add flags
|
|
13
15
|
for evidence already present, because `pm update` would overwrite that evidence.
|
|
@@ -25,11 +27,18 @@ recovery when applicable. `--force` is reserved for an intentional repeated
|
|
|
25
27
|
lifecycle transition. Adding evidence with `pm update` preserves the original
|
|
26
28
|
close timestamp, close reason, and immutable history event, then appends a
|
|
27
29
|
normal update event. It does not retroactively claim that evidence existed at
|
|
28
|
-
the original close.
|
|
30
|
+
the original close. Failed terminal retries retain `recovery.suggested_retry_args`;
|
|
31
|
+
successful closes never emit failure recovery. Complete closes have no follow-up.
|
|
29
32
|
|
|
30
33
|
The update flags for the other missing fields are `--resolution` and
|
|
31
34
|
`--expected-result`; include them only when the generated recovery requests them.
|
|
32
35
|
|
|
33
36
|
For new work, include all three fields in the original close command so its
|
|
34
|
-
immutable event contains the full evidence
|
|
35
|
-
|
|
37
|
+
immutable event contains the full evidence:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pm close <item-id> "Delivered and verified" --resolution "What changed" \
|
|
41
|
+
--expected "Required outcome" --actual "Observed outcome" --validate-close warn
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Warning-mode follow-up exists for incomplete historical or interrupted workflows.
|
package/docs/COMMANDS.md
CHANGED
|
@@ -209,6 +209,32 @@ Each aggregate row carries an explicit `group_label`: a blank/null group value (
|
|
|
209
209
|
pm list --all --sort updated --order desc
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
+
Brief list rows include an explicitly selected sort field (including normalized
|
|
213
|
+
aliases such as `updated_at`) and declare it in `projection.fields`. Explicit
|
|
214
|
+
`--fields`, compact and full projections retain their requested fields.
|
|
215
|
+
This rule is shared by SDK list queries.
|
|
216
|
+
|
|
217
|
+
Lifecycle filters such as `--all` and `--status all` retain the canonical `list`
|
|
218
|
+
command's brief default; they select rows without expanding item fields. Use
|
|
219
|
+
`--full`, `--compact`, `--brief`, `--fields` or `--include-body` to choose more
|
|
220
|
+
evidence explicitly. Raw SDK list calls keep their full default, and explicit
|
|
221
|
+
`--all --full --strict-read` remains a complete corpus read.
|
|
222
|
+
The implementation records
|
|
223
|
+
[pm-gh1481](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-gh1481.toon)
|
|
224
|
+
and [pm-gh1489](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-gh1489.toon)
|
|
225
|
+
are repository-only tracker files, excluded from the npm package.
|
|
226
|
+
|
|
227
|
+
New dependency writes record `created_at`. Supplied values must be calendar-valid
|
|
228
|
+
RFC 3339 date-times. SDK dependency reads expose this field as optional because
|
|
229
|
+
legacy rows without a timestamp remain readable: they sort before timestamped
|
|
230
|
+
rows, with deterministic id/kind/source
|
|
231
|
+
tie-breakers and no invented provenance. An invalid supplied timestamp produces
|
|
232
|
+
`item_document_invalid` with the item path and dependency field.
|
|
233
|
+
`pm validate --check-storage-integrity` and `pm health --check-only --full` expose
|
|
234
|
+
that malformed item. The implementation record
|
|
235
|
+
[pm-gh1482](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-gh1482.toon)
|
|
236
|
+
is a repository-only tracker file, excluded from the npm package.
|
|
237
|
+
|
|
212
238
|
### Incremental "what changed since" filters
|
|
213
239
|
|
|
214
240
|
Every `list*` command accepts `--updated-after`/`--updated-before`/`--created-after`/`--created-before`. `pm search` now supports the SAME filter surface as `pm list` (full parity): `--status`, `--type`, `--tag`, `--priority`, `--deadline-before`/`--deadline-after`, `--updated-after`/`--updated-before`, `--created-after`/`--created-before`, `--assignee`, `--sprint`, `--release`, and `--parent`, all with identical semantics. These keep a long-running agent's context focused on the slice it cares about instead of re-scanning the whole tracker:
|
|
@@ -620,14 +646,19 @@ row summaries. See tracker item [pm-awe3t6](../.agents/pm/issues/pm-awe3t6.toon)
|
|
|
620
646
|
Tracked by [pm-o8z748](../.agents/pm/issues/pm-o8z748.toon) and
|
|
621
647
|
[pm-cyn0y6](../.agents/pm/issues/pm-cyn0y6.toon).
|
|
622
648
|
|
|
623
|
-
`pm item mutate` is the noun-first CLI adapter over the public SDK
|
|
624
|
-
`commitItemMutations` primitive. Pipe either
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
649
|
+
`pm item mutate` is the noun-first CLI adapter over the public SDK planner
|
|
650
|
+
(`planItemMutationDocument`) and `commitItemMutations` primitive. Pipe either
|
|
651
|
+
the legacy non-empty JSON array, a versioned
|
|
652
|
+
`{ "schema_version": 1, "mutations": [...] }` document, or JSON Lines (one
|
|
653
|
+
record per line), or read any of them from a file with `--from <path>`. Mix
|
|
654
|
+
create/update/close/release operations in order. Create rows may declare a
|
|
655
|
+
unique `ref` and omit `id`; exact `@ref` values work in target ids, `parent`,
|
|
656
|
+
`blockedBy`, and dependency `id` fields. The resolver derives replay-stable ids
|
|
657
|
+
before the writer lock and returns a `references` receipt plus an input-ordered
|
|
658
|
+
`rows` receipt (`index`, `ref`, `id`, `op`, `upserted`). When `--transaction-id`
|
|
659
|
+
is omitted the id is derived from the exact document bytes
|
|
660
|
+
(`transaction_id_source: "derived"`), so identical bytes select the same
|
|
661
|
+
journal. Replaying a committed import also requires an unchanged resolved plan:
|
|
631
662
|
|
|
632
663
|
```bash
|
|
633
664
|
pm item mutate \
|
|
@@ -644,13 +675,83 @@ pm item mutate \
|
|
|
644
675
|
JSON
|
|
645
676
|
```
|
|
646
677
|
|
|
678
|
+
`--from <path>` selects a file and rejects an explicitly supplied `--stdin-json`.
|
|
679
|
+
Default stdin input, explicit `--stdin-json` without a file, and `--from -`
|
|
680
|
+
remain supported.
|
|
681
|
+
|
|
647
682
|
Use `--dry-run` to validate and preview without acquiring a writer lock. Reuse
|
|
648
683
|
the exact transaction id and deterministic batch after interruption: the SDK
|
|
649
684
|
journal resumes pending steps and never duplicates a successfully applied
|
|
650
|
-
step.
|
|
651
|
-
|
|
685
|
+
step. A different plan under a committed or resumable journal refuses with
|
|
686
|
+
`transaction_plan_mismatch`; pass a new `--transaction-id` to commit that changed
|
|
687
|
+
plan as its own transaction. A fully compensated attempt has nothing left to
|
|
688
|
+
resume and may accept a new plan under the same transaction id. Formatting-only
|
|
689
|
+
edits change a derived id; pass the original id explicitly to replay them when
|
|
690
|
+
the resolved plan is unchanged. `--create-compensation close|delete`,
|
|
691
|
+
`--lock-ttl-seconds`, and `--lock-wait-ms` expose the transaction safety controls. The equivalent MCP
|
|
652
692
|
surface is `pm_mutate`.
|
|
653
693
|
|
|
694
|
+
Raw mutation `options` use command option types: write `estimatedMinutes: "45"`.
|
|
695
|
+
Item documents may instead use numeric `estimated_minutes: 45`. A non-string
|
|
696
|
+
raw estimate refuses before journal or item writes with
|
|
697
|
+
`mutation_option_value_invalid` (exit 2), identifying the row and option.
|
|
698
|
+
Corrupt durable journals, including a wrong stored schema version or transaction
|
|
699
|
+
identity, refuse with `transaction_journal_invalid`; preserve
|
|
700
|
+
the journal and inspect or restore verified state before retrying. Changing the
|
|
701
|
+
transaction id does not safely recover unknown previously applied work.
|
|
702
|
+
|
|
703
|
+
#### Bulk creation (`pm create many` route)
|
|
704
|
+
|
|
705
|
+
Tracked by [pm-gh1456](../.agents/pm/features/pm-gh1456.toon). `pm create many`
|
|
706
|
+
is not a command; it refuses with `bulk_create_route` and points here. A record
|
|
707
|
+
without `op` is a create document that uses the same field names as
|
|
708
|
+
`pm create` flags or their JSON equivalents (`title`, `type`, `description`,
|
|
709
|
+
`body`, `tags`, `parent`, `priority`, declared custom fields, ...); a create
|
|
710
|
+
row may also carry that document under `item` instead of `options`. Records
|
|
711
|
+
without `ref` or `id` receive `row-<n>` aliases so the receipt and `@row-<n>`
|
|
712
|
+
references stay addressable. One process, one workspace transaction: every
|
|
713
|
+
record is created or none.
|
|
714
|
+
|
|
715
|
+
```bash
|
|
716
|
+
cat > items.jsonl <<'JSONL'
|
|
717
|
+
{"title":"Imported A","type":"Task","external_id":"ext-1","tags":["import"]}
|
|
718
|
+
{"ref":"b","title":"Imported B","type":"Feature","external_id":"ext-2","parent":"@row-1"}
|
|
719
|
+
JSONL
|
|
720
|
+
pm item mutate --from items.jsonl --dry-run --json # validate, derived transaction id
|
|
721
|
+
pm item mutate --from items.jsonl --json # commit; re-running replays (recovered: true)
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
`--upsert-key <field>` makes a re-run safe for changed data: a create record
|
|
725
|
+
whose field value matches exactly one existing item (core field such as
|
|
726
|
+
`title`, or a declared custom field such as `external_id`) becomes an update
|
|
727
|
+
of that item and is reported with `upserted: true`. Matching and lock-held
|
|
728
|
+
guards use the field's stored metadata key; core option names such as
|
|
729
|
+
`acceptanceCriteria`, declared field keys and their SDK option targets
|
|
730
|
+
(for example `externalId`) resolve to that
|
|
731
|
+
same stored key. The record keeps its
|
|
732
|
+
`ref` in the receipt, and later records may still address it as `@ref`, which
|
|
733
|
+
then resolves to the matched item. A record missing the key, two records
|
|
734
|
+
sharing a key value, or a key value matching several existing items refuses
|
|
735
|
+
before any write (`upsert_key_missing`, `upsert_key_duplicate`,
|
|
736
|
+
`upsert_key_ambiguous`). Matching happens before the writer lock, so every
|
|
737
|
+
record that matched nothing carries its key into the commit, which re-checks
|
|
738
|
+
it under the lock: when another writer created an item with that key value
|
|
739
|
+
after planning, the transaction refuses with `upsert_key_conflict` before any
|
|
740
|
+
write, and a re-run plans the record as an update of that item. A record that
|
|
741
|
+
did match is committed as an update that re-reads the key under the lock and
|
|
742
|
+
refuses with `upsert_match_changed` when the key was changed or removed after
|
|
743
|
+
planning. Either refusal rolls the attempt back completely, and a rolled-back
|
|
744
|
+
attempt leaves its derived transaction id reusable, so re-running the same
|
|
745
|
+
document simply starts a fresh attempt from the current key values.
|
|
746
|
+
|
|
747
|
+
```bash
|
|
748
|
+
printf '%s\n' '{"title":"Imported A (renamed)","type":"Task","external_id":"ext-1"}' \
|
|
749
|
+
| pm item mutate --upsert-key external_id --json
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
Over MCP, `pm_mutate` accepts the same document rows as `{ref?, item: {...}}`
|
|
753
|
+
entries, `upsertKey`, and an optional `transactionId`.
|
|
754
|
+
|
|
654
755
|
`pm item complete` composes evidence, governed closure, and claim release into
|
|
655
756
|
one compensating SDK transaction. It accepts the normal repeatable evidence
|
|
656
757
|
flags and can preview the exact ordered mutations before writing:
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -148,6 +148,18 @@ For command-level tracker targeting, prefer `--pm-path <tracker-root>`. The old
|
|
|
148
148
|
itself, not the repository workspace. During `pm init`, explicit tracker paths
|
|
149
149
|
that look like workspace roots are rejected unless `--force` is provided.
|
|
150
150
|
|
|
151
|
+
Implicit discovery checks the current directory and its ancestors up to the
|
|
152
|
+
nearest `.git` directory or file, including worktrees and submodules. An
|
|
153
|
+
uninitialized repository selects its own `.agents/pm` and returns initialization
|
|
154
|
+
recovery instead of reading or changing an enclosing repository's tracker.
|
|
155
|
+
Ordinary subdirectories still share their repository's tracker, including
|
|
156
|
+
root-layout trackers. To deliberately share a tracker across repository
|
|
157
|
+
boundaries, pass `--pm-path <tracker-root>` or set `PM_PATH` explicitly.
|
|
158
|
+
This shared SDK discovery policy also applies to CLI and MCP commands.
|
|
159
|
+
Directory aliases follow physical ancestry, including missing descendants of
|
|
160
|
+
an existing alias. Unexpected directory or `.git` lookup errors stop discovery
|
|
161
|
+
instead of falling through to an enclosing tracker.
|
|
162
|
+
|
|
151
163
|
Tests should set both `PM_PATH` and `PM_GLOBAL_PATH` to temporary directories. The wrapper `node scripts/run-tests.mjs ...` does that automatically.
|
|
152
164
|
|
|
153
165
|
### Telemetry environment variables
|
|
@@ -212,7 +224,16 @@ Interaction rules:
|
|
|
212
224
|
- `pm health --check-telemetry --json` surfaces flush and OTLP export diagnostics (`pending_otel_spans`, `last_otel_attempt_at`, `last_otel_success_at`, `last_otel_failure_at`, `last_otel_failure_error`) and the active `env_overrides` (including `telemetry_inline_flush` and `telemetry_source_context`) so agents can self-diagnose a stalled endpoint.
|
|
213
225
|
- An explicit `PM_AUTHOR` override adds a privacy-preserving agent-identity dimension to `command_start`/`command_finish` events so overridden invocations can be segmented in dashboards without leaking the raw author string. At `redacted`/`max` capture the events carry `author_context_hash` — the same installation-id-keyed one-way SHA-256 used for `pm_root_hash`/`cwd_hash`, so the same author hashes consistently within an installation but differently across installations. At `minimal` capture only a boolean `has_author_context` is emitted. The raw `PM_AUTHOR` value is never exported.
|
|
214
226
|
|
|
215
|
-
Test environments inferred from `VITEST`, `VITEST_WORKER_ID`,
|
|
227
|
+
Test environments inferred from `VITEST`, `VITEST_WORKER_ID`, `NODE_TEST_CONTEXT`
|
|
228
|
+
(native `node --test` children), or `NODE_ENV=test` suppress telemetry and Sentry
|
|
229
|
+
before identity creation. A valid explicit `PM_TELEMETRY_SOURCE_CONTEXT` or
|
|
230
|
+
`PM_TELEMETRY_SEND_TEST_EVENTS=1` permits intentional test delivery. Point such
|
|
231
|
+
tests at a local collector. Inferred tests use inline telemetry flushing even
|
|
232
|
+
after an opt in, so CLI delivery settles before process exit and disposable-root
|
|
233
|
+
cleanup. SDK telemetry completion also awaits inline delivery before returning.
|
|
234
|
+
Neither setting overrides a hard opt-out. `pm telemetry status` exposes effective `enabled`, persisted
|
|
235
|
+
`configured_enabled`, and `env_overrides` so an empty queue is distinguishable
|
|
236
|
+
from disabled delivery.
|
|
216
237
|
|
|
217
238
|
SDK consumers that previously used `TelemetryStatusSummary.enabled` to display the saved preference should read `configured_enabled` instead. Use `enabled` to determine whether this process permits delivery.
|
|
218
239
|
|
|
@@ -20,6 +20,13 @@ nightly quality and release paths enforce it. The registry-owned local
|
|
|
20
20
|
preflight also requires the static gate and permits no skip. Trivy separately
|
|
21
21
|
includes development dependencies in its required repository scan.
|
|
22
22
|
|
|
23
|
+
Composite action refs and their executed tool versions need separate review.
|
|
24
|
+
[pm-38w3ii](../.agents/pm/chores/pm-38w3ii.toon) pins TruffleHog's action
|
|
25
|
+
commit and explicitly selects scanner version `3.98.0`; the action otherwise
|
|
26
|
+
defaults to the `latest` image. The workflow contract checks both values on
|
|
27
|
+
every TruffleHog step. Recheck the action's executable selectors when renewing
|
|
28
|
+
its commit pin.
|
|
29
|
+
|
|
23
30
|
## Indexed source-map offsets
|
|
24
31
|
|
|
25
32
|
[pm-dba47](../.agents/pm/issues/pm-dba47.toon) tracks Dependabot alert 47 and
|
|
@@ -109,9 +116,21 @@ program matches the reviewed [shim templates](../config/codspeed-shims/), with
|
|
|
109
116
|
targets and module paths derived from the audited installed dependency. Arbitrary
|
|
110
117
|
names, nested payloads, links, altered programs and forged target markers fail;
|
|
111
118
|
these shims are outside the twelve package-owned hashes but are independently
|
|
112
|
-
validated.
|
|
113
|
-
|
|
114
|
-
|
|
119
|
+
validated. [pm-rnpmtp](../.agents/pm/chores/pm-rnpmtp.toon) renews the installer
|
|
120
|
+
to pnpm 11.28.5 and its bundled `bins/cmd-shim` generator. Separate complete shell
|
|
121
|
+
templates describe POSIX and Windows installations; only the host's template is
|
|
122
|
+
accepted. Windows shells pass Windows `NODE_PATH` values to native Node, and
|
|
123
|
+
Cygwin targets use Windows paths. CMD and PowerShell programs retain their
|
|
124
|
+
complete comparisons. Template changes require renewed real installation and
|
|
125
|
+
dependency-resolution evidence on POSIX, Git Bash and Cygwin, plus CMD and
|
|
126
|
+
PowerShell. The Windows script cohort downloads the archived Cygwin setup 2.937
|
|
127
|
+
installer and verifies its pinned SHA-512 before execution. To renew it, select
|
|
128
|
+
an eligible version from the official [setup archive](https://cygwin.com/setup/),
|
|
129
|
+
verify the executable against the archive's `sha512.sum`, and update the
|
|
130
|
+
versioned URL, pinned digest and workflow contract together. Preserve setup's
|
|
131
|
+
default package-signature verification and repeat native launcher acceptance.
|
|
132
|
+
Literal percent paths are exercised in disposable launcher fixtures;
|
|
133
|
+
the audited CodSpeed installation still refuses shell interpolation paths.
|
|
115
134
|
The CMD suffix follows the installed `PATHEXT` spelling, including `.CMD`;
|
|
116
135
|
format lookup folds its case while validating the complete program. All three
|
|
117
136
|
shell launchers are required, together with the CMD and PowerShell sets on
|
|
@@ -27,12 +27,16 @@ it is not silently equated with the earlier item snapshot. History-drift
|
|
|
27
27
|
validation passed across all 2,826 current items. The public SDK independently
|
|
28
28
|
verified hash chains for all 2,841 collected streams with zero failures.
|
|
29
29
|
|
|
30
|
-
[The per-item census](ecosystem-review-2026-09-28.json) records every snapshot
|
|
30
|
+
[The per-item census](https://github.com/unbraind/pm-cli/blob/main/docs/ecosystem-review-2026-09-28.json) records every snapshot
|
|
31
31
|
ID, status, content fingerprint, structural classification, missing planning
|
|
32
32
|
fields, historical evidence gaps, and remediation owner. These are mechanical
|
|
33
33
|
findings, not invented historical estimates, outcomes, or review approvals.
|
|
34
34
|
The full raw corpus stays outside public documentation.
|
|
35
35
|
|
|
36
|
+
The census is intentionally excluded from npm. This packaged page uses its
|
|
37
|
+
canonical GitHub file URL under the [documentation policy](../AGENTS.md#documentation-policy),
|
|
38
|
+
so installed readers can access the data without a broken package-relative path.
|
|
39
|
+
|
|
36
40
|
| Measure | Initial observation | Interpretation |
|
|
37
41
|
| --- | ---: | --- |
|
|
38
42
|
| Directed graph edges | 14,097 | Deduplicated directed basis |
|
package/docs/EXTENSIONS.md
CHANGED
|
@@ -305,7 +305,7 @@ Use the public SDK barrel. Do not deep-import from `src/core` or `dist/core`.
|
|
|
305
305
|
|
|
306
306
|
- `api.extension` is a read-only identity (`name`, `layer`, `version`, `capabilities`, `pm_min_version?`, `pm_max_version?`, `source_package?`) for self-identifying logs and version gating without re-reading the manifest.
|
|
307
307
|
- `api.registerCommand(definition)` adds package-owned commands; `read_output` opts readers into the [SDK output contract](SDK.md#minimal-command-extension).
|
|
308
|
-
- `api.registerFlags(command, flags)` adds runtime command flags. A flag may declare `value_type` (canonical; the legacy `type` alias is honored only when `value_type` is absent), `list: true` to accumulate repeated/comma-joined values like core `--tags`,
|
|
308
|
+
- `api.registerFlags(command, flags)` adds runtime command flags. A flag may declare `value_type` (canonical; the legacy `type` alias is honored only when `value_type` is absent), `list: true` to accumulate repeated/comma-joined values like core `--tags`, a `default` applied when the flag is omitted, and `value_validation: "strict"` to refuse malformed `number`/`boolean` tokens before the handler runs (the default `"coerce"` forwards the raw token). See [Flag Contracts](SDK.md#flag-contracts).
|
|
309
309
|
- `api.registerItemFields(fields)` adds custom metadata fields. Agents can set declared fields with repeatable `pm create --field name=value` and `pm update <id> --field name=value`; undeclared names are rejected. `SchemaFieldDefinition.type` is the same closed union used by `pm schema add-field`: `string | number | boolean | string_array | array | object`. Unsupported values fail at compile time for TypeScript authors and at activation for JavaScript packages, with a did-you-mean hint on typos. `string_array` is the repeatable string collection; `array` and `object` require JSON containers.
|
|
310
310
|
- Custom fields whose camel-case option name is already owned by a canonical MCP input remain usable through `options.<name>`, but authoring surfaces report the collision instead of allowing silent top-level shadowing. `pm schema add-field`, `pm profile lint`, and `pm package doctor` name the field, canonical `mcp_tool_input` owner, and nested recovery path. SDK authors can preflight the same rule with `resolvePmToolCustomFieldCollision`.
|
|
311
311
|
- `api.registerItemTypes(types)` adds custom item types.
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Output Projection and Omission Contracts
|
|
2
2
|
|
|
3
|
+
Passing extension health defaults are tracked by
|
|
4
|
+
[pm-gh1486](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-gh1486.toon),
|
|
5
|
+
a repository-only tracker file excluded from the npm package. Standard `pm health` output
|
|
6
|
+
reports healthy extension counts and `restore_with: "pm health --full"` rather
|
|
7
|
+
than the command registry. Its `standard` projection declares the omitted full
|
|
8
|
+
check details. Warning and failure details remain available by default.
|
|
9
|
+
`--full` restores structured evidence; `--brief` never expands an individual
|
|
10
|
+
check's serialized detail beyond the standard projection. Summary and check-only
|
|
11
|
+
verdict semantics remain unchanged. SDK `runHealth` and MCP use the same engine.
|
|
12
|
+
|
|
3
13
|
Tracker references: [pm-p258tx](../.agents/pm/features/pm-p258tx.toon),
|
|
4
14
|
[pm-cyrfjq](../.agents/pm/issues/pm-cyrfjq.toon), and
|
|
5
15
|
[pm-qhnq6t](../.agents/pm/issues/pm-qhnq6t.toon). The universal row and
|
package/docs/RELEASING.md
CHANGED
|
@@ -304,7 +304,14 @@ The release workflow publishes this staged tarball with provenance; CI and
|
|
|
304
304
|
packed smoke tests use the same staging command. Application distribution and
|
|
305
305
|
bundled runtime have separate committed size and file-count limits, so runtime
|
|
306
306
|
payload cannot hide application growth. The ledger ships with the tarball for
|
|
307
|
-
installed-version verification.
|
|
307
|
+
installed-version verification. [pm-iceees](../.agents/pm/issues/pm-iceees.toon)
|
|
308
|
+
keeps selected optional-peer subtrees complete: npm deliberately skips peer edges
|
|
309
|
+
when gathering bundled files, so staged runtime manifests record the exact tested
|
|
310
|
+
peer bindings as ordinary or optional dependency entries. Package code, source
|
|
311
|
+
and installed manifests, peer declarations, and the root public dependency
|
|
312
|
+
inventory remain intact. A real archive regression resolves the peer's descendant
|
|
313
|
+
from an extracted package and the installed-runtime verifier still refuses any
|
|
314
|
+
missing locked package. npm 12 ignores published shrinkwraps; shipping
|
|
308
315
|
a shrinkwrap alone therefore cannot enforce this contract. SDK consumers
|
|
309
316
|
supply the bounded optional Node types peer themselves.
|
|
310
317
|
|
package/docs/SDK.md
CHANGED
|
@@ -483,6 +483,12 @@ not renderer-specific code, so package authors can reuse
|
|
|
483
483
|
`resolvePmCommandOutputBudget`, and
|
|
484
484
|
`estimatePmOutputTokens` in custom transports.
|
|
485
485
|
|
|
486
|
+
Read-output, context-intent, recurrence and diagnostic string compaction retain
|
|
487
|
+
Unicode-safe prefixes. A cutoff through a surrogate pair backs up one UTF-16
|
|
488
|
+
code unit before adding its suffix. Rendering and token receipts use the actual
|
|
489
|
+
retained text; unbounded reads and preserved-string exceptions are unchanged.
|
|
490
|
+
Tracked by [pm-gh1478](../.agents/pm/issues/pm-gh1478.toon).
|
|
491
|
+
|
|
486
492
|
```ts
|
|
487
493
|
import {
|
|
488
494
|
definePmCommandOutputBudget,
|
|
@@ -946,6 +952,27 @@ recurrence reason, accepts only the workspace open or in-progress target, and
|
|
|
946
952
|
returns the terminal evidence captured atomically before the update path clears
|
|
947
953
|
it from active metadata.
|
|
948
954
|
|
|
955
|
+
Lifecycle handoff and receipt guidance are tracked by
|
|
956
|
+
[pm-gh1465](../.agents/pm/features/pm-gh1465.toon) and
|
|
957
|
+
[pm-gh1464](../.agents/pm/issues/pm-gh1464.toon). Register a project-specific
|
|
958
|
+
queue with `client.schemaAddStatus("review", { role: ["active"] })`, then call
|
|
959
|
+
`client.release(id, { handoff: "review", message: "Implemented; run linked verification" })`.
|
|
960
|
+
The SDK atomically changes status and clears ownership in one release history
|
|
961
|
+
event, applying project ownership, type-transition, and workflow policies.
|
|
962
|
+
`ReleaseMutationOptions` declares the handoff option; `ReleaseResult.handoff`
|
|
963
|
+
identifies the source and destination states and evidence. `client.list({ status:
|
|
964
|
+
"review" })` selects the verifier queue; context preserves its status without
|
|
965
|
+
counting it as in-progress work. The destination must already exist, be
|
|
966
|
+
non-terminal, and differ from the configured in-progress status. Handoff needs
|
|
967
|
+
a claimed source and evidence message, and cannot be combined with pause.
|
|
968
|
+
|
|
969
|
+
A successful warning-mode close with missing evidence returns optional
|
|
970
|
+
`follow_up: CloseEvidenceFollowUp`. Its `kind` is `complete_close_evidence` and
|
|
971
|
+
`suggested_command_args` selects an evidence-only update of the same item and
|
|
972
|
+
tracker. Consumers migrating from successful-close `recovery` should read
|
|
973
|
+
`follow_up` instead; a successful close never asks for a retry. Failed close
|
|
974
|
+
commands retain failure recovery. See [close evidence guidance](CLOSE_EVIDENCE_RECOVERY.md).
|
|
975
|
+
|
|
949
976
|
### Atomic workspace transactions
|
|
950
977
|
|
|
951
978
|
Tracked by [pm-4e12](../.agents/pm/features/pm-4e12.toon), with the VCS
|
|
@@ -1103,7 +1130,14 @@ bulk sync), `commitItemMutations` wraps the coordinator so callers describe
|
|
|
1103
1130
|
the mutations instead of hand-writing a step array. The helper wires the
|
|
1104
1131
|
crash-consistency contract for you: creates use their resolved stable `id` as
|
|
1105
1132
|
the idempotency key (exists-by-id inspection) and are compensated by closing
|
|
1106
|
-
the item (or deleting it with `createCompensation: "delete"`)
|
|
1133
|
+
the item (or deleting it with `createCompensation: "delete"`). A retry refuses
|
|
1134
|
+
with `transaction_create_compensated` while a creation's latest closure belongs
|
|
1135
|
+
to compensation, even if its close prose was edited. Review its immutable history
|
|
1136
|
+
and explicitly reopen it before retrying; the SDK preserves later lifecycle
|
|
1137
|
+
decisions instead of silently reopening the item or reporting it committed.
|
|
1138
|
+
A later explicit user close or status update takes precedence over the earlier
|
|
1139
|
+
compensation close and is preserved when the transaction resumes.
|
|
1140
|
+
Updates stamp a
|
|
1107
1141
|
durable history marker for applied-detection and are compensated by restoring
|
|
1108
1142
|
the captured pre-mutation version; closes treat an already-terminal target as
|
|
1109
1143
|
applied and are likewise compensated by version restore; releases restore the
|
|
@@ -1241,6 +1275,70 @@ await commitItemMutations({
|
|
|
1241
1275
|
});
|
|
1242
1276
|
```
|
|
1243
1277
|
|
|
1278
|
+
For imports, use `planItemMutationDocument` (tracked by
|
|
1279
|
+
[pm-gh1456](../.agents/pm/features/pm-gh1456.toon)). It reads the workspace
|
|
1280
|
+
schema so declared custom fields route through their option targets, accepts
|
|
1281
|
+
JSON Lines and op-less create documents (records shaped like `pm create
|
|
1282
|
+
--stdin-json` input, optionally wrapped as `{ ref, item }`), synthesizes
|
|
1283
|
+
`row-<n>` aliases for records without `ref`/`id`, derives a stable
|
|
1284
|
+
`transaction_id` from the document bytes when none is supplied, and resolves
|
|
1285
|
+
`upsertKey` against existing items so matching create records become updates;
|
|
1286
|
+
core camelCase option names (such as `acceptanceCriteria`) and declared field
|
|
1287
|
+
keys or option targets resolve to the stored metadata key before candidate
|
|
1288
|
+
reads and lock-held guards.
|
|
1289
|
+
An explicitly supplied blank `upsertKey` is a usage error; omit it to select plain creation.
|
|
1290
|
+
Unrelated extension metadata keys retain their exact spelling, including camelCase.
|
|
1291
|
+
Item documents also accept known core camelCase option names, including inside
|
|
1292
|
+
`{ item }` wrappers. Exact stored metadata keys win when both spellings appear.
|
|
1293
|
+
Records that match nothing carry a `unique` guard that `commitItemMutations`
|
|
1294
|
+
re-checks under the writer lock and refuses with `upsert_key_conflict` when a
|
|
1295
|
+
concurrent writer created the key value after planning; matched records become
|
|
1296
|
+
updates carrying a `match` guard checked against the locked target document,
|
|
1297
|
+
after acquiring its item lock. It refuses with `upsert_match_changed` when the
|
|
1298
|
+
target's key changed in between, including changes made by ordinary item updates.
|
|
1299
|
+
Successful update, close and release steps invalidate cached unique-key scans
|
|
1300
|
+
inside a mixed batch, so subsequent creates see the current persisted values,
|
|
1301
|
+
including changes to earlier creates in that batch.
|
|
1302
|
+
Every create also advances cached scans from its returned metadata, including
|
|
1303
|
+
unguarded creates and records guarded on a different key, without a new project scan.
|
|
1304
|
+
The returned `rows` receipt maps every input record, in order, to its resolved
|
|
1305
|
+
`id` and `op`:
|
|
1306
|
+
|
|
1307
|
+
```ts
|
|
1308
|
+
import {
|
|
1309
|
+
commitItemMutations,
|
|
1310
|
+
planItemMutationDocument,
|
|
1311
|
+
} from "@unbrained/pm-cli/sdk";
|
|
1312
|
+
|
|
1313
|
+
const plan = await planItemMutationDocument({
|
|
1314
|
+
pmRoot,
|
|
1315
|
+
input: [
|
|
1316
|
+
'{"title":"Imported A","type":"Task","external_id":"ext-1"}',
|
|
1317
|
+
'{"ref":"b","title":"Imported B","type":"Feature","parent":"@row-1","external_id":"ext-2"}',
|
|
1318
|
+
].join("\n"),
|
|
1319
|
+
upsertKey: "external_id",
|
|
1320
|
+
});
|
|
1321
|
+
const result = await commitItemMutations({
|
|
1322
|
+
pmRoot,
|
|
1323
|
+
author: "import-agent",
|
|
1324
|
+
transactionId: plan.transaction_id,
|
|
1325
|
+
mutations: plan.mutations,
|
|
1326
|
+
});
|
|
1327
|
+
console.log(plan.transaction_id_source, plan.rows, result.recovered);
|
|
1328
|
+
```
|
|
1329
|
+
|
|
1330
|
+
After a successful commit, reuse its transaction id and unchanged resolved
|
|
1331
|
+
mutation plan to replay it (`recovered: true`). A formatting-only edit changes
|
|
1332
|
+
the derived id; pass the original id explicitly to replay an unchanged plan.
|
|
1333
|
+
The planner excludes items created by that transaction from upsert matching,
|
|
1334
|
+
retaining those create rows.
|
|
1335
|
+
If document edits, external matches, or schema context change the resolved
|
|
1336
|
+
plan under that committed id, the coordinator refuses with
|
|
1337
|
+
`transaction_plan_mismatch`; use a new transaction id for the changed import.
|
|
1338
|
+
Corrupt journal JSON, stored schema version/transaction identity, lifecycle state or metadata instead refuses with
|
|
1339
|
+
`transaction_journal_invalid`. Preserve and inspect or restore the journal;
|
|
1340
|
+
starting a new id can duplicate work whose durable state cannot be verified.
|
|
1341
|
+
|
|
1244
1342
|
`buildItemCompletionMutations` creates the ordered evidence/update, close, and
|
|
1245
1343
|
release plan for inspection. `commitItemCompletion` executes that plan through
|
|
1246
1344
|
the same durable coordinator, restoring annotations, linked artifacts,
|
|
@@ -2225,6 +2323,20 @@ same list/default semantics as core flags:
|
|
|
2225
2323
|
`default: "a,b"` or `default: ["a,b", "c"]`) are split into elements. A default
|
|
2226
2324
|
that would not cleanly coerce under the declared `value_type` (e.g.
|
|
2227
2325
|
`value_type: "number", default: "abc"`) is rejected at registration.
|
|
2326
|
+
- `value_validation` (`"coerce"` | `"strict"`, tracked by
|
|
2327
|
+
[pm-extension-scalar-validation](../.agents/pm/features/pm-extension-scalar-validation.toon))
|
|
2328
|
+
decides what happens to a `number`/`boolean` token that does not coerce.
|
|
2329
|
+
`coerce` is the compatible default: the raw token reaches the handler for its
|
|
2330
|
+
own validation (`--limit abc` arrives as `"abc"`). `strict` refuses the
|
|
2331
|
+
invocation before dispatch with `extension_flag_value_invalid` (exit 2),
|
|
2332
|
+
naming the flag, the command, the expected grammar, and the received token;
|
|
2333
|
+
list entries are checked one by one, including attached values on boolean
|
|
2334
|
+
list switches. CSV boolean lists accept `true,false`; repeatable boolean
|
|
2335
|
+
lists keep each occurrence as one value. Switch presence (`--verbose`,
|
|
2336
|
+
`--no-verbose`), the legacy `bool` optional-value grammar (`--enabled` alone
|
|
2337
|
+
is `true`), declared defaults, and string flags are unaffected. `strict` on a
|
|
2338
|
+
`string` or untyped flag is rejected at registration because there is nothing
|
|
2339
|
+
to validate.
|
|
2228
2340
|
|
|
2229
2341
|
```ts
|
|
2230
2342
|
api.registerFlags("report", [
|
|
@@ -2235,7 +2347,7 @@ api.registerFlags("report", [
|
|
|
2235
2347
|
list: true,
|
|
2236
2348
|
default: "all",
|
|
2237
2349
|
},
|
|
2238
|
-
{ long: "--limit", value_type: "number", default: 20 },
|
|
2350
|
+
{ long: "--limit", value_type: "number", default: 20, value_validation: "strict" },
|
|
2239
2351
|
]);
|
|
2240
2352
|
```
|
|
2241
2353
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# SDK context coordination primitives
|
|
2
2
|
|
|
3
|
-
Trackers: [pm-e200](
|
|
3
|
+
Trackers: [pm-e200](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/features/pm-e200.toon), [pm-ez1dfg](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/tasks/pm-ez1dfg.toon), [pm-4ri6](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/features/pm-4ri6.toon), [pm-hcrmye](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-hcrmye.toon), [pm-gh1485](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-gh1485.toon), and [pm-xj80p9](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-xj80p9.toon).
|
|
4
|
+
|
|
5
|
+
Tracker records live in the repository and are excluded from the npm package.
|
|
4
6
|
|
|
5
7
|
`pm` treats project management as context management. These primitives let an
|
|
6
8
|
agent learn what changed, avoid creating redundant work, and keep that work
|
|
@@ -38,10 +40,61 @@ idempotently or deduplicate replays. `--cursor-mode row` preserves the previous
|
|
|
38
40
|
shape with one `cursor` per event and no trailer for consumers that checkpoint
|
|
39
41
|
every row. Already issued version-1 cursors remain accepted by `--since`.
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
Version-1 cursor ordering uses recorded timestamps, stream ids, and offsets.
|
|
44
|
+
A fact committed later with an older timestamp falls before an advanced cursor.
|
|
45
|
+
Clock-independent ordering and late-commit recovery remain tracked by
|
|
46
|
+
[pm-10l1vm](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-10l1vm.toon). Hosts needing complete concurrent
|
|
47
|
+
observation can retain a fixed lower boundary and deduplicate snapshots by
|
|
48
|
+
`item_id` and `version` while work is being committed.
|
|
49
|
+
|
|
50
|
+
Runtimes exposing `node:sqlite` use the rebuildable SQLite event projection.
|
|
51
|
+
Runtimes without it transparently scan the authoritative history
|
|
43
52
|
streams with the same ordering, filters, pagination, and cursor contract; pages
|
|
44
53
|
identify that path with `source: "authoritative_history"`.
|
|
54
|
+
Writers without SQLite use the same pending and committed invalidation protocol,
|
|
55
|
+
so a later Node writer cannot certify a cache that omitted their facts.
|
|
56
|
+
Incremental writes also verify the previous size receipt before advancing it,
|
|
57
|
+
so merged history cannot be hidden by a later append. Upgraded runtimes rebuild
|
|
58
|
+
legacy projections that could contain omitted facts with apparently current
|
|
59
|
+
receipts; authoritative history does not require a format migration.
|
|
60
|
+
|
|
61
|
+
Index readers take a synchronous SQLite read transaction containing both event
|
|
62
|
+
rows and their stream-size receipts, then close the database before checking
|
|
63
|
+
authoritative files. They acquire neither history-index writer lock. File
|
|
64
|
+
identity and write timestamps, authoritative stream sizes, and pending or
|
|
65
|
+
committed invalidations must still match before a snapshot is returned. A
|
|
66
|
+
concurrent change refuses the optional snapshot; it cannot certify older rows
|
|
67
|
+
using a newer size receipt.
|
|
68
|
+
|
|
69
|
+
Incremental projection writes also use a zero SQLite busy timeout. Native
|
|
70
|
+
reader or writer contention falls back to the authoritative append and
|
|
71
|
+
invalidation protocol instead of spending a separate SQLite wait budget.
|
|
72
|
+
An unexpired, token-owned append lease marks ordinary incremental work as
|
|
73
|
+
active until its commit or invalidation completes. Native contention retains
|
|
74
|
+
the cache file and a committed contention marker; a zero-wait native probe
|
|
75
|
+
distinguishes an ongoing contender from settled damage before requesting repair.
|
|
76
|
+
|
|
77
|
+
Authoritative writers fail fast when an active owner holds the projection writer
|
|
78
|
+
lock, including when a full repair owns it. They publish an invalidation instead.
|
|
79
|
+
Stale-owner recovery follows the built-in lock policy. A repair
|
|
80
|
+
refuses publication if those markers changed during its scan. Full projection
|
|
81
|
+
construction yields between batches, and marker cleanup occurs outside the
|
|
82
|
+
short invalidation publication lock.
|
|
83
|
+
After a refused full publication or failed repair, a best effort per-tracker runtime receipt
|
|
84
|
+
defers automatic repair for five seconds. Busy periods therefore do not restart
|
|
85
|
+
a complete SQLite build on every read. Pages and recency reads continue using
|
|
86
|
+
authoritative history; after the cooldown, a later read can repair during a
|
|
87
|
+
quiet interval. This backoff bounds repair frequency, not index availability
|
|
88
|
+
during continuous writes.
|
|
89
|
+
|
|
90
|
+
Transient generation changes and SQLite contention use authoritative fallback
|
|
91
|
+
directly. Missing, incompatible, or damaged projections receive one optional
|
|
92
|
+
repair attempt without waiting for either projection lock. Repair failure or
|
|
93
|
+
invalidation after rebuilding
|
|
94
|
+
falls back to authoritative JSONL with the same filters and cursor format.
|
|
95
|
+
Pages may change `source` between calls. A fallback still reports malformed or
|
|
96
|
+
inaccessible authoritative history as an error. A successful repair may scan
|
|
97
|
+
the workspace; this protocol bounds lock waiting, not total execution time.
|
|
45
98
|
|
|
46
99
|
`--full` also includes the complete authoritative history entry.
|
|
47
100
|
`--type`, `--author`, and `--item` accept repeatable or comma-separated values.
|
|
@@ -109,10 +162,7 @@ Package authors can query the same scorer used by create/copy and the bundled
|
|
|
109
162
|
governance audit:
|
|
110
163
|
|
|
111
164
|
```ts
|
|
112
|
-
import {
|
|
113
|
-
findSimilarItems,
|
|
114
|
-
scoreItemSimilarity,
|
|
115
|
-
} from "@unbrained/pm-cli/sdk";
|
|
165
|
+
import { findSimilarItems, scoreItemSimilarity } from "@unbrained/pm-cli/sdk";
|
|
116
166
|
|
|
117
167
|
const score = scoreItemSimilarity("Fix OAuth refresh", "Fix oauth refresh");
|
|
118
168
|
const matches = await findSimilarItems(
|
|
@@ -155,6 +205,20 @@ accepted aliases for existing automation.
|
|
|
155
205
|
|
|
156
206
|
## Scale contract
|
|
157
207
|
|
|
208
|
+
The mixed-reader acceptance used 100 fixed-boundary snapshot observers,
|
|
209
|
+
five SDK writer lanes, and five CLI writer lanes, with five updates per lane.
|
|
210
|
+
Both separate traced and untraced cohorts passed 5,000 unique observations,
|
|
211
|
+
duplicate-free pages, strict history integrity, and a 2,000 ms first-observation
|
|
212
|
+
ceiling. These are bounded host measurements recorded in
|
|
213
|
+
[pm-gh1485](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-gh1485.toon).
|
|
214
|
+
|
|
215
|
+
The native regression suspends filesystem validation and requires an
|
|
216
|
+
authoritative writer to finish before that reader resumes. Run it with:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
node scripts/run-tests.mjs test -- tests/unit/core/history/event-index-snapshots.spec.ts
|
|
220
|
+
```
|
|
221
|
+
|
|
158
222
|
Event catch-up reads from a persistent ordered projection and follows only new
|
|
159
223
|
rows. Similarity governance is zero-cost when off and index-bounded when
|
|
160
224
|
enabled on an indexed workspace. Production bundles are syntax-, whitespace-,
|