@unbrained/pm-cli 2026.8.26 → 2026.8.28

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.
Files changed (196) hide show
  1. package/.agents/skills/HARNESS_COMPATIBILITY.md +32 -0
  2. package/.agents/skills/README.md +47 -0
  3. package/.agents/skills/pm-developer/SKILL.md +117 -0
  4. package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +49 -0
  5. package/.agents/skills/pm-developer/references/GRAPH_AND_RELATIONSHIPS.md +91 -0
  6. package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +72 -0
  7. package/.agents/skills/pm-developer/references/PROMPTS.md +17 -0
  8. package/.agents/skills/pm-developer/references/SCRIPTING_COMPOSITION.md +82 -0
  9. package/.agents/skills/pm-developer/references/TOKEN_BUDGETS.md +85 -0
  10. package/.agents/skills/pm-extensions/SKILL.md +106 -0
  11. package/.agents/skills/pm-extensions/references/AUTHORING.md +95 -0
  12. package/.agents/skills/pm-extensions/references/LIFECYCLE.md +40 -0
  13. package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +25 -0
  14. package/.agents/skills/pm-sdk/SKILL.md +107 -0
  15. package/.agents/skills/pm-sdk/references/DOMAIN_MODELING.md +78 -0
  16. package/.agents/skills/pm-sdk/references/INTEGRATION_CHECKLIST.md +31 -0
  17. package/.agents/skills/pm-sdk/references/PROMPTS.md +13 -0
  18. package/.agents/skills/pm-sdk/references/SURFACE_MAP.md +82 -0
  19. package/.agents/skills/pm-user/SKILL.md +111 -0
  20. package/.agents/skills/pm-user/references/BACKLOG_SHAPING.md +105 -0
  21. package/.agents/skills/pm-user/references/PROMPTS.md +17 -0
  22. package/.agents/skills/pm-user/references/WORKFLOWS.md +35 -0
  23. package/.claude-plugin/marketplace.json +2 -2
  24. package/CHANGELOG.md +50 -4
  25. package/README.md +8 -5
  26. package/dist/cli/commander-usage.js +11 -7
  27. package/dist/cli/error-guidance.js +62 -8
  28. package/dist/cli/help-content.d.ts +2 -0
  29. package/dist/cli/help-content.js +53 -17
  30. package/dist/cli/help-json-payload.d.ts +8 -2
  31. package/dist/cli/help-json-payload.js +46 -12
  32. package/dist/cli/main.js +52 -74
  33. package/dist/cli/register-annotations.js +83 -60
  34. package/dist/cli/register-setup.js +98 -57
  35. package/dist/cli-bundle/bundle-manifest.json +151 -151
  36. package/dist/cli-bundle/chunks/{chunk-UKBCRPA2.js → chunk-BY2FQ2NI.js} +2 -2
  37. package/dist/cli-bundle/chunks/chunk-E73FDIWT.js +3 -0
  38. package/dist/cli-bundle/chunks/{chunk-WRHJ3MB6.js → chunk-FEVBFFCQ.js} +2 -2
  39. package/dist/cli-bundle/chunks/{chunk-KBFP3E4E.js → chunk-M7OXRQE3.js} +66 -44
  40. package/dist/cli-bundle/chunks/{chunk-S4U76VZF.js → chunk-NBCBFVZI.js} +2 -2
  41. package/dist/cli-bundle/chunks/{chunk-ZNRLJ54C.js → chunk-NTXZHRKA.js} +45 -45
  42. package/dist/cli-bundle/chunks/chunk-QE6WQXFO.js +3 -0
  43. package/dist/cli-bundle/chunks/chunk-TIQ6AMH2.js +13 -0
  44. package/dist/cli-bundle/chunks/chunk-X2RROGZE.js +2 -0
  45. package/dist/cli-bundle/chunks/{chunk-E2GCFJSU.js → chunk-XRVVYRRO.js} +33 -33
  46. package/dist/cli-bundle/chunks/chunk-XWEQGHHG.js +202 -0
  47. package/dist/cli-bundle/chunks/{register-list-query-EMCPMICY.js → register-list-query-J35ZPQQ5.js} +2 -2
  48. package/dist/cli-bundle/chunks/{register-mutation-OJ67ABCB.js → register-mutation-J6XJJOGU.js} +4 -4
  49. package/dist/cli-bundle/chunks/{register-operations-H2GLP7LT.js → register-operations-AE3JEMFT.js} +2 -2
  50. package/dist/cli-bundle/chunks/register-setup-OQERLLWE.js +2 -0
  51. package/dist/cli-bundle/focused-chunks/{chunk-72T6JGAE.js → chunk-4ZDRZYYJ.js} +43 -43
  52. package/dist/cli-bundle/focused-chunks/{chunk-OHIHZ7HS.js → chunk-6GCRSLPG.js} +2 -2
  53. package/dist/cli-bundle/focused-chunks/{chunk-UYBA57GY.js → chunk-AD6ULRAF.js} +2 -2
  54. package/dist/cli-bundle/focused-chunks/{chunk-FXDLT6FL.js → chunk-AHAM2HAU.js} +2 -2
  55. package/dist/cli-bundle/focused-chunks/{chunk-LV5N3LK5.js → chunk-FC2AXLB5.js} +2 -2
  56. package/dist/cli-bundle/focused-chunks/{chunk-IBHXMFE7.js → chunk-HC7ODMH3.js} +2 -2
  57. package/dist/cli-bundle/focused-chunks/{chunk-4K2II4TV.js → chunk-HVQ22RC4.js} +2 -2
  58. package/dist/cli-bundle/focused-chunks/{chunk-MMXUPDDJ.js → chunk-JZYPPMXF.js} +2 -2
  59. package/dist/cli-bundle/focused-chunks/chunk-LLNTHF5X.js +2 -0
  60. package/dist/cli-bundle/focused-chunks/chunk-LYFWQMVC.js +2 -0
  61. package/dist/cli-bundle/focused-chunks/{chunk-A644DUFQ.js → chunk-MEASX544.js} +2 -2
  62. package/dist/cli-bundle/focused-chunks/{chunk-YO3ZF3FI.js → chunk-THEPQMLX.js} +2 -2
  63. package/dist/cli-bundle/focused-chunks/{chunk-57XY346D.js → chunk-XDPYBQCF.js} +9 -9
  64. package/dist/cli-bundle/focused-chunks/{chunk-TMJDFHVD.js → chunk-Y3JJXRVK.js} +2 -2
  65. package/dist/cli-bundle/focused-chunks/{chunk-66VGB23P.js → chunk-Y5A7SJJ7.js} +2 -2
  66. package/dist/cli-bundle/focused-chunks/chunk-YJLDHJOD.js +2 -0
  67. package/dist/cli-bundle/focused-chunks/{chunk-P2E6LDAE.js → chunk-YVVZ3LQ6.js} +3 -3
  68. package/dist/cli-bundle/focused-chunks/chunk-Z2USIBR2.js +5 -0
  69. package/dist/cli-bundle/main.js +15 -14
  70. package/dist/cli-bundle/sdk-authoring.js +1 -1
  71. package/dist/cli-bundle/sdk-contracts.js +2 -2
  72. package/dist/cli-bundle/sdk-core.js +31 -31
  73. package/dist/cli-bundle/sdk-governance.js +1 -1
  74. package/dist/cli-bundle/sdk-graph.js +1 -1
  75. package/dist/cli-bundle/sdk-merge.js +31 -31
  76. package/dist/cli-bundle/sdk-query.js +1 -1
  77. package/dist/cli-bundle/sdk-runtime.js +1 -1
  78. package/dist/cli-bundle/sdk-testing.js +1 -1
  79. package/dist/cli-bundle/sdk.js +32 -7
  80. package/dist/core/governance/issue-codes.d.ts +11 -2
  81. package/dist/core/governance/issue-codes.js +29 -10
  82. package/dist/core/item/item-format.js +3 -3
  83. package/dist/core/store/item-store.js +12 -5
  84. package/dist/mcp/server.js +123 -9
  85. package/dist/mcp/tool-definitions.d.ts +2 -0
  86. package/dist/mcp/tool-definitions.js +5 -5
  87. package/dist/sdk/agent/closed-domain-contracts.d.ts +1 -1
  88. package/dist/sdk/agent/closed-domain-contracts.js +24 -2
  89. package/dist/sdk/agent/command-recovery.js +3 -3
  90. package/dist/sdk/agent/task-transcript-contracts.d.ts +52 -0
  91. package/dist/sdk/agent/task-transcript-contracts.js +198 -0
  92. package/dist/sdk/agent-capability-contracts.js +6 -2
  93. package/dist/sdk/annotations.d.ts +5 -2
  94. package/dist/sdk/annotations.js +66 -36
  95. package/dist/sdk/cli-bootstrap.d.ts +2 -8
  96. package/dist/sdk/cli-bootstrap.js +7 -66
  97. package/dist/sdk/cli-contracts/bootstrap-command-scanner.d.ts +23 -0
  98. package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +80 -0
  99. package/dist/sdk/cli-contracts/command-aliases.js +15 -2
  100. package/dist/sdk/cli-contracts/enum-contracts.d.ts +4 -1
  101. package/dist/sdk/cli-contracts/enum-contracts.js +7 -2
  102. package/dist/sdk/cli-contracts/flag-contracts.js +12 -5
  103. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +5 -5
  104. package/dist/sdk/cli-contracts/grammar-contracts.d.ts +3 -3
  105. package/dist/sdk/cli-contracts/grammar-contracts.js +24 -17
  106. package/dist/sdk/cli-contracts/runtime-contracts.js +13 -11
  107. package/dist/sdk/cli-contracts/tool-parameter-tables.js +15 -2
  108. package/dist/sdk/cli-contracts/tool-schema.d.ts +1 -1
  109. package/dist/sdk/cli-contracts/tool-schema.js +32 -16
  110. package/dist/sdk/cli-contracts.d.ts +1 -1
  111. package/dist/sdk/cli-contracts.js +3 -3
  112. package/dist/sdk/cli-program.js +3 -2
  113. package/dist/sdk/comments.d.ts +4 -0
  114. package/dist/sdk/comments.js +2 -2
  115. package/dist/sdk/completion.js +47 -16
  116. package/dist/sdk/contracts.d.ts +1 -0
  117. package/dist/sdk/contracts.js +3 -2
  118. package/dist/sdk/extension/install-sources.d.ts +13 -0
  119. package/dist/sdk/extension/install-sources.js +62 -30
  120. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +26 -2
  121. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +38 -14
  122. package/dist/sdk/governance/upgrade.d.ts +2 -0
  123. package/dist/sdk/governance/upgrade.js +30 -8
  124. package/dist/sdk/governance/validate.js +8 -6
  125. package/dist/sdk/guide-topics.js +6 -6
  126. package/dist/sdk/index.d.ts +5 -2
  127. package/dist/sdk/index.js +6 -3
  128. package/dist/sdk/learnings.d.ts +4 -0
  129. package/dist/sdk/learnings.js +7 -4
  130. package/dist/sdk/lifecycle/close.js +4 -3
  131. package/dist/sdk/mcp/apps.d.ts +70 -0
  132. package/dist/sdk/mcp/apps.js +154 -0
  133. package/dist/sdk/mcp/skills.d.ts +127 -0
  134. package/dist/sdk/mcp/skills.js +390 -0
  135. package/dist/sdk/notes.d.ts +4 -0
  136. package/dist/sdk/notes.js +2 -2
  137. package/dist/sdk/read-output-contracts.js +16 -3
  138. package/dist/sdk/runtime-action-aliases.js +7 -3
  139. package/dist/sdk/runtime-input.js +15 -4
  140. package/dist/sdk/runtime-primitives.d.ts +1 -1
  141. package/dist/sdk/runtime-primitives.js +3 -3
  142. package/dist/sdk/runtime.d.ts +6 -6
  143. package/dist/sdk/runtime.js +8 -8
  144. package/docs/CLI_GRAMMAR.md +7 -1
  145. package/docs/COMMANDS.md +5 -4
  146. package/docs/EXTENSIONS.md +33 -32
  147. package/docs/MCP_2026_07_28.md +24 -2
  148. package/docs/MCP_2026_07_28_CONFORMANCE.md +4 -4
  149. package/docs/MCP_SKILLS_AND_APPS.md +107 -0
  150. package/docs/OUTPUT_TOKEN_ACCOUNTING.md +20 -7
  151. package/docs/QUICKSTART.md +15 -15
  152. package/docs/README.md +1 -0
  153. package/docs/RELEASING.md +20 -4
  154. package/docs/SDK.md +12 -0
  155. package/docs/SDK_CONTEXT_INTEGRITY.md +18 -1
  156. package/docs/SDK_EVIDENCE_TRACEABILITY.md +9 -1
  157. package/docs/SDK_RUNTIME_BOUNDARIES.md +10 -0
  158. package/docs/TESTING.md +6 -2
  159. package/docs/agent-task-token-baseline.json +97 -11
  160. package/docs/agent-task-transcripts.json +211 -0
  161. package/docs/generated/AGENT_CAPABILITY_ROUTING.md +1 -1
  162. package/docs/generated/FLAG_LEXICON_BUDGETS.md +3 -3
  163. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +11 -7
  164. package/docs/performance/cli-transport-overhead.md +10 -2
  165. package/marketplace.json +2 -2
  166. package/package.json +10 -8
  167. package/packages/pm-beads/README.md +12 -6
  168. package/packages/pm-beads/docs/MIGRATION.md +53 -0
  169. package/packages/pm-beads/extensions/beads/index.ts +8 -0
  170. package/packages/pm-beads/extensions/beads/runtime.ts +671 -112
  171. package/packages/pm-beads/package.json +1 -1
  172. package/packages/pm-calendar/package.json +1 -1
  173. package/packages/pm-command-kit/package.json +1 -1
  174. package/packages/pm-digital-twin/package.json +1 -1
  175. package/packages/pm-governance-audit/package.json +1 -1
  176. package/packages/pm-guide-shell/package.json +1 -1
  177. package/packages/pm-kanban/package.json +1 -1
  178. package/packages/pm-lifecycle-hooks/package.json +1 -1
  179. package/packages/pm-linked-test-adapters/package.json +1 -1
  180. package/packages/pm-search-advanced/package.json +1 -1
  181. package/packages/pm-templates/package.json +1 -1
  182. package/packages/pm-todos/package.json +1 -1
  183. package/packages/pm-vcs/package.json +1 -1
  184. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  185. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  186. package/sdk/public-surface.json +430 -36
  187. package/dist/cli-bundle/chunks/chunk-ES25LX3D.js +0 -202
  188. package/dist/cli-bundle/chunks/chunk-FRDWWB6R.js +0 -3
  189. package/dist/cli-bundle/chunks/chunk-ICQ3RVIY.js +0 -2
  190. package/dist/cli-bundle/chunks/chunk-IV64RJVE.js +0 -13
  191. package/dist/cli-bundle/chunks/chunk-MVYLQ67M.js +0 -3
  192. package/dist/cli-bundle/chunks/register-setup-GLZAHLVI.js +0 -2
  193. package/dist/cli-bundle/focused-chunks/chunk-4XNH2HM7.js +0 -2
  194. package/dist/cli-bundle/focused-chunks/chunk-7I23XGWO.js +0 -2
  195. package/dist/cli-bundle/focused-chunks/chunk-7YCDTCBC.js +0 -2
  196. package/dist/cli-bundle/focused-chunks/chunk-LMKG3DFE.js +0 -5
@@ -0,0 +1,198 @@
1
+ /**
2
+ * @module sdk/agent-task-transcript-contracts
3
+ *
4
+ * Defines and validates replayable agent-task transcripts without adding the
5
+ * SDK-only parser to ordinary CLI command bundles.
6
+ */
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]="006109f8-cb09-5a91-8929-7ac7521753b6")}catch(e){}}();
9
+ import { isPmSuccessfulExitCode, resolvePmCommandExitContract, } from "../cli-contracts/command-exit-contracts.js";
10
+ import { parseBootstrapCommandName } from "../cli-contracts/bootstrap-command-scanner.js";
11
+ import { PM_OUTPUT_ENVELOPE_KINDS, resolvePmCommandOutputEnvelope, } from "../output-contracts.js";
12
+ /** Stable schema version for replayable agent-task transcript corpora. */
13
+ export const PM_AGENT_TASK_TRANSCRIPT_VERSION = 2;
14
+ /** Supported strategies for measuring one transcript step's output cost. */
15
+ export const PM_AGENT_TASK_ACCOUNTING_MODES = [
16
+ "self_reported",
17
+ "independent_transport",
18
+ ];
19
+ function isRecord(value) {
20
+ return typeof value === "object" && value !== null && !Array.isArray(value);
21
+ }
22
+ function readTranscriptString(value, field) {
23
+ if (typeof value !== "string" || value.trim().length === 0) {
24
+ throw new TypeError(`${field} must be a non-empty string`);
25
+ }
26
+ return value.trim();
27
+ }
28
+ function readTranscriptStringArray(value, field, preserveWhitespace = false) {
29
+ if (!Array.isArray(value) || value.length === 0) {
30
+ throw new TypeError(`${field} must be a non-empty string array`);
31
+ }
32
+ return value.map((entry, index) => {
33
+ const normalized = readTranscriptString(entry, `${field}[${String(index)}]`);
34
+ return preserveWhitespace ? entry : normalized;
35
+ });
36
+ }
37
+ function readOptionalTranscriptString(value, field) {
38
+ return value === undefined ? undefined : readTranscriptString(value, field);
39
+ }
40
+ function readExpectedFieldValues(value, field) {
41
+ if (value === undefined)
42
+ return undefined;
43
+ if (!isRecord(value) || Object.keys(value).length === 0) {
44
+ throw new TypeError(`${field} must be a non-empty object`);
45
+ }
46
+ const entries = Object.entries(value).map(([path, expectedValue]) => {
47
+ if (path.length === 0 ||
48
+ path.split(".").some((segment) => segment.length === 0)) {
49
+ throw new TypeError(`${field} must use dot-separated own-property paths`);
50
+ }
51
+ if (expectedValue !== null &&
52
+ typeof expectedValue !== "string" &&
53
+ typeof expectedValue !== "boolean" &&
54
+ (typeof expectedValue !== "number" || !Number.isFinite(expectedValue))) {
55
+ throw new TypeError(`${field} values must be JSON primitives`);
56
+ }
57
+ return [path, expectedValue];
58
+ });
59
+ return Object.fromEntries(entries);
60
+ }
61
+ function assertTranscriptStepOutputContract(field, args, exitCode, outputKind, errorCode, refusalSurface) {
62
+ if (outputKind === "refusal") {
63
+ if (isPmSuccessfulExitCode(exitCode) ||
64
+ errorCode === undefined ||
65
+ refusalSurface === undefined) {
66
+ throw new TypeError(`${field} refusal steps require a non-success exit, error code, and refusal surface`);
67
+ }
68
+ return;
69
+ }
70
+ if (errorCode !== undefined || refusalSurface !== undefined) {
71
+ throw new TypeError(`${field} only refusal steps may declare expected_error_code or expected_refusal_surface`);
72
+ }
73
+ const command = parseBootstrapCommandName(args);
74
+ if (command === undefined) {
75
+ throw new TypeError(`${field}.args must identify a command after global flags`);
76
+ }
77
+ const exitContract = resolvePmCommandExitContract(command);
78
+ if (!isPmSuccessfulExitCode(exitCode) ||
79
+ (exitCode !== 0 &&
80
+ !exitContract?.exit_codes.some((declaredExitCode) => declaredExitCode === exitCode))) {
81
+ throw new TypeError(`${field} successful output must use exit code 0 or a command-declared successful effect exit`);
82
+ }
83
+ const declaredKind = resolvePmCommandOutputEnvelope(command).kind;
84
+ if (outputKind !== declaredKind) {
85
+ throw new TypeError(`${field} expected ${outputKind}, but ${command} declares ${declaredKind}`);
86
+ }
87
+ }
88
+ function parseAgentTaskTranscriptStep(value, taskId, index) {
89
+ if (!isRecord(value)) {
90
+ throw new TypeError(`tasks.${taskId}.steps[${String(index)}] must be an object`);
91
+ }
92
+ const field = `tasks.${taskId}.steps[${String(index)}]`;
93
+ const id = readTranscriptString(value.id, `${field}.id`);
94
+ const args = readTranscriptStringArray(value.args, `${field}.args`, true);
95
+ const expectedExitCode = value.expected_exit_code;
96
+ if (typeof expectedExitCode !== "number" ||
97
+ !Number.isSafeInteger(expectedExitCode)) {
98
+ throw new TypeError(`${field}.expected_exit_code must be a safe integer`);
99
+ }
100
+ const rawOutputKind = value.expected_output_kind;
101
+ if (rawOutputKind !== "refusal" &&
102
+ !PM_OUTPUT_ENVELOPE_KINDS.includes(rawOutputKind)) {
103
+ throw new TypeError(`${field}.expected_output_kind is unsupported`);
104
+ }
105
+ const expectedOutputKind = rawOutputKind;
106
+ const rawAccountingMode = value.expected_accounting_mode;
107
+ if (!PM_AGENT_TASK_ACCOUNTING_MODES.includes(rawAccountingMode)) {
108
+ throw new TypeError(`${field}.expected_accounting_mode is unsupported`);
109
+ }
110
+ const expectedAccountingMode = rawAccountingMode;
111
+ if (expectedAccountingMode === "independent_transport" &&
112
+ expectedOutputKind !== "refusal") {
113
+ throw new TypeError(`${field} independent_transport accounting is supported only for refusal steps`);
114
+ }
115
+ const requiredFields = readTranscriptStringArray(value.required_fields, `${field}.required_fields`);
116
+ if (requiredFields.some((requiredField) => requiredField.split(".").some((segment) => segment.length === 0))) {
117
+ throw new TypeError(`${field}.required_fields must contain dot-separated own-property paths`);
118
+ }
119
+ const expectedFieldValues = readExpectedFieldValues(value.expected_field_values, `${field}.expected_field_values`);
120
+ const expectedErrorCode = readOptionalTranscriptString(value.expected_error_code, `${field}.expected_error_code`);
121
+ const expectedRefusalSurface = readOptionalTranscriptString(value.expected_refusal_surface, `${field}.expected_refusal_surface`);
122
+ const recoveryFor = readOptionalTranscriptString(value.recovery_for, `${field}.recovery_for`);
123
+ assertTranscriptStepOutputContract(field, args, expectedExitCode, expectedOutputKind, expectedErrorCode, expectedRefusalSurface);
124
+ return {
125
+ id,
126
+ args,
127
+ expected_exit_code: expectedExitCode,
128
+ expected_output_kind: expectedOutputKind,
129
+ expected_accounting_mode: expectedAccountingMode,
130
+ required_fields: requiredFields,
131
+ ...(expectedFieldValues
132
+ ? { expected_field_values: expectedFieldValues }
133
+ : {}),
134
+ ...(expectedErrorCode ? { expected_error_code: expectedErrorCode } : {}),
135
+ ...(expectedRefusalSurface
136
+ ? { expected_refusal_surface: expectedRefusalSurface }
137
+ : {}),
138
+ ...(recoveryFor ? { recovery_for: recoveryFor } : {}),
139
+ };
140
+ }
141
+ function parseAgentTaskTranscript(value, index) {
142
+ if (!isRecord(value)) {
143
+ throw new TypeError(`tasks[${String(index)}] must be an object`);
144
+ }
145
+ const id = readTranscriptString(value.id, `tasks[${String(index)}].id`);
146
+ const description = readTranscriptString(value.description, `tasks.${id}.description`);
147
+ if (!Array.isArray(value.steps) || value.steps.length === 0) {
148
+ throw new TypeError(`tasks.${id}.steps must be a non-empty array`);
149
+ }
150
+ const steps = value.steps.map((step, stepIndex) => parseAgentTaskTranscriptStep(step, id, stepIndex));
151
+ const priorSteps = new Map();
152
+ for (const step of steps) {
153
+ if (priorSteps.has(step.id)) {
154
+ throw new TypeError(`tasks.${id} contains duplicate step id ${step.id}`);
155
+ }
156
+ if (step.recovery_for !== undefined) {
157
+ const refusal = priorSteps.get(step.recovery_for);
158
+ if (refusal?.expected_output_kind !== "refusal" ||
159
+ step.expected_output_kind === "refusal") {
160
+ throw new TypeError(`tasks.${id}.${step.id} recovery_for must reference an earlier refusal and declare successful output`);
161
+ }
162
+ }
163
+ priorSteps.set(step.id, step);
164
+ }
165
+ if (steps.at(-1)?.expected_output_kind === "refusal") {
166
+ throw new TypeError(`tasks.${id} completed task must terminate with successful output`);
167
+ }
168
+ for (const step of steps) {
169
+ if (step.expected_output_kind === "refusal" &&
170
+ !steps.some((candidate) => candidate.recovery_for === step.id)) {
171
+ throw new TypeError(`tasks.${id}.${step.id} refusal must have a later successful recovery_for step`);
172
+ }
173
+ }
174
+ return { id, description, steps };
175
+ }
176
+ /** Parse and fail closed on malformed or internally inconsistent transcripts. */
177
+ export function parsePmAgentTaskTranscriptCorpus(value) {
178
+ if (!isRecord(value)) {
179
+ throw new TypeError("agent-task transcript corpus must be an object");
180
+ }
181
+ if (value.version !== PM_AGENT_TASK_TRANSCRIPT_VERSION) {
182
+ throw new TypeError(`agent-task transcript corpus version must be ${String(PM_AGENT_TASK_TRANSCRIPT_VERSION)}`);
183
+ }
184
+ if (!Array.isArray(value.tasks) || value.tasks.length === 0) {
185
+ throw new TypeError("agent-task transcript corpus tasks must be non-empty");
186
+ }
187
+ const tasks = value.tasks.map((task, index) => parseAgentTaskTranscript(task, index));
188
+ const taskIds = new Set();
189
+ for (const task of tasks) {
190
+ if (taskIds.has(task.id)) {
191
+ throw new TypeError(`duplicate agent-task transcript id ${task.id}`);
192
+ }
193
+ taskIds.add(task.id);
194
+ }
195
+ return { version: PM_AGENT_TASK_TRANSCRIPT_VERSION, tasks };
196
+ }
197
+ //# sourceMappingURL=task-transcript-contracts.js.map
198
+ //# debugId=006109f8-cb09-5a91-8929-7ac7521753b6
@@ -5,7 +5,7 @@
5
5
  * surfaces from one public SDK contract.
6
6
  */
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]="51e187c6-d48f-59e8-ad23-c72670ade3cc")}catch(e){}}();
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]="d8f3f734-9adf-56f3-a5ba-c8b6407c4a89")}catch(e){}}();
9
9
  import { PM_CORE_COMMAND_NAMES } from "./cli-contracts/enum-contracts.js";
10
10
  const CORE_COMMANDS = new Set([
11
11
  "claim",
@@ -244,6 +244,8 @@ const CAPABILITY_FAMILY_ORDER = [
244
244
  ];
245
245
  const CAPABILITY_ROUTING_EXCLUDED_ALIASES = new Set([
246
246
  "ctx",
247
+ "extension",
248
+ "install",
247
249
  "item-reopen",
248
250
  "list-all",
249
251
  "list-blocked",
@@ -252,6 +254,8 @@ const CAPABILITY_ROUTING_EXCLUDED_ALIASES = new Set([
252
254
  "list-draft",
253
255
  "list-in-progress",
254
256
  "list-open",
257
+ "packages",
258
+ "upgrade",
255
259
  ]);
256
260
  /** Group the command registry for progressive-disclosure routing surfaces. */
257
261
  export function listPmCommandCapabilityGroups(contracts = PM_COMMAND_CAPABILITY_CONTRACTS) {
@@ -420,4 +424,4 @@ export function renderPmCapabilityRoutingMarkdown(contracts = PM_COMMAND_CAPABIL
420
424
  ].join("\n");
421
425
  }
422
426
  //# sourceMappingURL=agent-capability-contracts.js.map
423
- //# debugId=51e187c6-d48f-59e8-ad23-c72670ade3cc
427
+ //# debugId=d8f3f734-9adf-56f3-a5ba-c8b6407c4a89
@@ -25,6 +25,8 @@ export interface AnnotationCommandOptions {
25
25
  includeMeta?: boolean;
26
26
  /** Return the complete collection after a mutation instead of the bounded mutation receipt. */
27
27
  fullHistory?: boolean;
28
+ /** Append only when no entry has the same resolved author and text. */
29
+ ifAbsent?: boolean;
28
30
  }
29
31
  /** Identifies the single annotation mutation represented by a bounded response. */
30
32
  export interface AnnotationMutationReceipt {
@@ -32,8 +34,8 @@ export interface AnnotationMutationReceipt {
32
34
  action: "add" | "edit" | "delete";
33
35
  /** Stable one-based collection position targeted by the mutation. */
34
36
  entry_index: number;
35
- /** Number of stored entries changed by the mutation. */
36
- changed_count: 1;
37
+ /** Number of stored entries changed by the mutation attempt. */
38
+ changed_count: 0 | 1;
37
39
  /** Whether the response includes the complete post-mutation collection. */
38
40
  full_history_included: boolean;
39
41
  }
@@ -133,6 +135,7 @@ export type AnnotationCommandResult<TKey extends string, TEntry extends Annotati
133
135
  limit?: number;
134
136
  mutation_receipt?: AnnotationMutationReceipt;
135
137
  omission_receipt?: AnnotationOmissionReceipt;
138
+ changed?: boolean;
136
139
  };
137
140
  /** Implements limit annotation entries for the public runtime surface of this module. */
138
141
  export declare function limitAnnotationEntries<TEntry>(values: TEntry[], limit: number | undefined): TEntry[];
@@ -4,7 +4,7 @@
4
4
  * Implements the pm annotation command command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !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]="39acab93-f9ad-5b95-871e-625d912f1322")}catch(e){}}();
7
+ !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]="6d20a21c-ac67-5712-9f63-b10ffc0e2c64")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "./environment/tracker-preflight.js";
9
9
  import { readFile } from "node:fs/promises";
10
10
  import { isFileAbsentError } from "../core/fs/fs-utils.js";
@@ -217,6 +217,13 @@ function assertAnnotationAddValueIsNotFlagLike(raw, config) {
217
217
  * with the same structured recovery bundle.
218
218
  */
219
219
  function assertAnnotationMessageHasTextSource(config, options) {
220
+ if (options.ifAbsent === true &&
221
+ !["add", "stdin", "file"].includes(config.input.mode)) {
222
+ throw new PmCliError(`--if-absent requires a ${config.collectionKey.replace(/s$/, "")} append`, EXIT_CODE.USAGE, {
223
+ code: "annotation_if_absent_without_append",
224
+ required: "Combine --if-absent with one append text source; omit it for list, edit, and delete operations.",
225
+ });
226
+ }
220
227
  if (config.input.mode !== "list" || options.message === undefined) {
221
228
  return;
222
229
  }
@@ -230,6 +237,19 @@ function assertAnnotationMessageHasTextSource(config, options) {
230
237
  ],
231
238
  });
232
239
  }
240
+ /** Append one annotation entry or return the matching entry for an idempotent retry. */
241
+ function appendAnnotationEntry(document, collectionKey, author, text, ifAbsent, createEntry) {
242
+ const entries = readAnnotationEntries(document.metadata, collectionKey);
243
+ const existingIndex = ifAbsent
244
+ ? entries.findIndex((entry) => entry.author === author && entry.text === text)
245
+ : -1;
246
+ if (existingIndex >= 0) {
247
+ return { changedFields: [], entryIndex: existingIndex + 1 };
248
+ }
249
+ entries.push(createEntry({ created_at: nowIso(), author, text }));
250
+ document.metadata[collectionKey] = entries;
251
+ return { changedFields: [collectionKey], entryIndex: entries.length };
252
+ }
233
253
  /** Implements run annotation command for the public runtime surface of this module. */
234
254
  export async function runAnnotationCommand(id, options, global, config) {
235
255
  assertAnnotationMessageHasTextSource(config, options);
@@ -325,6 +345,7 @@ export async function runAnnotationCommand(id, options, global, config) {
325
345
  }, options.fullHistory === true);
326
346
  }
327
347
  let result;
348
+ let entryIndex = 0;
328
349
  try {
329
350
  result = await mutateItem({
330
351
  pmRoot,
@@ -335,12 +356,11 @@ export async function runAnnotationCommand(id, options, global, config) {
335
356
  message: options.message,
336
357
  force: options.force,
337
358
  bypassAssigneeConflict: config.bypassOwnershipConflict,
359
+ skipNoop: options.ifAbsent === true,
338
360
  mutate(document) {
339
- const entries = readAnnotationEntries(document.metadata, config.collectionKey);
340
- const entryInput = { created_at: nowIso(), author, text };
341
- entries.push(config.createEntry(entryInput));
342
- document.metadata[config.collectionKey] = entries;
343
- return { changedFields: [config.collectionKey] };
361
+ const appended = appendAnnotationEntry(document, config.collectionKey, author, text, options.ifAbsent === true, config.createEntry);
362
+ entryIndex = appended.entryIndex;
363
+ return { changedFields: appended.changedFields };
344
364
  },
345
365
  });
346
366
  }
@@ -350,8 +370,11 @@ export async function runAnnotationCommand(id, options, global, config) {
350
370
  const allEntries = readAnnotationEntries(result.item, config.collectionKey);
351
371
  return renderAnnotationResult(result.item.id, config.collectionKey, allEntries, limit, options.includeMeta === true, {
352
372
  action: "add",
353
- entryIndex: allEntries.length,
354
- entry: allEntries.at(-1),
373
+ entryIndex,
374
+ entry: allEntries[entryIndex - 1],
375
+ changedCount: options.ifAbsent === true
376
+ ? Math.min(result.changedFields.length, 1)
377
+ : undefined,
355
378
  }, options.fullHistory === true);
356
379
  }
357
380
  /** Implements resolve annotation index for the public runtime surface of this module. */
@@ -367,6 +390,36 @@ export function resolveAnnotationIndex(oneBasedIndex, count, collectionKey) {
367
390
  }
368
391
  return oneBasedIndex - 1;
369
392
  }
393
+ /** Build the mutation and omission receipts attached to bounded annotation results. */
394
+ function renderAnnotationMutationReceipts(collectionKey, mutation, historyOmitted) {
395
+ if (mutation === undefined)
396
+ return {};
397
+ return {
398
+ mutation_receipt: {
399
+ action: mutation.action,
400
+ entry_index: mutation.entryIndex,
401
+ changed_count: mutation.changedCount ?? 1,
402
+ full_history_included: !historyOmitted,
403
+ },
404
+ omission_receipt: {
405
+ has_omissions: historyOmitted,
406
+ omitted_field_group_count: historyOmitted ? 1 : 0,
407
+ omitted_field_groups: historyOmitted
408
+ ? [
409
+ {
410
+ name: `${collectionKey}_history`,
411
+ restore_with: {
412
+ selector: "full_history",
413
+ cli_flag: "--full-history",
414
+ sdk_option: "fullHistory",
415
+ mcp_option: "full",
416
+ },
417
+ },
418
+ ]
419
+ : [],
420
+ },
421
+ };
422
+ }
370
423
  function renderAnnotationResult(id, collectionKey, allEntries, limit, includeMeta, mutation, fullHistory = false) {
371
424
  const entries = mutation === undefined || fullHistory
372
425
  ? limitAnnotationEntries(allEntries, mutation !== undefined && fullHistory ? undefined : limit)
@@ -378,6 +431,9 @@ function renderAnnotationResult(id, collectionKey, allEntries, limit, includeMet
378
431
  id,
379
432
  [collectionKey]: entries,
380
433
  count: entries.length,
434
+ ...(mutation?.changedCount === undefined
435
+ ? {}
436
+ : { changed: mutation.changedCount === 1 }),
381
437
  ...([includeMeta, mutation !== undefined].includes(true)
382
438
  ? {
383
439
  total_count: allEntries.length,
@@ -386,34 +442,8 @@ function renderAnnotationResult(id, collectionKey, allEntries, limit, includeMet
386
442
  ...(limit !== undefined ? { limit } : {}),
387
443
  }
388
444
  : {}),
389
- ...(mutation === undefined
390
- ? {}
391
- : {
392
- mutation_receipt: {
393
- action: mutation.action,
394
- entry_index: mutation.entryIndex,
395
- changed_count: 1,
396
- full_history_included: !historyOmitted,
397
- },
398
- omission_receipt: {
399
- has_omissions: historyOmitted,
400
- omitted_field_group_count: historyOmitted ? 1 : 0,
401
- omitted_field_groups: historyOmitted
402
- ? [
403
- {
404
- name: `${collectionKey}_history`,
405
- restore_with: {
406
- selector: "full_history",
407
- cli_flag: "--full-history",
408
- sdk_option: "fullHistory",
409
- mcp_option: "full",
410
- },
411
- },
412
- ]
413
- : [],
414
- },
415
- }),
445
+ ...renderAnnotationMutationReceipts(collectionKey, mutation, historyOmitted),
416
446
  };
417
447
  }
418
448
  //# sourceMappingURL=annotations.js.map
419
- //# debugId=39acab93-f9ad-5b95-871e-625d912f1322
449
+ //# debugId=6d20a21c-ac67-5712-9f63-b10ffc0e2c64
@@ -53,15 +53,9 @@ export interface BootstrapHelpRequest {
53
53
  }
54
54
  /** Implements parse bootstrap help request for the public runtime surface of this module. */
55
55
  export declare function parseBootstrapHelpRequest(argv: string[]): BootstrapHelpRequest;
56
- /**
57
- * Index of the command token in argv — the first non-flag token, skipping the
58
- * value-consuming/global bootstrap flags. Returns undefined when there is none
59
- * (bare invocation, only global flags, or a leading `--`). Single source of truth
60
- * for command-position scanning shared by {@link parseBootstrapCommandName} and the
61
- * command-alias rewrite so their precedence rules can never drift apart.
62
- */
56
+ /** Locate the command token after global bootstrap flags and their values. */
63
57
  export declare function findBootstrapCommandTokenIndex(argv: string[]): number | undefined;
64
- /** Implements parse bootstrap command name for the public runtime surface of this module. */
58
+ /** Resolve the normalized command name from bootstrap invocation arguments. */
65
59
  export declare function parseBootstrapCommandName(argv: string[]): string | undefined;
66
60
  /** Implements apply bootstrap pager policy for the public runtime surface of this module. */
67
61
  export declare function applyBootstrapPagerPolicy(argv: string[]): () => void;
@@ -4,24 +4,14 @@
4
4
  * Provides public bootstrap argument normalization for embedded CLI hosts.
5
5
  */
6
6
 
7
- !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]="d45455ca-9496-5b8c-906c-d33d3d890e68")}catch(e){}}();
7
+ !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]="3d35c0f5-e1b8-5fd8-8fd7-c754a21784a1")}catch(e){}}();
8
8
  import { EXECUTABLE_COMMAND_ALIASES, PM_COMMAND_ALIAS_CONTRACTS, renderPmCommandAliasMigrationHint, resolvePmCommandAlias, resolveSubcommandFlagContractsForCommand, } from "./cli-contracts.js";
9
9
  export { EXECUTABLE_COMMAND_ALIASES, PM_COMMAND_ALIAS_CONTRACTS, renderPmCommandAliasMigrationHint, resolvePmCommandAlias, };
10
10
  import { levenshteinDistanceWithinLimit } from "../core/shared/levenshtein.js";
11
11
  import { EXIT_CODE } from "../core/shared/constants.js";
12
12
  import { PmCliError } from "../core/shared/errors.js";
13
13
  import { normalizeItemAddressInvocation } from "./agent/item-addressing.js";
14
- const GLOBAL_VALUE_CONSUMING_FLAGS = new Set([
15
- "--pm-path",
16
- "--path",
17
- "--author",
18
- "--output-include",
19
- "--output-limit",
20
- "--output-budget",
21
- "--output-format",
22
- "--output-session",
23
- "--output-cursor",
24
- ]);
14
+ import { BOOTSTRAP_BOOLEAN_FLAGS, GLOBAL_VALUE_CONSUMING_FLAGS, consumesBootstrapValue, findBootstrapCommandTokenIndex as findContractBootstrapCommandTokenIndex, isInlineGlobalValueToken, parseBootstrapCommandName as parseContractBootstrapCommandName, } from "./cli-contracts/bootstrap-command-scanner.js";
25
15
  const OUTPUT_VALUE_FLAGS = new Set([
26
16
  "--output-include",
27
17
  "--output-limit",
@@ -30,27 +20,6 @@ const OUTPUT_VALUE_FLAGS = new Set([
30
20
  "--output-session",
31
21
  "--output-cursor",
32
22
  ]);
33
- /** Whether a global value-consuming flag uses its inline `--flag=value` form. */
34
- const isInlineGlobalValueToken = (token) => {
35
- const equalsIndex = token.indexOf("=");
36
- return (equalsIndex > 0 &&
37
- GLOBAL_VALUE_CONSUMING_FLAGS.has(token.slice(0, equalsIndex)));
38
- };
39
- /** Whether a bootstrap value flag consumes its following token. */
40
- const consumesBootstrapValue = (flag, next) => {
41
- if (typeof next !== "string")
42
- return false;
43
- return flag === "--path" || flag === "--pm-path" || !next.startsWith("-");
44
- };
45
- const BOOTSTRAP_BOOLEAN_FLAGS = new Set([
46
- "--no-extensions",
47
- "--no-pager",
48
- "--json",
49
- "--quiet",
50
- "--lean",
51
- "--token-accounting",
52
- "--output-row-contract",
53
- ]);
54
23
  /** Consume one bootstrap-global token and update the accumulated parse state. */
55
24
  function consumeBootstrapGlobalToken(argv, index, state) {
56
25
  const token = argv[index];
@@ -196,41 +165,13 @@ export function parseBootstrapHelpRequest(argv) {
196
165
  commandPathTokens,
197
166
  };
198
167
  }
199
- /**
200
- * Index of the command token in argv — the first non-flag token, skipping the
201
- * value-consuming/global bootstrap flags. Returns undefined when there is none
202
- * (bare invocation, only global flags, or a leading `--`). Single source of truth
203
- * for command-position scanning shared by {@link parseBootstrapCommandName} and the
204
- * command-alias rewrite so their precedence rules can never drift apart.
205
- */
168
+ /** Locate the command token after global bootstrap flags and their values. */
206
169
  export function findBootstrapCommandTokenIndex(argv) {
207
- for (let index = 0; index < argv.length; index += 1) {
208
- const token = argv[index];
209
- if (token === "--") {
210
- return undefined;
211
- }
212
- if (GLOBAL_VALUE_CONSUMING_FLAGS.has(token)) {
213
- index += consumesBootstrapValue(token, argv[index + 1]) ? 1 : 0;
214
- continue;
215
- }
216
- if (isInlineGlobalValueToken(token) ||
217
- BOOTSTRAP_BOOLEAN_FLAGS.has(token) ||
218
- token === "--profile" ||
219
- token === "--id-only" ||
220
- token === "--explain") {
221
- continue;
222
- }
223
- if (token.startsWith("-")) {
224
- continue;
225
- }
226
- return index;
227
- }
228
- return undefined;
170
+ return findContractBootstrapCommandTokenIndex(argv);
229
171
  }
230
- /** Implements parse bootstrap command name for the public runtime surface of this module. */
172
+ /** Resolve the normalized command name from bootstrap invocation arguments. */
231
173
  export function parseBootstrapCommandName(argv) {
232
- const index = findBootstrapCommandTokenIndex(argv);
233
- return index === undefined ? undefined : argv[index].trim().toLowerCase();
174
+ return parseContractBootstrapCommandName(argv);
234
175
  }
235
176
  function shouldDisablePagerForInvocation(argv, bootstrapGlobal) {
236
177
  if (bootstrapGlobal.noPager) {
@@ -895,4 +836,4 @@ export const _testOnly = {
895
836
  resolveCanonicalFlag,
896
837
  };
897
838
  //# sourceMappingURL=cli-bootstrap.js.map
898
- //# debugId=d45455ca-9496-5b8c-906c-d33d3d890e68
839
+ //# debugId=3d35c0f5-e1b8-5fd8-8fd7-c754a21784a1
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @module sdk/cli-contracts/bootstrap-command-scanner
3
+ *
4
+ * Resolves command position from shell-free argv without loading CLI runtime
5
+ * normalization, error, filesystem, or item-addressing dependencies.
6
+ */
7
+ /** Global options that consume a following value when one is present. */
8
+ export declare const GLOBAL_VALUE_CONSUMING_FLAGS: Set<string>;
9
+ /** Boolean global options ignored while locating the command token. */
10
+ export declare const BOOTSTRAP_BOOLEAN_FLAGS: Set<string>;
11
+ /** Whether a global value-consuming flag uses its inline `--flag=value` form. */
12
+ export declare function isInlineGlobalValueToken(token: string): boolean;
13
+ /** Whether a bootstrap value flag consumes its following token. */
14
+ export declare function consumesBootstrapValue(flag: string, next: string | undefined): boolean;
15
+ /**
16
+ * Locate the first command token after global flags and their values.
17
+ *
18
+ * A leading `--` terminates command discovery. Unknown flags are ignored so
19
+ * later command-specific validation can return the canonical diagnostic.
20
+ */
21
+ export declare function findBootstrapCommandTokenIndex(argv: readonly string[]): number | undefined;
22
+ /** Resolve the normalized command name from shell-free invocation arguments. */
23
+ export declare function parseBootstrapCommandName(argv: readonly string[]): string | undefined;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * @module sdk/cli-contracts/bootstrap-command-scanner
3
+ *
4
+ * Resolves command position from shell-free argv without loading CLI runtime
5
+ * normalization, error, filesystem, or item-addressing dependencies.
6
+ */
7
+ /** Global options that consume a following value when one is present. */
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]="9d04e30a-caf5-59b4-8853-9df39c1728aa")}catch(e){}}();
10
+ export const GLOBAL_VALUE_CONSUMING_FLAGS = new Set([
11
+ "--pm-path",
12
+ "--path",
13
+ "--author",
14
+ "--output-include",
15
+ "--output-limit",
16
+ "--output-budget",
17
+ "--output-format",
18
+ "--output-session",
19
+ "--output-cursor",
20
+ ]);
21
+ /** Boolean global options ignored while locating the command token. */
22
+ export const BOOTSTRAP_BOOLEAN_FLAGS = new Set([
23
+ "--no-extensions",
24
+ "--no-pager",
25
+ "--json",
26
+ "--quiet",
27
+ "--lean",
28
+ "--token-accounting",
29
+ "--output-row-contract",
30
+ "--all",
31
+ ]);
32
+ /** Whether a global value-consuming flag uses its inline `--flag=value` form. */
33
+ export function isInlineGlobalValueToken(token) {
34
+ const equalsIndex = token.indexOf("=");
35
+ return (equalsIndex > 0 &&
36
+ GLOBAL_VALUE_CONSUMING_FLAGS.has(token.slice(0, equalsIndex)));
37
+ }
38
+ /** Whether a bootstrap value flag consumes its following token. */
39
+ export function consumesBootstrapValue(flag, next) {
40
+ if (typeof next !== "string")
41
+ return false;
42
+ return flag === "--path" || flag === "--pm-path" || !next.startsWith("-");
43
+ }
44
+ /**
45
+ * Locate the first command token after global flags and their values.
46
+ *
47
+ * A leading `--` terminates command discovery. Unknown flags are ignored so
48
+ * later command-specific validation can return the canonical diagnostic.
49
+ */
50
+ export function findBootstrapCommandTokenIndex(argv) {
51
+ for (let index = 0; index < argv.length; index += 1) {
52
+ const token = argv[index];
53
+ if (token === "--") {
54
+ return undefined;
55
+ }
56
+ if (GLOBAL_VALUE_CONSUMING_FLAGS.has(token)) {
57
+ index += consumesBootstrapValue(token, argv[index + 1]) ? 1 : 0;
58
+ continue;
59
+ }
60
+ if (isInlineGlobalValueToken(token) ||
61
+ BOOTSTRAP_BOOLEAN_FLAGS.has(token) ||
62
+ token === "--profile" ||
63
+ token === "--id-only" ||
64
+ token === "--explain") {
65
+ continue;
66
+ }
67
+ if (token.startsWith("-")) {
68
+ continue;
69
+ }
70
+ return index;
71
+ }
72
+ return undefined;
73
+ }
74
+ /** Resolve the normalized command name from shell-free invocation arguments. */
75
+ export function parseBootstrapCommandName(argv) {
76
+ const index = findBootstrapCommandTokenIndex(argv);
77
+ return index === undefined ? undefined : argv[index].trim().toLowerCase();
78
+ }
79
+ //# sourceMappingURL=bootstrap-command-scanner.js.map
80
+ //# debugId=9d04e30a-caf5-59b4-8853-9df39c1728aa