@unbrained/pm-cli 2026.8.21 → 2026.8.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +44 -0
- package/dist/cli/error-guidance.d.ts +22 -4
- package/dist/cli/error-guidance.js +73 -16
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.js +51 -9
- package/dist/cli/register-mutation.js +6 -6
- package/dist/cli/register-operations.d.ts +73 -0
- package/dist/cli/register-operations.js +39 -14
- package/dist/cli/register-setup.js +3 -3
- package/dist/cli/schema-registration-helpers.d.ts +8 -1
- package/dist/cli/schema-registration-helpers.js +14 -5
- package/dist/cli-bundle/bundle-manifest.json +149 -149
- package/dist/cli-bundle/chunks/chunk-3ENVHX6C.js +36 -0
- package/dist/cli-bundle/chunks/{chunk-LOVTQ52Z.js → chunk-DW2CGEMU.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-EG6CLDZT.js +5 -0
- package/dist/cli-bundle/chunks/{chunk-LARJJ3RK.js → chunk-F3AI2JFL.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-N3DSV4CH.js → chunk-HWZ6CELB.js} +8 -8
- package/dist/cli-bundle/chunks/chunk-HZBMLSZI.js +201 -0
- package/dist/cli-bundle/chunks/chunk-JB4KZWBF.js +3 -0
- package/dist/cli-bundle/chunks/chunk-KPH73XXJ.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-BKYB45NQ.js → chunk-KXPMB2YL.js} +50 -50
- package/dist/cli-bundle/chunks/{chunk-BUNIEJNE.js → chunk-QDVHNHAQ.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-TFI5V5N2.js +13 -0
- package/dist/cli-bundle/chunks/{register-list-query-F57EWDEF.js → register-list-query-UJB5FMV2.js} +2 -2
- package/dist/cli-bundle/chunks/register-mutation-NX5XE4VX.js +20 -0
- package/dist/cli-bundle/chunks/register-operations-RXIJIYXC.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-HXU7IZZD.js → register-setup-GFUZEKRE.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-F4YEW5I2.js → chunk-37Z4OEAP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-3UPTYG44.js +8 -0
- package/dist/cli-bundle/focused-chunks/chunk-5S7E72FY.js +16 -0
- package/dist/cli-bundle/focused-chunks/{chunk-4ERLO7QD.js → chunk-AUFH5H35.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-E7X25GC3.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-FQCSTBWE.js +4 -0
- package/dist/cli-bundle/focused-chunks/{chunk-FH6DYED3.js → chunk-FZS4H32O.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-IFLWKY2R.js +156 -0
- package/dist/cli-bundle/focused-chunks/{chunk-YKBKIEAJ.js → chunk-JOWDB2MH.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-LYVSW5VM.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-MRCNF3U6.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-UZE7XUZK.js → chunk-OFVUGTLJ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-FJ22HNRP.js → chunk-OGLQBL46.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-OY7QAV4Y.js +51 -0
- package/dist/cli-bundle/focused-chunks/chunk-QGFNI65N.js +26 -0
- package/dist/cli-bundle/focused-chunks/{chunk-KDNG7TKQ.js → chunk-R27IDGHD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-UYRFYCDQ.js +5 -0
- package/dist/cli-bundle/focused-chunks/{chunk-2NIY5NKG.js → chunk-ZHVA42R5.js} +9 -9
- package/dist/cli-bundle/main.js +13 -13
- 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 +40 -40
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +33 -32
- 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 +5 -5
- package/dist/core/config/nested-settings.js +8 -2
- package/dist/core/config/positional-value.d.ts +1 -1
- package/dist/core/config/positional-value.js +5 -2
- package/dist/core/extensions/extension-hook-runtime.js +22 -20
- package/dist/core/extensions/extension-types.d.ts +8 -1
- package/dist/core/extensions/extension-types.js +2 -2
- package/dist/core/extensions/loader.js +7 -3
- package/dist/core/extensions/service-ownership.d.ts +8 -0
- package/dist/core/extensions/service-ownership.js +20 -0
- package/dist/core/history/history.js +3 -3
- package/dist/core/item/id.js +20 -5
- package/dist/core/item/item-format.js +81 -2
- package/dist/core/reproducibility/context.d.ts +4 -0
- package/dist/core/reproducibility/context.js +14 -8
- package/dist/core/shared/author.d.ts +55 -1
- package/dist/core/shared/author.js +333 -16
- package/dist/core/shared/constants.js +3 -2
- package/dist/core/shared/errors.d.ts +4 -0
- package/dist/core/shared/errors.js +2 -2
- package/dist/core/store/settings-validator.d.ts +1 -0
- package/dist/core/store/settings-validator.js +6 -3
- package/dist/core/store/settings.js +5 -2
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +30 -9
- package/dist/sdk/agent/identity-config.d.ts +63 -0
- package/dist/sdk/agent/identity-config.js +107 -0
- package/dist/sdk/agent/refusal-corpus-contracts.d.ts +76 -0
- package/dist/sdk/agent/refusal-corpus-contracts.js +194 -0
- package/dist/sdk/agent/refusal-reachability.d.ts +1 -1
- package/dist/sdk/authoring.d.ts +1 -1
- package/dist/sdk/authoring.js +2 -2
- package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +77 -0
- package/dist/sdk/cli-contracts/agent-output-contracts.js +326 -2
- package/dist/sdk/cli-contracts/commander-mutation-options.js +3 -3
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +4 -0
- package/dist/sdk/cli-contracts/enum-contracts.js +9 -2
- package/dist/sdk/cli-contracts/flag-contracts.js +9 -2
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +4 -4
- package/dist/sdk/cli-contracts/registration-helpers.js +5 -2
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +3 -1
- package/dist/sdk/cli-contracts/runtime-contracts.js +4 -3
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +22 -2
- package/dist/sdk/cli-contracts/tool-schema.d.ts +1 -1
- package/dist/sdk/cli-contracts/tool-schema.js +14 -3
- package/dist/sdk/cli-contracts.d.ts +4 -4
- package/dist/sdk/cli-contracts.js +5 -5
- package/dist/sdk/config.d.ts +6 -1
- package/dist/sdk/config.js +119 -14
- package/dist/sdk/context-intent-contracts.js +4 -2
- package/dist/sdk/core-governance.d.ts +1 -1
- package/dist/sdk/core-governance.js +3 -3
- package/dist/sdk/extension/install-sources.d.ts +1 -1
- package/dist/sdk/extension/install-sources.js +6 -3
- package/dist/sdk/extension/output-ownership.d.ts +1 -0
- package/dist/sdk/extension/output-ownership.js +3 -2
- package/dist/sdk/extension/scaffold.js +11 -5
- package/dist/sdk/flag-invocation-contracts.js +4 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +74 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +87 -26
- package/dist/sdk/governance/assurance-action.js +30 -10
- package/dist/sdk/governance/health.d.ts +3 -0
- package/dist/sdk/governance/health.js +39 -7
- package/dist/sdk/governance/hierarchy-validation.d.ts +29 -0
- package/dist/sdk/governance/hierarchy-validation.js +109 -0
- package/dist/sdk/governance/validate.d.ts +3 -9
- package/dist/sdk/governance/validate.js +84 -111
- package/dist/sdk/graph/assembly.d.ts +6 -1
- package/dist/sdk/graph/assembly.js +16 -22
- package/dist/sdk/graph/governance-contracts.d.ts +1 -1
- package/dist/sdk/graph/governance-contracts.js +8 -2
- package/dist/sdk/graph/governance.js +46 -2
- package/dist/sdk/graph/hierarchy-integrity.d.ts +94 -0
- package/dist/sdk/graph/hierarchy-integrity.js +311 -0
- package/dist/sdk/graph/index.d.ts +2 -1
- package/dist/sdk/graph/index.js +3 -2
- package/dist/sdk/graph/remediation.js +32 -2
- package/dist/sdk/graph/run.d.ts +31 -2
- package/dist/sdk/graph/run.js +80 -31
- package/dist/sdk/graph/workspace-relationship-kind-registry.d.ts +8 -0
- package/dist/sdk/graph/workspace-relationship-kind-registry.js +28 -0
- package/dist/sdk/index.d.ts +8 -3
- package/dist/sdk/index.js +9 -4
- package/dist/sdk/item-children.js +21 -8
- package/dist/sdk/lifecycle/create.js +129 -97
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.d.ts +15 -0
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +25 -0
- package/dist/sdk/lifecycle/update.d.ts +2 -0
- package/dist/sdk/lifecycle/update.js +174 -84
- package/dist/sdk/merge/three-way.js +105 -26
- package/dist/sdk/query/complete-list.d.ts +3 -3
- package/dist/sdk/query/complete-list.js +46 -3
- package/dist/sdk/query/list.d.ts +4 -3
- package/dist/sdk/query/list.js +89 -49
- package/dist/sdk/read-output-budget.d.ts +21 -0
- package/dist/sdk/read-output-budget.js +39 -2
- package/dist/sdk/read-output-contracts.d.ts +10 -4
- package/dist/sdk/read-output-contracts.js +105 -32
- package/dist/sdk/relationship-context.js +3 -4
- package/dist/sdk/relationships.js +17 -10
- package/dist/sdk/reproducibility/process.d.ts +19 -0
- package/dist/sdk/reproducibility/process.js +88 -0
- package/dist/sdk/runtime-primitives.d.ts +1 -1
- package/dist/sdk/runtime-primitives.js +3 -3
- package/dist/sdk/runtime.d.ts +3 -2
- package/dist/sdk/runtime.js +7 -5
- package/dist/sdk/test/batch.d.ts +6 -0
- package/dist/sdk/test/batch.js +26 -6
- package/dist/sdk/test/entry.d.ts +1 -1
- package/dist/sdk/test/entry.js +3 -2
- package/dist/sdk/test/execution.d.ts +28 -3
- package/dist/sdk/test/execution.js +201 -34
- package/dist/sdk/test/parsers.d.ts +6 -0
- package/dist/sdk/test/parsers.js +21 -2
- package/dist/sdk/test/trust.d.ts +33 -0
- package/dist/sdk/test/trust.js +207 -0
- package/dist/types.d.ts +34 -0
- package/dist/types.js +2 -2
- package/docs/AGENT_PROVENANCE_ADR.md +41 -5
- package/docs/AGENT_UX_CONTRACTS.md +20 -4
- package/docs/COMMANDS.md +29 -14
- package/docs/CONFIGURATION.md +4 -0
- package/docs/DEPENDENCY_KIND_CONTRACT.md +31 -3
- package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +115 -0
- package/docs/EXTENSIONS.md +2 -1
- package/docs/MERGE_SAFETY.md +15 -1
- package/docs/README.md +1 -0
- package/docs/READ_OUTPUT_CONTRACTS.md +19 -2
- package/docs/RELATIONSHIP_GRAPH.md +6 -3
- package/docs/REPRODUCIBLE_WORKSPACES.md +42 -8
- package/docs/SDK.md +9 -0
- package/docs/SDK_AGENT_SESSION_CONTEXT.md +6 -4
- package/docs/SDK_EVIDENCE_TRACEABILITY.md +1 -1
- package/docs/TESTING.md +83 -1
- package/docs/agent-task-token-baseline.json +2 -2
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +2 -2
- package/marketplace.json +2 -2
- package/package.json +2 -2
- 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-codex/.codex-plugin/plugin.json +1 -1
- package/sdk/public-surface.json +1021 -53
- package/dist/cli-bundle/chunks/chunk-2MA6ZQVZ.js +0 -197
- package/dist/cli-bundle/chunks/chunk-3AFAUHUE.js +0 -2
- package/dist/cli-bundle/chunks/chunk-7VHZS727.js +0 -5
- package/dist/cli-bundle/chunks/chunk-JSLOFXGA.js +0 -3
- package/dist/cli-bundle/chunks/chunk-OCLPLFAY.js +0 -35
- package/dist/cli-bundle/chunks/chunk-S4IRYKBU.js +0 -13
- package/dist/cli-bundle/chunks/register-mutation-7IY2D5KO.js +0 -20
- package/dist/cli-bundle/chunks/register-operations-FALL3YTU.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-7WZRLCYF.js +0 -50
- package/dist/cli-bundle/focused-chunks/chunk-CKKQSJNN.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-EEFKYMDR.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-F2A56DHV.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-FV5ACOK7.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-JEAVFOWM.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-NJ63LOP6.js +0 -155
- package/dist/cli-bundle/focused-chunks/chunk-NXRTQ7HI.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-TJ7EMJ46.js +0 -4
- package/dist/cli-bundle/focused-chunks/chunk-ZOSEELYJ.js +0 -26
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/test/trust
|
|
3
|
+
*
|
|
4
|
+
* Provides provenance and clone-local trust decisions for stored linked-test
|
|
5
|
+
* commands. Tracker items remain portable while execution acknowledgements stay
|
|
6
|
+
* outside the merge-unioned project record.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="30a61f26-5db8-50ba-af37-1990a4742ce8")}catch(e){}}();
|
|
10
|
+
import { execFile } from "node:child_process";
|
|
11
|
+
import { readFile } from "node:fs/promises";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import { promisify } from "node:util";
|
|
14
|
+
import { ensureDir, writeFileAtomic, } from "../../core/fs/fs-utils.js";
|
|
15
|
+
import { sha256Hex, stableStringify } from "../../core/shared/serialization.js";
|
|
16
|
+
import { isTimestampLiteral } from "../../core/shared/time.js";
|
|
17
|
+
import { getRuntimePath } from "../../core/store/paths.js";
|
|
18
|
+
const execFileAsync = promisify(execFile);
|
|
19
|
+
const LINKED_TEST_TRUST_LEDGER_VERSION = 1;
|
|
20
|
+
const LINKED_TEST_TRUST_LEDGER_FILE = "linked-test-trust.json";
|
|
21
|
+
function trustLedgerPath(pmRoot) {
|
|
22
|
+
return path.join(getRuntimePath(pmRoot), LINKED_TEST_TRUST_LEDGER_FILE);
|
|
23
|
+
}
|
|
24
|
+
function emptyTrustLedger() {
|
|
25
|
+
return { version: LINKED_TEST_TRUST_LEDGER_VERSION, acknowledged: {} };
|
|
26
|
+
}
|
|
27
|
+
async function readTrustLedger(pmRoot) {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(await readFile(trustLedgerPath(pmRoot), "utf8"));
|
|
30
|
+
if (parsed.version !== LINKED_TEST_TRUST_LEDGER_VERSION ||
|
|
31
|
+
typeof parsed.acknowledged !== "object" ||
|
|
32
|
+
parsed.acknowledged === null ||
|
|
33
|
+
Array.isArray(parsed.acknowledged)) {
|
|
34
|
+
return emptyTrustLedger();
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
version: LINKED_TEST_TRUST_LEDGER_VERSION,
|
|
38
|
+
acknowledged: parsed.acknowledged,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// A missing, corrupt, or unreadable ledger grants no acknowledgements.
|
|
43
|
+
// The local/source-ref provenance checks remain independent of this file.
|
|
44
|
+
return emptyTrustLedger();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Resolve the current Git branch without invoking a shell. */
|
|
48
|
+
export async function resolveLinkedTestSourceRef(cwd = process.cwd()) {
|
|
49
|
+
const hostedRef = process.env.GITHUB_HEAD_REF?.trim() || process.env.GITHUB_REF_NAME?.trim();
|
|
50
|
+
if (hostedRef && hostedRef !== "merge") {
|
|
51
|
+
return hostedRef;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const { stdout } = await execFileAsync("git", ["symbolic-ref", "--quiet", "--short", "HEAD"], { cwd, encoding: "utf8", windowsHide: true, timeout: 10_000 });
|
|
55
|
+
const ref = stdout.trim();
|
|
56
|
+
/* c8 ignore start -- successful git symbolic-ref output is non-empty by contract */
|
|
57
|
+
if (ref.length === 0)
|
|
58
|
+
return undefined;
|
|
59
|
+
/* c8 ignore stop */
|
|
60
|
+
return ref;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Resolve the source checkout shared by linked-test provenance and execution. */
|
|
67
|
+
export function resolveLinkedTestSourceWorkspaceRoot(cwd = process.cwd()) {
|
|
68
|
+
return process.env.PM_SOURCE_WORKSPACE_ROOT?.trim() || cwd;
|
|
69
|
+
}
|
|
70
|
+
function hasValidLinkedTestProvenance(provenance) {
|
|
71
|
+
if (provenance === null || typeof provenance !== "object")
|
|
72
|
+
return false;
|
|
73
|
+
return (typeof provenance.author === "string" &&
|
|
74
|
+
provenance.author.trim().length > 0 &&
|
|
75
|
+
typeof provenance.created_at === "string" &&
|
|
76
|
+
isTimestampLiteral(provenance.created_at) &&
|
|
77
|
+
(provenance.source_kind === "local_mutation" ||
|
|
78
|
+
provenance.source_kind === "merge_union"));
|
|
79
|
+
}
|
|
80
|
+
/** Build the optional ref portion shared by clone-local trust decisions. */
|
|
81
|
+
function linkedTestTrustRefs(sourceRef, currentSourceRef) {
|
|
82
|
+
return {
|
|
83
|
+
...(sourceRef ? { source_ref: sourceRef } : {}),
|
|
84
|
+
...(currentSourceRef ? { current_source_ref: currentSourceRef } : {}),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Attach immutable author/time/ref provenance to newly stored commands. */
|
|
88
|
+
export function attachLinkedTestProvenance(tests, author, createdAt, sourceRef) {
|
|
89
|
+
return tests?.map((test) => test.command && !test.provenance
|
|
90
|
+
? {
|
|
91
|
+
...test,
|
|
92
|
+
provenance: {
|
|
93
|
+
author,
|
|
94
|
+
created_at: createdAt,
|
|
95
|
+
source_kind: "local_mutation",
|
|
96
|
+
...(sourceRef ? { source_ref: sourceRef } : {}),
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
: test);
|
|
100
|
+
}
|
|
101
|
+
/** Attach provenance while avoiding Git inspection for an empty mutation. */
|
|
102
|
+
export async function attachLinkedTestMutationProvenance(tests, author, createdAt) {
|
|
103
|
+
if (!tests || tests.length === 0)
|
|
104
|
+
return tests;
|
|
105
|
+
const sourceWorkspaceRoot = resolveLinkedTestSourceWorkspaceRoot();
|
|
106
|
+
return attachLinkedTestProvenance(tests, author, createdAt, await resolveLinkedTestSourceRef(sourceWorkspaceRoot));
|
|
107
|
+
}
|
|
108
|
+
/** Produce the clone-local trust identity for one linked-test entry. */
|
|
109
|
+
export function linkedTestTrustFingerprint(test) {
|
|
110
|
+
return sha256Hex(stableStringify({
|
|
111
|
+
command: test.command ?? null,
|
|
112
|
+
path: test.path ?? null,
|
|
113
|
+
scope: test.scope,
|
|
114
|
+
pm_context_mode: test.pm_context_mode ?? null,
|
|
115
|
+
workspace_context_mode: test.workspace_context_mode ?? null,
|
|
116
|
+
env_set: test.env_set ?? null,
|
|
117
|
+
env_clear: test.env_clear ?? null,
|
|
118
|
+
shared_host_safe: test.shared_host_safe ?? null,
|
|
119
|
+
provenance: test.provenance ?? null,
|
|
120
|
+
provenance_invalid: test.provenance_invalid ?? null,
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
/** Resolve whether one stored command is trusted by this clone. */
|
|
124
|
+
export async function resolveLinkedTestTrust(pmRoot, test, currentSourceRef) {
|
|
125
|
+
const ledger = await readTrustLedger(pmRoot);
|
|
126
|
+
return resolveLinkedTestTrustFromLedger(test, currentSourceRef, ledger);
|
|
127
|
+
}
|
|
128
|
+
function resolveLinkedTestTrustFromLedger(test, currentSourceRef, ledger) {
|
|
129
|
+
const fingerprint = linkedTestTrustFingerprint(test);
|
|
130
|
+
const sourceRef = test.provenance?.source_ref;
|
|
131
|
+
if (test.provenance === undefined &&
|
|
132
|
+
test.provenance_invalid !== true) {
|
|
133
|
+
return { fingerprint, trusted: true, reason: "legacy" };
|
|
134
|
+
}
|
|
135
|
+
const acknowledged = Object.hasOwn(ledger.acknowledged, fingerprint);
|
|
136
|
+
if (test.provenance_invalid === true ||
|
|
137
|
+
!hasValidLinkedTestProvenance(test.provenance)) {
|
|
138
|
+
if (acknowledged) {
|
|
139
|
+
return {
|
|
140
|
+
fingerprint,
|
|
141
|
+
trusted: true,
|
|
142
|
+
reason: "acknowledged",
|
|
143
|
+
...linkedTestTrustRefs(undefined, currentSourceRef),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
fingerprint,
|
|
148
|
+
trusted: false,
|
|
149
|
+
reason: "invalid_provenance",
|
|
150
|
+
...linkedTestTrustRefs(undefined, currentSourceRef),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (test.provenance.source_kind === "local_mutation" &&
|
|
154
|
+
sourceRef === undefined) {
|
|
155
|
+
return {
|
|
156
|
+
fingerprint,
|
|
157
|
+
trusted: true,
|
|
158
|
+
reason: "local_mutation",
|
|
159
|
+
...linkedTestTrustRefs(undefined, currentSourceRef),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
if (test.provenance.source_kind === "local_mutation" &&
|
|
163
|
+
sourceRef !== undefined &&
|
|
164
|
+
sourceRef === currentSourceRef) {
|
|
165
|
+
return {
|
|
166
|
+
fingerprint,
|
|
167
|
+
trusted: true,
|
|
168
|
+
reason: "local_source_ref",
|
|
169
|
+
source_ref: sourceRef,
|
|
170
|
+
current_source_ref: currentSourceRef,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (acknowledged) {
|
|
174
|
+
return {
|
|
175
|
+
fingerprint,
|
|
176
|
+
trusted: true,
|
|
177
|
+
reason: "acknowledged",
|
|
178
|
+
...linkedTestTrustRefs(sourceRef, currentSourceRef),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
fingerprint,
|
|
183
|
+
trusted: false,
|
|
184
|
+
reason: "foreign_source_ref",
|
|
185
|
+
...linkedTestTrustRefs(sourceRef, currentSourceRef),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/** Resolve a collection with one ledger read for validation and batch runs. */
|
|
189
|
+
export async function resolveLinkedTestTrustBatch(pmRoot, tests, currentSourceRef) {
|
|
190
|
+
const ledger = await readTrustLedger(pmRoot);
|
|
191
|
+
return tests.map((test) => resolveLinkedTestTrustFromLedger(test, currentSourceRef, ledger));
|
|
192
|
+
}
|
|
193
|
+
/** Persist explicit clone-local acknowledgement for selected linked tests. */
|
|
194
|
+
export async function acknowledgeLinkedTests(pmRoot, tests, acknowledgedAt) {
|
|
195
|
+
const ledger = await readTrustLedger(pmRoot);
|
|
196
|
+
const fingerprints = tests
|
|
197
|
+
.filter((test) => typeof test.command === "string" && test.command.length > 0)
|
|
198
|
+
.map(linkedTestTrustFingerprint);
|
|
199
|
+
for (const fingerprint of fingerprints) {
|
|
200
|
+
ledger.acknowledged[fingerprint] = { acknowledged_at: acknowledgedAt };
|
|
201
|
+
}
|
|
202
|
+
await ensureDir(path.dirname(trustLedgerPath(pmRoot)));
|
|
203
|
+
await writeFileAtomic(trustLedgerPath(pmRoot), `${JSON.stringify(ledger, null, 2)}\n`);
|
|
204
|
+
return { acknowledged: fingerprints.length, fingerprints };
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=trust.js.map
|
|
207
|
+
//# debugId=30a61f26-5db8-50ba-af37-1990a4742ce8
|
package/dist/types.d.ts
CHANGED
|
@@ -166,6 +166,17 @@ export interface LinkedFile {
|
|
|
166
166
|
/** Value that configures or reports note for this contract. */
|
|
167
167
|
note?: string;
|
|
168
168
|
}
|
|
169
|
+
/** Valid immutable provenance captured when a linked command enters tracker data. */
|
|
170
|
+
export interface LinkedTestProvenance {
|
|
171
|
+
/** Author identity recorded by the originating mutation. */
|
|
172
|
+
author: string;
|
|
173
|
+
/** ISO 8601 time at which the command entered tracker data. */
|
|
174
|
+
created_at: string;
|
|
175
|
+
/** Mutation path that introduced the command. */
|
|
176
|
+
source_kind: "local_mutation" | "merge_union";
|
|
177
|
+
/** Best-effort Git branch or hosted head ref of the originating mutation. */
|
|
178
|
+
source_ref?: string;
|
|
179
|
+
}
|
|
169
180
|
/** Documents the linked test payload exchanged by command, SDK, and package integrations. */
|
|
170
181
|
export interface LinkedTest {
|
|
171
182
|
/** Value that configures or reports command for this contract. */
|
|
@@ -178,6 +189,12 @@ export interface LinkedTest {
|
|
|
178
189
|
timeout_seconds?: number;
|
|
179
190
|
/** Strategy used to control pm context behavior. */
|
|
180
191
|
pm_context_mode?: "schema" | "tracker" | "auto";
|
|
192
|
+
/** Strategy used for source-workspace visibility and command working directory. */
|
|
193
|
+
workspace_context_mode?: "source" | "isolated" | "snapshot";
|
|
194
|
+
/** Immutable provenance captured when the linked command enters tracker data. */
|
|
195
|
+
provenance?: LinkedTestProvenance;
|
|
196
|
+
/** Explicit fail-closed marker retained when stored provenance is malformed. */
|
|
197
|
+
provenance_invalid?: true;
|
|
181
198
|
/** Value that configures or reports env set for this contract. */
|
|
182
199
|
env_set?: Record<string, string>;
|
|
183
200
|
/** Value that configures or reports env clear for this contract. */
|
|
@@ -558,6 +575,19 @@ export interface TestRunMeasurement {
|
|
|
558
575
|
/** ISO 8601 timestamp binding the measurement to its producing run. */
|
|
559
576
|
recorded_at: string;
|
|
560
577
|
}
|
|
578
|
+
/** Bounded command and tracker-context provenance for one linked-test execution. */
|
|
579
|
+
export interface ItemTestRunExecution {
|
|
580
|
+
/** Exact linked command selected for execution. */
|
|
581
|
+
command: string;
|
|
582
|
+
/** Context mode requested before linked-test overrides or auto-remediation. */
|
|
583
|
+
requested_pm_context_mode?: "schema" | "tracker" | "auto";
|
|
584
|
+
/** Effective context mode used by the linked command. */
|
|
585
|
+
pm_context_mode?: "schema" | "tracker" | "auto";
|
|
586
|
+
/** Effective source-workspace mode used by the linked command. */
|
|
587
|
+
workspace_context_mode?: "source" | "isolated" | "snapshot";
|
|
588
|
+
/** Trust classification applied before execution. */
|
|
589
|
+
trust_reason?: "legacy" | "local_mutation" | "local_source_ref" | "acknowledged" | "invalid_provenance" | "foreign_source_ref";
|
|
590
|
+
}
|
|
561
591
|
/** Documents the item test run summary payload exchanged by command, SDK, and package integrations. */
|
|
562
592
|
export interface ItemTestRunSummary {
|
|
563
593
|
/** Executes the id operation through the package runtime. */
|
|
@@ -590,6 +620,8 @@ export interface ItemTestRunSummary {
|
|
|
590
620
|
fail_on_skipped_triggered?: boolean;
|
|
591
621
|
/** Bounded, deterministic quantitative evidence produced by this run. */
|
|
592
622
|
measurements?: TestRunMeasurement[];
|
|
623
|
+
/** Commands and effective tracker contexts bound to this recorded run. */
|
|
624
|
+
executions?: ItemTestRunExecution[];
|
|
593
625
|
}
|
|
594
626
|
/** Documents the item metadata payload exchanged by command, SDK, and package integrations. */
|
|
595
627
|
export interface ItemMetadata {
|
|
@@ -1110,6 +1142,8 @@ export interface PmSettings {
|
|
|
1110
1142
|
/** Value that configures or reports testing for this contract. */
|
|
1111
1143
|
testing: {
|
|
1112
1144
|
record_results_to_items: boolean;
|
|
1145
|
+
/** Permit explicit one-shot execution of commands not yet trusted by this clone. */
|
|
1146
|
+
allow_untrusted_linked_tests: boolean;
|
|
1113
1147
|
};
|
|
1114
1148
|
/** Value that configures or reports telemetry for this contract. */
|
|
1115
1149
|
telemetry: {
|
package/dist/types.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
/** Supported values accepted by the builtin item type contract. */
|
|
7
7
|
|
|
8
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
8
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="64223a83-1287-57ac-915d-dbd5e375a6eb")}catch(e){}}();
|
|
9
9
|
export const BUILTIN_ITEM_TYPE_VALUES = [
|
|
10
10
|
"Epic",
|
|
11
11
|
"Feature",
|
|
@@ -243,4 +243,4 @@ export const CONTEXT_SECTION_VALUES = [
|
|
|
243
243
|
"tests",
|
|
244
244
|
];
|
|
245
245
|
//# sourceMappingURL=types.js.map
|
|
246
|
-
//# debugId=
|
|
246
|
+
//# debugId=64223a83-1287-57ac-915d-dbd5e375a6eb
|
|
@@ -10,7 +10,10 @@ Implementation lineage:
|
|
|
10
10
|
resolution and patch-free historical reads implemented by
|
|
11
11
|
[pm-ffz0a9](../.agents/pm/issues/pm-ffz0a9.toon),
|
|
12
12
|
[pm-v8gfi7](../.agents/pm/issues/pm-v8gfi7.toon), and
|
|
13
|
-
[pm-3yxwv5](../.agents/pm/issues/pm-3yxwv5.toon).
|
|
13
|
+
[pm-3yxwv5](../.agents/pm/issues/pm-3yxwv5.toon). Cross-harness adapters and
|
|
14
|
+
operator-managed probe/vocabulary controls are tracked by
|
|
15
|
+
[pm-c0lrdm](../.agents/pm/features/pm-c0lrdm.toon) and
|
|
16
|
+
[pm-yds9dt](../.agents/pm/chores/pm-yds9dt.toon).
|
|
14
17
|
|
|
15
18
|
Status: accepted amendment to
|
|
16
19
|
[pm-qwuber](../.agents/pm/decisions/pm-qwuber.toon). The original stable-author
|
|
@@ -51,10 +54,13 @@ Provenance values are descriptive context, never authentication or
|
|
|
51
54
|
authorization principals. Values are trimmed, length-bounded, and obtained only
|
|
52
55
|
from literal descriptor keys, trusted caller data, or a named bounded resolver.
|
|
53
56
|
Detection does not spawn processes, traverse process trees, evaluate user
|
|
54
|
-
regexes, or access the network. The built-in Claude
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
regexes, or access the network. The built-in Claude and Codex resolvers read
|
|
58
|
+
only bounded windows of the current session's harness-owned JSONL file. Claude
|
|
59
|
+
uses the recent tail to recover its recorded model/version. Codex uses the
|
|
60
|
+
recent tail plus a bounded initial-head fallback for oversized sessions to
|
|
61
|
+
recover allow-listed `turn_context.model` and `turn_context.effort` values.
|
|
62
|
+
Both cap traversal, file bytes, lines, and line length, ignore all other fields,
|
|
63
|
+
never follow symlinks, and fail closed. `agent_identity.probes_enabled` or
|
|
58
64
|
`PM_AGENT_PROBES=off` disables every local resolver without disabling ordinary
|
|
59
65
|
environment, argv, client, or host detection.
|
|
60
66
|
|
|
@@ -113,6 +119,11 @@ fabricate precision that was never captured.
|
|
|
113
119
|
The aggregate and core SDK entrypoints export:
|
|
114
120
|
|
|
115
121
|
- `AGENT_PROVENANCE_DIMENSIONS`;
|
|
122
|
+
- `BUILTIN_AGENT_PROVENANCE_ADAPTERS`,
|
|
123
|
+
`listAgentProvenanceAdapters()`, and
|
|
124
|
+
`registerAgentProvenanceAdapters()`;
|
|
125
|
+
- `normalizeAgentProvenanceAdapterValue()` for stable model-family and effort
|
|
126
|
+
vocabulary projections that retain the bounded raw observation;
|
|
116
127
|
- `detectAgentIdentity()` and `detectHarnessIdentity()`;
|
|
117
128
|
- `analyzeAgentProvenanceDescriptorCoverage()` for the descriptor capability
|
|
118
129
|
matrix and negative controls;
|
|
@@ -138,6 +149,31 @@ Legacy author interpretation is workspace-owned data under
|
|
|
138
149
|
version and whether a harness was `recorded`, resolved by `vocabulary`, or
|
|
139
150
|
remains `unresolved`; immutable authors and hashes are never rewritten.
|
|
140
151
|
|
|
152
|
+
`pm config get agent-identity-vocabulary`, `config list`, and `config export`
|
|
153
|
+
publish only its `version` and `alias_count`. Typed mutations use the existing
|
|
154
|
+
config transport:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
pm config set agent-identity-probes-enabled false
|
|
158
|
+
pm config set agent-identity-vocabulary --policy preview-add \
|
|
159
|
+
--value "Legacy Codex=codex" --criterion "Legacy Codex" --criterion "Alice"
|
|
160
|
+
pm config set agent-identity-vocabulary --policy add \
|
|
161
|
+
--value "Legacy Codex=codex"
|
|
162
|
+
pm config set agent-identity-vocabulary --policy remove --value "Legacy Codex"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
`preview-*` policies perform no write and report the exact residual unique
|
|
166
|
+
author count without returning author spellings. Real add/remove/clear changes
|
|
167
|
+
bump the vocabulary revision once; identical adds and absent removes are
|
|
168
|
+
idempotent. Aliases for already canonical `harness:<name>` authors fail closed.
|
|
169
|
+
|
|
170
|
+
Every built-in interactive harness has a contract-versioned adapter with an
|
|
171
|
+
implementation version, priority, covered dimensions, source classes,
|
|
172
|
+
normalization revisions, confidence, waivers, and immutable probe bounds.
|
|
173
|
+
Packages may register a new namespace or explicitly replace a built-in only at
|
|
174
|
+
a higher priority. Equal-priority ambiguity and descriptor mismatch fail
|
|
175
|
+
closed, and the disposer restores the prior adapter.
|
|
176
|
+
|
|
141
177
|
The SDK/CLI matrix classifies every input as shared, positional, transport,
|
|
142
178
|
presentation, local adapter, scope selector, compatibility alias, or SDK-native.
|
|
143
179
|
An unknown CLI flag fails closed as `unclassified`. Committed test baselines cap
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Agent UX Contracts
|
|
2
2
|
|
|
3
|
-
Tracker references: [pm-v1yo](../.agents/pm/issues/pm-v1yo.toon), [pm-i6pi](../.agents/pm/issues/pm-i6pi.toon), [pm-um4g](../.agents/pm/issues/pm-um4g.toon), [pm-tmhs](../.agents/pm/issues/pm-tmhs.toon), [pm-6m1i](../.agents/pm/issues/pm-6m1i.toon), [pm-cj9v](../.agents/pm/issues/pm-cj9v.toon), [pm-yp56](../.agents/pm/issues/pm-yp56.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon),
|
|
3
|
+
Tracker references: [pm-v1yo](../.agents/pm/issues/pm-v1yo.toon), [pm-i6pi](../.agents/pm/issues/pm-i6pi.toon), [pm-um4g](../.agents/pm/issues/pm-um4g.toon), [pm-tmhs](../.agents/pm/issues/pm-tmhs.toon), [pm-6m1i](../.agents/pm/issues/pm-6m1i.toon), [pm-cj9v](../.agents/pm/issues/pm-cj9v.toon), [pm-yp56](../.agents/pm/issues/pm-yp56.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon), [pm-flnefm](../.agents/pm/issues/pm-flnefm.toon), [pm-rggtvd](../.agents/pm/issues/pm-rggtvd.toon), and [pm-vk7zek](../.agents/pm/issues/pm-vk7zek.toon).
|
|
4
4
|
|
|
5
5
|
These contracts keep common agent loops deterministic, token-efficient, and recoverable. Runtime contracts and `--help --json` remain the exact source for available flags.
|
|
6
6
|
|
|
@@ -13,9 +13,25 @@ The public SDK exports `collectNewOrderingCycleWarnings(beforeItems, afterItems,
|
|
|
13
13
|
Dependency removal is lossless. `--dep-remove` rejects the same malformed
|
|
14
14
|
shorthand as `--dep`, and a selector that matches nothing returns the typed
|
|
15
15
|
`dependency_remove_no_match` refusal instead of a successful no-op. Exact
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
rows can be retired by selecting `id`, `kind` (or its input-only `type` alias),
|
|
17
|
+
`source_kind`, `author`, and `created_at`; omitted coordinates intentionally broaden the match. Exact
|
|
18
|
+
duplicate rows can still be normalized without delete-then-add risk by
|
|
19
|
+
re-adding the same identity; the mutation keeps one canonical row and never
|
|
20
|
+
removes the logical edge. Identity comparison includes normalized `id`, `kind`,
|
|
21
|
+
`source_kind`, `author`, and creation instant, preserving provenance-distinct
|
|
22
|
+
siblings.
|
|
23
|
+
|
|
24
|
+
Hierarchy mutations are stricter than ordering advisories. `pm create` and
|
|
25
|
+
`pm update` refuse a new cycle, registry cardinality breach, or contradictory
|
|
26
|
+
scalar/dependency parent before writing. The structured refusal names the
|
|
27
|
+
changed holder plus the cycle members or competing parents. Existing legacy
|
|
28
|
+
debt remains mutable only toward a cleaner state, so repair does not require a
|
|
29
|
+
global bypass. Read paths canonicalize every registry-declared hierarchy kind;
|
|
30
|
+
an item cannot disappear from `pm list --parent` or `pm get --tree` merely
|
|
31
|
+
because an integration used a dependency row instead of the scalar field.
|
|
32
|
+
`pm update-many` applies the same hierarchy guard independently to each matched
|
|
33
|
+
item: one refused row is reported as failed while other rows may still commit,
|
|
34
|
+
so a bulk hierarchy mutation is not atomic across the complete match set.
|
|
19
35
|
|
|
20
36
|
`pm graph audit` uses two explicit units:
|
|
21
37
|
|
package/docs/COMMANDS.md
CHANGED
|
@@ -6,6 +6,8 @@ Tracked implementation updates: [pm-52eh](../.agents/pm/features/pm-52eh.toon),
|
|
|
6
6
|
|
|
7
7
|
Workspace-integrity contracts are tracked by [pm-22rzjp](../.agents/pm/issues/pm-22rzjp.toon), [pm-76fkpp](../.agents/pm/issues/pm-76fkpp.toon), [pm-igdvfq](../.agents/pm/issues/pm-igdvfq.toon), [pm-643e0k](../.agents/pm/issues/pm-643e0k.toon), and [pm-larv4r](../.agents/pm/issues/pm-larv4r.toon).
|
|
8
8
|
|
|
9
|
+
Create-safe init prefix normalization is tracked by [pm-gh1073](../.agents/pm/issues/pm-gh1073.toon).
|
|
10
|
+
|
|
9
11
|
```bash
|
|
10
12
|
pm <command> --help
|
|
11
13
|
pm <command> --help --json
|
|
@@ -49,21 +51,21 @@ JSON ceiling; TOON uses the smaller default agent ceiling.
|
|
|
49
51
|
|
|
50
52
|
## Command Families
|
|
51
53
|
|
|
52
|
-
| Family | Commands
|
|
53
|
-
| ------------ |
|
|
54
|
-
| Bootstrap | `init`, `config`, `health`, `telemetry`
|
|
54
|
+
| Family | Commands | Purpose |
|
|
55
|
+
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
56
|
+
| Bootstrap | `init`, `config`, `health`, `telemetry` | create and inspect tracker setup |
|
|
55
57
|
| Lifecycle | `create`, `copy`, `focus`, `claim`, `update`, `item reopen`, `append`, `close`, `release`, `delete`, `start-task`, `pause-task`, `close-task` | mutate item state, including terminal-work recurrence without duplicate creation |
|
|
56
|
-
| Bulk | `item mutate`, `item complete`, `update-many`, `close-many`
|
|
57
|
-
| Scheduling | `meet`, `event`, `remind`
|
|
58
|
-
| Planning | `plan create`, `plan add-step`, `plan update-step`, `plan complete-step`, `plan link`, `plan approve`, `plan materialize`
|
|
59
|
-
| Links | `files`, `docs`, `test`, `deps`
|
|
60
|
-
| Verification | `test`, `test-all`, `test-runs`†, `validate`, `gc`
|
|
61
|
-
| History | `history`, `history-compact`, `history-redact`, `history-repair`, `activity`, `restore`, `stats`
|
|
62
|
-
| Schema | `schema add/remove-*` / `rename-type` / `rename-field` / `remap-status` / `apply-preset`
|
|
63
|
-
| Profiles | `profile list` / `show` / `apply` / `lint`
|
|
64
|
-
| Calendar | `calendar`, `cal`
|
|
65
|
-
| Packages | `install`, `upgrade`, `package`, `packages`, `extension`, package/extension command groups
|
|
66
|
-
| Machines | `contracts`, `help`, optional `guide`/`completion`
|
|
58
|
+
| Bulk | `item mutate`, `item complete`, `update-many`, `close-many` | atomically commit heterogeneous SDK mutation batches or evidence-backed completion, or apply one change across a matched, dry-run-previewed set with a rollback checkpoint |
|
|
59
|
+
| Scheduling | `meet`, `event`, `remind` | low-friction Meeting/Event/Reminder creation |
|
|
60
|
+
| Planning | `plan create`, `plan add-step`, `plan update-step`, `plan complete-step`, `plan link`, `plan approve`, `plan materialize` | agent-optimized living plans with ordered steps, evidence, decisions, validation, and materialization |
|
|
61
|
+
| Links | `files`, `docs`, `test`, `deps` | connect items to artifacts, tests, and relationships |
|
|
62
|
+
| Verification | `test`, `test-all`, `test-runs`†, `validate`, `gc` | run linked tests and repository checks |
|
|
63
|
+
| History | `history`, `history-compact`, `history-redact`, `history-repair`, `activity`, `restore`, `stats` | inspect, compact, redact, re-anchor, and recover item state |
|
|
64
|
+
| Schema | `schema add/remove-*` / `rename-type` / `rename-field` / `remap-status` / `apply-preset` | manage config-driven types, statuses, and fields; losslessly migrate existing items when definitions evolve; adopt presets or infer types |
|
|
65
|
+
| Profiles | `profile list` / `show` / `apply` / `lint` | compose item types, statuses, fields, workflows, config, templates, and recommended packages into archetype bundles (agile/ops/research); `apply` stages every dimension idempotently; `lint` reports author-time consistency findings without writing |
|
|
66
|
+
| Calendar | `calendar`, `cal` | project deadlines, reminders, and events |
|
|
67
|
+
| Packages | `install`, `upgrade`, `package`, `packages`, `extension`, package/extension command groups | install, upgrade, manage, and run package-backed extension commands |
|
|
68
|
+
| Machines | `contracts`, `help`, optional `guide`/`completion` | command contracts plus optional guide-shell docs routing and shell helpers |
|
|
67
69
|
|
|
68
70
|
`†` `test-runs` subcommands are provided by the optional `linked-test-adapters` package (`pm install linked-test-adapters --project`).
|
|
69
71
|
|
|
@@ -89,6 +91,15 @@ ID prefix without relying on the legacy positional form. `pm init ops` remains
|
|
|
89
91
|
compatible, and supplying both forms is accepted only when they normalize to the
|
|
90
92
|
same prefix; conflicting values fail with `init_id_prefix_conflict` instead of
|
|
91
93
|
silently choosing one.
|
|
94
|
+
Prefixes normalize through the same primitive used by item creation: letters
|
|
95
|
+
become lowercase, each run of whitespace or punctuation becomes one `-`, edge
|
|
96
|
+
separators are removed, and exactly one trailing `-` is stored. For example,
|
|
97
|
+
`"Release Candidate"` persists as `release-candidate-`; an input with no ASCII
|
|
98
|
+
letters or digits falls back to `pm-`. Path-like values remain invalid tracker
|
|
99
|
+
prefixes when passed through `--id-prefix`; a path-like positional value remains
|
|
100
|
+
the advanced tracker-root target described below. To repair an older unsafe
|
|
101
|
+
value, rerun init with a safe prefix and explicit replacement intent, for example
|
|
102
|
+
`pm init --id-prefix "release candidate" --force --defaults`.
|
|
92
103
|
Use `pm init --workspace <dir>` when `<dir>` is a project root; it creates `<dir>/.agents/pm`. A path-like positional remains the advanced tracker-root form and writes tracker files directly at that path. Both explicit target forms return `target.mode`, `target.tracker_root`, and tracker-scoped executable `next_steps` so agents can run the suggestions from any working directory.
|
|
93
104
|
Implicit init discovery also reports whether the selected tracker is local or was found in an ancestor. If `pm init <name>` would change an ancestor tracker, the refusal names both directories and gives the safe current-directory retry: `pm init <name> --pm-path "$PWD/.agents/pm" --defaults`.
|
|
94
105
|
`pm init --agent-guidance ask` is the default behavior: prompt in TTY only when AGENTS/CLAUDE guidance is missing and no decline is recorded.
|
|
@@ -163,6 +174,10 @@ Use `duplicates --status all` for a true whole-history duplicate check. The
|
|
|
163
174
|
result echoes `filters.statuses: null` for the unrestricted corpus; named or
|
|
164
175
|
custom statuses are normalized through the runtime status registry and an
|
|
165
176
|
unknown status fails instead of returning a false-clean result.
|
|
177
|
+
As a read-only structured surface, `duplicates` accepts the universal output
|
|
178
|
+
controls, including `--output-format json`, `--lean`, projection/amount
|
|
179
|
+
controls, and token accounting, while its default TOON output remains bounded.
|
|
180
|
+
Tracked by [pm-gh1076](../.agents/pm/issues/pm-gh1076.toon).
|
|
166
181
|
Use `pm get <id>` to read a single item by ID — the single-item read primitive used throughout the agent loop. It accepts `--fields <list>` and `--depth brief|standard|deep|full` for token-minimal projections, and `--tree`/`--tree-depth <n>` to include descendants. Standard/deep reads expose a normalized `schedule` facet (`deadline`, `start_at`, `end_at`, `location`, reminders, and events) when scheduling metadata exists. Container-oriented built-ins (Epic, Feature, Milestone, and Plan) plus custom types automatically expose type-agnostic child counts and continuation metadata. Standard depth keeps that rollup counts-only; `--depth deep|full` or an explicit `--fields id,children` request adds the deterministic bounded child sample. Built-in leaf reads avoid a workspace scan unless children are explicitly requested. `pm get <id> --json` returns the `body` inside the `item` object (`.item.body`); see [Full results, totals, and bodies](#full-results-totals-and-bodies). To duplicate an existing item as a starting point, `pm copy <id> --title "New title"` clones it into a fresh id with lifecycle fields reset.
|
|
167
182
|
|
|
168
183
|
When the strongest duplicate match is terminal because the same work recurred,
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -29,6 +29,7 @@ pm config project export --json
|
|
|
29
29
|
pm config project get item-format --json
|
|
30
30
|
pm config project set item-format --format toon
|
|
31
31
|
pm config project set test-result-tracking --policy enabled
|
|
32
|
+
pm config project set untrusted-linked-test-execution --policy disabled
|
|
32
33
|
```
|
|
33
34
|
|
|
34
35
|
`config set <key> <value>` also accepts the value as a positional argument; pm routes
|
|
@@ -85,6 +86,7 @@ When `settings.json` cannot be loaded, `pm` falls back to built-in defaults and
|
|
|
85
86
|
| `history.compact_policy.max_entries` | when the policy is enabled, the entry count above which a stream is flagged by `pm health` and the default `pm history-compact --all-over` threshold (default `500`) |
|
|
86
87
|
| `history.compact_policy.trigger` | policy intent when enabled: `health_warn` (advisory only) or `auto` (scheduled sweeps expected) |
|
|
87
88
|
| `testing.record_results_to_items` | persist bounded linked-test summaries |
|
|
89
|
+
| `testing.allow_untrusted_linked_tests` | permit the explicit `pm test --allow-untrusted-linked-tests` one-run override (default `false`; does not trust or execute commands by itself) |
|
|
88
90
|
| `validation.sprint_release_format` | `warn` or `strict_error` |
|
|
89
91
|
| `validation.parent_reference` | `warn` or `strict_error` (`strict_error` is the built-in default; `pm create --allow-missing-parent` is the explicit escape hatch) |
|
|
90
92
|
| `item_types.definitions[]` | custom item types and type options |
|
|
@@ -115,6 +117,7 @@ pm config project set schema_unknown_field_policy reject # (schema.unknown_fie
|
|
|
115
117
|
pm config project set governance-duplicate-detection-mode strict # (governance.duplicate_detection_mode) off | advisory | strict
|
|
116
118
|
pm config project set governance-duplicate-detection-threshold 0.8 # (governance.duplicate_detection_threshold) ratio 0..1
|
|
117
119
|
pm config project set governance-duplicate-detection-limit 3 # (governance.duplicate_detection_limit) integer 0..20
|
|
120
|
+
pm config project set untrusted-linked-test-execution disabled # (testing.allow_untrusted_linked_tests) enabled | disabled
|
|
118
121
|
```
|
|
119
122
|
|
|
120
123
|
Duplicate governance uses the shared SDK scorer and bounded metadata query
|
|
@@ -227,6 +230,7 @@ pm config project set sprint-release-format-policy --policy warn
|
|
|
227
230
|
pm config project set parent-reference-policy --policy strict_error
|
|
228
231
|
pm config project set history-missing-stream-policy --policy auto_create
|
|
229
232
|
pm config project set test-result-tracking --policy enabled
|
|
233
|
+
pm config project set untrusted-linked-test-execution --policy disabled
|
|
230
234
|
```
|
|
231
235
|
|
|
232
236
|
Use standalone checks when validating a repository:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Dependency-kind contract
|
|
2
2
|
|
|
3
|
-
Tracker: [pm-4020c5](../.agents/pm/issues/pm-4020c5.toon), [pm-jkbqt8](../.agents/pm/issues/pm-jkbqt8.toon), [pm-q6n8sj](../.agents/pm/issues/pm-q6n8sj.toon), [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon),
|
|
3
|
+
Tracker: [pm-4020c5](../.agents/pm/issues/pm-4020c5.toon), [pm-jkbqt8](../.agents/pm/issues/pm-jkbqt8.toon), [pm-q6n8sj](../.agents/pm/issues/pm-q6n8sj.toon), [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon), [pm-flnefm](../.agents/pm/issues/pm-flnefm.toon), [pm-rggtvd](../.agents/pm/issues/pm-rggtvd.toon), and [pm-vk7zek](../.agents/pm/issues/pm-vk7zek.toon).
|
|
4
4
|
|
|
5
5
|
Dependency rows have one canonical stored spelling per relationship meaning. Command inputs remain compatibility-friendly: hyphens normalize to underscores and the aliases below are accepted, but `pm create` and `pm update` persist the canonical kind. Existing historical rows are never rewritten implicitly.
|
|
6
6
|
|
|
@@ -15,9 +15,17 @@ Dependency rows have one canonical stored spelling per relationship meaning. Com
|
|
|
15
15
|
|
|
16
16
|
The SDK relationship registry is authoritative. `canonicalizeRelationshipKind()` rejects unknown spellings, while `resolveCanonicalRelationshipKind()` supports validation flows that need an undefined result. `pm contracts` publishes `relationship_kind_contracts` with canonical names, aliases, inverses, and ordering/hierarchy semantics.
|
|
17
17
|
|
|
18
|
+
Extension kinds may opt into both ordering and hierarchy semantics. Unless they
|
|
19
|
+
declare an explicit `traversal`, ordering is the primary traversal and context
|
|
20
|
+
role family; hierarchy direction and cardinality remain enforceable integrity
|
|
21
|
+
constraints. This ordering-first precedence is shared by registry snapshots and
|
|
22
|
+
direct-edge context explanations.
|
|
23
|
+
|
|
18
24
|
Dependency additions and removals share the same lossless input grammar. A
|
|
19
|
-
bare value is an item id; structured input uses `id=<id>` plus
|
|
20
|
-
canonical `kind
|
|
25
|
+
bare value is an item id; structured removal input uses `id=<id>` plus optional
|
|
26
|
+
canonical `kind` (with `type` accepted only as an input alias), `source_kind`, `author`, and ISO `created_at`
|
|
27
|
+
selectors. Supplying all stored coordinates retires exactly one dependency row
|
|
28
|
+
without deleting siblings that share an id and kind. Punctuation-shaped shorthand such as
|
|
21
29
|
`OTHER,related` is rejected with `dependency_flag_value_invalid` on both
|
|
22
30
|
`--dep` and `--dep-remove`, before prefix normalization can turn it into a
|
|
23
31
|
dangling id. A removal selector that matches no stored row fails with
|
|
@@ -25,6 +33,26 @@ dangling id. A removal selector that matches no stored row fails with
|
|
|
25
33
|
available identities. Re-adding a stored dependency identity is idempotent; if
|
|
26
34
|
legacy storage contains that exact identity more than once, the same mutation
|
|
27
35
|
collapses the touched copies to one without creating an edge-absence window.
|
|
36
|
+
The stored identity includes normalized `id`, `kind`, `source_kind`, `author`,
|
|
37
|
+
and creation instant, so provenance-distinct sibling rows remain independent.
|
|
38
|
+
|
|
39
|
+
## Hierarchy integrity
|
|
40
|
+
|
|
41
|
+
The registry's `hierarchy`, `hierarchyDirection`, `outgoing`, and `incoming`
|
|
42
|
+
fields are executable contracts. Scalar `parent` metadata and every registered
|
|
43
|
+
hierarchy dependency spelling normalize into the same parent-to-child relation.
|
|
44
|
+
That normalized relation powers `pm list --parent`, list/get tree projections,
|
|
45
|
+
child rollups, graph traversal, graph analysis, graph audit, validate, and
|
|
46
|
+
health. Extensions therefore gain hierarchy behavior by registering semantics;
|
|
47
|
+
consumers do not hard-code kind names.
|
|
48
|
+
|
|
49
|
+
Create and update transactions reject a newly introduced hierarchy cycle,
|
|
50
|
+
registry cardinality violation, or scalar/dependency direction contradiction
|
|
51
|
+
before persistence. Existing debt remains readable and repairable. Active debt
|
|
52
|
+
is gate-failing in graph governance and health; defects confined to terminal
|
|
53
|
+
items are labeled legacy and are never mutated automatically. `pm validate`
|
|
54
|
+
reports cycle, cardinality, and parent-divergence counts and exact bounded rows,
|
|
55
|
+
while `pm graph analyze` exposes a compact `hierarchy` summary.
|
|
28
56
|
|
|
29
57
|
`recurs_from` has no alias: a later occurrence points to an earlier occurrence.
|
|
30
58
|
It is persistent after both items become terminal and carries temporal identity,
|