@deftai/directive-core 0.106.0 → 0.108.0

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 (249) hide show
  1. package/dist/architecture/sor-preflight.js +2 -0
  2. package/dist/check/cached-orchestrator.js +28 -3
  3. package/dist/check/gate-lists.js +2 -0
  4. package/dist/check/named-cause.js +18 -3
  5. package/dist/codebase/provider.js +7 -1
  6. package/dist/delivery-attempt/handoff.js +1 -1
  7. package/dist/design-critique/citation-grammar.d.ts +53 -0
  8. package/dist/design-critique/citation-grammar.js +303 -0
  9. package/dist/design-critique/completed-arc-record.d.ts +62 -0
  10. package/dist/design-critique/completed-arc-record.js +232 -0
  11. package/dist/design-critique/exclusive-chip.d.ts +33 -0
  12. package/dist/design-critique/exclusive-chip.js +68 -0
  13. package/dist/design-critique/parent-audit.d.ts +59 -0
  14. package/dist/design-critique/parent-audit.js +121 -0
  15. package/dist/doctor/checks.d.ts +6 -0
  16. package/dist/doctor/checks.js +35 -0
  17. package/dist/freshness/bind.d.ts +32 -3
  18. package/dist/freshness/bind.js +58 -12
  19. package/dist/hooks/classify/host-session-identity.d.ts +76 -0
  20. package/dist/hooks/classify/host-session-identity.js +470 -0
  21. package/dist/hooks/classify/index.d.ts +3 -2
  22. package/dist/hooks/classify/index.js +3 -2
  23. package/dist/hooks/classify/paths.d.ts +7 -0
  24. package/dist/hooks/classify/paths.js +35 -0
  25. package/dist/hooks/classify/stdin.d.ts +5 -0
  26. package/dist/hooks/classify/stdin.js +27 -0
  27. package/dist/hooks/dest-form.d.ts +46 -0
  28. package/dist/hooks/dest-form.js +575 -0
  29. package/dist/hooks/dispatcher.d.ts +69 -2
  30. package/dist/hooks/dispatcher.js +609 -45
  31. package/dist/hooks/fixtures/cases.d.ts +16 -2
  32. package/dist/hooks/fixtures/cases.js +175 -0
  33. package/dist/hooks/index.d.ts +1 -0
  34. package/dist/hooks/index.js +1 -0
  35. package/dist/hooks/scope.js +3 -1
  36. package/dist/init-deposit/agent-hooks.d.ts +2 -1
  37. package/dist/init-deposit/agent-hooks.js +8 -1
  38. package/dist/init-deposit/hook-runtime-travel.d.ts +77 -0
  39. package/dist/init-deposit/hook-runtime-travel.js +269 -0
  40. package/dist/intake/clause-derivation.js +9 -3
  41. package/dist/intake/github-auth-modes-cli.js +14 -2
  42. package/dist/intake/github-auth-modes.d.ts +54 -9
  43. package/dist/intake/github-auth-modes.js +326 -123
  44. package/dist/intake/issue-ingest.js +62 -2
  45. package/dist/intake/platform-capabilities.d.ts +9 -2
  46. package/dist/intake/platform-capabilities.js +38 -9
  47. package/dist/lifecycle/completed-tracked-on-delivery.d.ts +26 -0
  48. package/dist/lifecycle/completed-tracked-on-delivery.js +37 -14
  49. package/dist/lifecycle/completed-write-guard.d.ts +48 -0
  50. package/dist/lifecycle/completed-write-guard.js +373 -0
  51. package/dist/lifecycle/index.d.ts +1 -0
  52. package/dist/lifecycle/index.js +1 -0
  53. package/dist/literal-acceptance/capture.d.ts +16 -0
  54. package/dist/literal-acceptance/capture.js +75 -7
  55. package/dist/literal-acceptance/evaluate.js +25 -3
  56. package/dist/literal-acceptance/index.d.ts +2 -2
  57. package/dist/literal-acceptance/index.js +2 -2
  58. package/dist/literal-acceptance/run.js +9 -3
  59. package/dist/literal-acceptance/types.d.ts +6 -0
  60. package/dist/literal-acceptance/types.js +6 -0
  61. package/dist/orphan-active/evaluate.d.ts +25 -0
  62. package/dist/orphan-active/evaluate.js +193 -128
  63. package/dist/orphan-active/index.d.ts +1 -0
  64. package/dist/orphan-active/index.js +1 -0
  65. package/dist/orphan-active/issue-state.d.ts +121 -0
  66. package/dist/orphan-active/issue-state.js +278 -0
  67. package/dist/platform/cursor-managed-runtime.d.ts +95 -0
  68. package/dist/platform/cursor-managed-runtime.js +241 -0
  69. package/dist/platform/index.d.ts +1 -0
  70. package/dist/platform/index.js +1 -0
  71. package/dist/platform/platform-capabilities.d.ts +23 -1
  72. package/dist/platform/platform-capabilities.js +55 -15
  73. package/dist/policy/ceremony-dial.js +5 -9
  74. package/dist/policy/host-hooks.js +4 -9
  75. package/dist/policy/org-force-on-migration.js +5 -10
  76. package/dist/policy/plan-extensions.d.ts +14 -2
  77. package/dist/policy/plan-extensions.js +24 -3
  78. package/dist/policy/product-signal.js +5 -10
  79. package/dist/policy/require-human-merge.js +5 -9
  80. package/dist/policy/resolve.js +77 -16
  81. package/dist/policy/runtime-authority.d.ts +18 -0
  82. package/dist/policy/runtime-authority.js +11 -0
  83. package/dist/policy/value-feedback.js +9 -18
  84. package/dist/policy/write-fence.js +3 -0
  85. package/dist/pr-closeout-attestable/evaluate.d.ts +80 -0
  86. package/dist/pr-closeout-attestable/evaluate.js +306 -0
  87. package/dist/pr-closeout-attestable/index.d.ts +2 -0
  88. package/dist/pr-closeout-attestable/index.js +2 -0
  89. package/dist/pr-protected-issues/gh.d.ts +6 -2
  90. package/dist/pr-protected-issues/gh.js +7 -3
  91. package/dist/pr-wait-mergeable/cascade.d.ts +9 -1
  92. package/dist/pr-wait-mergeable/cascade.js +21 -1
  93. package/dist/pr-wait-mergeable/types.d.ts +2 -0
  94. package/dist/pr-wait-mergeable/wrappers.d.ts +6 -0
  95. package/dist/pr-wait-mergeable/wrappers.js +11 -0
  96. package/dist/preflight/evaluate.d.ts +15 -0
  97. package/dist/preflight/evaluate.js +29 -3
  98. package/dist/preflight-cache/evaluate.js +9 -3
  99. package/dist/product-first-done-gate/acceptance-resolver.d.ts +14 -2
  100. package/dist/product-first-done-gate/acceptance-resolver.js +13 -2
  101. package/dist/product-first-done-gate/evaluate.js +53 -12
  102. package/dist/release/cli-drift-report.d.ts +68 -0
  103. package/dist/release/cli-drift-report.js +189 -0
  104. package/dist/release/index.d.ts +1 -0
  105. package/dist/release/index.js +1 -0
  106. package/dist/release/issue-state-fetch.d.ts +5 -3
  107. package/dist/release/issue-state-fetch.js +86 -21
  108. package/dist/release/native-steps.js +1 -0
  109. package/dist/release/pipeline.js +19 -0
  110. package/dist/release/types.d.ts +14 -0
  111. package/dist/render/constants.d.ts +4 -0
  112. package/dist/render/constants.js +11 -8
  113. package/dist/render/export-spec.js +31 -5
  114. package/dist/render/index.d.ts +1 -1
  115. package/dist/render/index.js +1 -1
  116. package/dist/render/prd-render.d.ts +4 -1
  117. package/dist/render/prd-render.js +82 -23
  118. package/dist/render/project-render.js +14 -7
  119. package/dist/render/scope-outlook.d.ts +2 -0
  120. package/dist/render/scope-outlook.js +3 -0
  121. package/dist/render/spec-render.js +2 -2
  122. package/dist/resolution/package-manager.d.ts +33 -4
  123. package/dist/resolution/package-manager.js +210 -9
  124. package/dist/review-monitor/constants.d.ts +7 -0
  125. package/dist/review-monitor/constants.js +7 -0
  126. package/dist/review-monitor/github-lease.d.ts +98 -1
  127. package/dist/review-monitor/github-lease.js +182 -1
  128. package/dist/review-monitor/lease-comment.d.ts +36 -0
  129. package/dist/review-monitor/lease-comment.js +103 -2
  130. package/dist/scm/call.js +12 -3
  131. package/dist/scm/design-critique-chip.d.ts +38 -0
  132. package/dist/scm/design-critique-chip.js +187 -0
  133. package/dist/scm/gh-rest.d.ts +9 -1
  134. package/dist/scm/gh-rest.js +103 -0
  135. package/dist/scm/index.d.ts +1 -0
  136. package/dist/scm/index.js +1 -0
  137. package/dist/scm/main.d.ts +3 -0
  138. package/dist/scm/main.js +15 -1
  139. package/dist/scm/readiness-cli.d.ts +2 -0
  140. package/dist/scm/readiness-cli.js +42 -1
  141. package/dist/scm/readiness.d.ts +4 -1
  142. package/dist/scm/readiness.js +35 -5
  143. package/dist/scope/decompose.js +2 -1
  144. package/dist/scope/delivery-evidence.d.ts +27 -1
  145. package/dist/scope/index.d.ts +1 -0
  146. package/dist/scope/index.js +1 -0
  147. package/dist/scope/lifecycle-write.d.ts +24 -0
  148. package/dist/scope/lifecycle-write.js +64 -0
  149. package/dist/scope/main.js +3 -1
  150. package/dist/scope/project-definition-sync.js +14 -7
  151. package/dist/scope/transition.js +90 -11
  152. package/dist/scope-provenance/evaluate.js +5 -1
  153. package/dist/session/git.d.ts +42 -0
  154. package/dist/session/git.js +219 -3
  155. package/dist/session/occupancy.d.ts +239 -12
  156. package/dist/session/occupancy.js +820 -27
  157. package/dist/session/ritual-sentinel.d.ts +5 -0
  158. package/dist/session/ritual-sentinel.js +5 -0
  159. package/dist/session/session-ready.d.ts +5 -1
  160. package/dist/session/session-ready.js +98 -8
  161. package/dist/session/session-start.d.ts +17 -1
  162. package/dist/session/session-start.js +49 -17
  163. package/dist/session/toolchain-preflight.d.ts +13 -3
  164. package/dist/session/toolchain-preflight.js +93 -18
  165. package/dist/session/verify-session-ritual.d.ts +33 -3
  166. package/dist/session/verify-session-ritual.js +89 -19
  167. package/dist/slice/constants.d.ts +1 -1
  168. package/dist/spec-authority/constants.d.ts +10 -2
  169. package/dist/spec-authority/constants.js +53 -8
  170. package/dist/spec-authority/resolver.d.ts +3 -0
  171. package/dist/spec-authority/resolver.js +55 -7
  172. package/dist/subprocess/max-buffer.d.ts +14 -0
  173. package/dist/subprocess/max-buffer.js +15 -0
  174. package/dist/swarm/complete-cohort.d.ts +2 -0
  175. package/dist/swarm/complete-cohort.js +21 -13
  176. package/dist/swarm/index.d.ts +1 -0
  177. package/dist/swarm/index.js +1 -0
  178. package/dist/swarm/launch-cli.js +53 -33
  179. package/dist/swarm/launch.d.ts +77 -0
  180. package/dist/swarm/launch.js +248 -38
  181. package/dist/swarm/pre-dispatch-cli.js +2 -1
  182. package/dist/swarm/pre-dispatch.js +10 -1
  183. package/dist/swarm/subagent-status-dir.d.ts +27 -0
  184. package/dist/swarm/subagent-status-dir.js +42 -0
  185. package/dist/swarm/worktrees.d.ts +17 -3
  186. package/dist/swarm/worktrees.js +48 -4
  187. package/dist/triage/actions/index.d.ts +4 -0
  188. package/dist/triage/actions/index.js +6 -0
  189. package/dist/triage/evaluate/evaluate.d.ts +11 -0
  190. package/dist/triage/evaluate/evaluate.js +169 -0
  191. package/dist/triage/evaluate/github.d.ts +16 -0
  192. package/dist/triage/evaluate/github.js +153 -0
  193. package/dist/triage/evaluate/index.d.ts +9 -0
  194. package/dist/triage/evaluate/index.js +8 -0
  195. package/dist/triage/evaluate/paths.d.ts +7 -0
  196. package/dist/triage/evaluate/paths.js +25 -0
  197. package/dist/triage/evaluate/sink.d.ts +5 -0
  198. package/dist/triage/evaluate/sink.js +52 -0
  199. package/dist/triage/evaluate/types.d.ts +93 -0
  200. package/dist/triage/evaluate/types.js +13 -0
  201. package/dist/triage/evaluate/validity.d.ts +8 -0
  202. package/dist/triage/evaluate/validity.js +87 -0
  203. package/dist/triage/evaluate/value.d.ts +12 -0
  204. package/dist/triage/evaluate/value.js +33 -0
  205. package/dist/triage/evaluate/wip-census.d.ts +5 -0
  206. package/dist/triage/evaluate/wip-census.js +39 -0
  207. package/dist/triage/evaluate/worktrees.d.ts +8 -0
  208. package/dist/triage/evaluate/worktrees.js +68 -0
  209. package/dist/triage/evaluate/xbrief-refs.d.ts +8 -0
  210. package/dist/triage/evaluate/xbrief-refs.js +60 -0
  211. package/dist/triage/help/registry-data.d.ts +21 -7
  212. package/dist/triage/help/registry-data.js +53 -5
  213. package/dist/triage/index.d.ts +1 -0
  214. package/dist/triage/index.js +1 -0
  215. package/dist/triage/scope/mutations-core.d.ts +2 -6
  216. package/dist/triage/scope/mutations-core.js +23 -55
  217. package/dist/triage/scope-drift/add-ignore.js +5 -39
  218. package/dist/triage/subscribe/index.d.ts +2 -6
  219. package/dist/triage/subscribe/index.js +15 -65
  220. package/dist/triage/welcome/writers.js +15 -74
  221. package/dist/value/feedback-file.d.ts +17 -2
  222. package/dist/value/feedback-file.js +80 -6
  223. package/dist/vbrief-build/index.d.ts +2 -1
  224. package/dist/vbrief-build/index.js +2 -1
  225. package/dist/vbrief-build/parity-scenarios.js +5 -5
  226. package/dist/vbrief-build/project-definition-io.d.ts +63 -3
  227. package/dist/vbrief-build/project-definition-io.js +357 -31
  228. package/dist/vbrief-build/project-definition-mutation.d.ts +32 -0
  229. package/dist/vbrief-build/project-definition-mutation.js +43 -0
  230. package/dist/vbrief-reconcile/labels.d.ts +1 -0
  231. package/dist/vbrief-reconcile/labels.js +30 -0
  232. package/dist/vbrief-validate/conformance.d.ts +1 -0
  233. package/dist/vbrief-validate/conformance.js +85 -8
  234. package/dist/vbrief-validate/main.js +2 -0
  235. package/dist/vbrief-validate/precutover.js +5 -10
  236. package/dist/vbrief-validation/story-quality.d.ts +7 -0
  237. package/dist/vbrief-validation/story-quality.js +8 -1
  238. package/dist/verify-ac/clauses.d.ts +62 -2
  239. package/dist/verify-ac/clauses.js +183 -111
  240. package/dist/verify-ac/index.d.ts +1 -1
  241. package/dist/verify-ac/index.js +1 -1
  242. package/dist/verify-env/node-runtime.d.ts +8 -4
  243. package/dist/verify-env/node-runtime.js +9 -6
  244. package/dist/verify-env/toolchain-check.d.ts +35 -3
  245. package/dist/verify-env/toolchain-check.js +155 -36
  246. package/dist/verify-source/project-definition-mutation-boundary.d.ts +104 -0
  247. package/dist/verify-source/project-definition-mutation-boundary.js +326 -0
  248. package/dist/xbrief-migrate/agents-header.js +69 -7
  249. package/package.json +7 -3
@@ -1,3 +1,4 @@
1
+ import { PASS_MARKER_KIND } from "./constants.js";
1
2
  import type { PlatformPrimitive } from "./tier-detection.js";
2
3
  export declare function parseIso8601Utc(value: string): Date | null;
3
4
  export interface ReviewOwnerLease {
@@ -33,4 +34,39 @@ export declare function findActiveLeaseComment(comments: readonly ReviewOwnerCom
33
34
  now?: Date;
34
35
  headSha?: string | null;
35
36
  }): ReviewOwnerComment | null;
37
+ /**
38
+ * Advisory pass-open mark on an issue thread (#3607).
39
+ *
40
+ * Observe-and-mark only: it records that a pass is open, who owns it, the declared
41
+ * ceiling comment, and when the mark expires. It never holds, blocks, or gates
42
+ * another actor's write -- an arriving agent reads it and decides for itself.
43
+ */
44
+ export interface PassOpenMarker {
45
+ readonly kind: typeof PASS_MARKER_KIND;
46
+ readonly pass_kind: string;
47
+ readonly owner: string;
48
+ readonly agent_id: string | null;
49
+ readonly ceiling: string | null;
50
+ readonly started_at: string;
51
+ readonly expires_at: string;
52
+ readonly ended_at: string | null;
53
+ }
54
+ export interface PassOpenComment {
55
+ readonly id: number;
56
+ readonly body: string;
57
+ readonly createdAt: string;
58
+ /** GitHub login that authored the comment; "" when the source did not report one. */
59
+ readonly authorLogin: string;
60
+ readonly marker: PassOpenMarker | null;
61
+ }
62
+ export declare function parsePassOpenMarker(body: string): PassOpenMarker | null;
63
+ export declare function renderPassOpenComment(marker: PassOpenMarker): string;
64
+ /** Expired or synthesis-cleared marks are ignored on read; a mark self-clears (#3607). */
65
+ export declare function isPassMarkerActive(marker: PassOpenMarker, now?: Date): boolean;
66
+ export declare function mapPassCommentEntry(entry: unknown): PassOpenComment | null;
67
+ /** Oldest comment id wins when two marks race, matching the lease (#2814 / #3607). */
68
+ export declare function selectWinningPassComment(comments: readonly PassOpenComment[]): PassOpenComment | null;
69
+ export declare function findActivePassComment(comments: readonly PassOpenComment[], options?: {
70
+ now?: Date;
71
+ }): PassOpenComment | null;
36
72
  //# sourceMappingURL=lease-comment.d.ts.map
@@ -1,4 +1,4 @@
1
- import { DEFAULT_STALE_MINUTES, REVIEW_OWNER_MARKER_END, REVIEW_OWNER_MARKER_START, } from "./constants.js";
1
+ import { DEFAULT_STALE_MINUTES, PASS_MARKER_KIND, REVIEW_OWNER_MARKER_END, REVIEW_OWNER_MARKER_START, } from "./constants.js";
2
2
  export function parseIso8601Utc(value) {
3
3
  if (typeof value !== "string" || value.length === 0) {
4
4
  return null;
@@ -17,7 +17,7 @@ export function parseIso8601Utc(value) {
17
17
  }
18
18
  return parsed;
19
19
  }
20
- const FIELD_RE = /^(owner|monitor_agent_id|head_sha|started_at|expires_at|platform_primitive|ended_at):\s*(.*)$/;
20
+ const FIELD_RE = /^(kind|owner|monitor_agent_id|agent_id|pass_kind|ceiling|head_sha|started_at|expires_at|platform_primitive|ended_at):\s*(.*)$/;
21
21
  /** True when the comment body contains the review-owner marker block. */
22
22
  export function hasReviewOwnerMarker(body) {
23
23
  return body.includes(REVIEW_OWNER_MARKER_START);
@@ -42,8 +42,17 @@ function parseFieldBlock(body) {
42
42
  }
43
43
  return fields;
44
44
  }
45
+ /** Marker `kind:` value, or "" when the block declares none (ownership-lease shape). */
46
+ function markerKind(body) {
47
+ return parseFieldBlock(body).kind ?? "";
48
+ }
45
49
  export function parseReviewOwnerLease(body) {
46
50
  const fields = parseFieldBlock(body);
51
+ // An advisory pass mark shares the marker but must never satisfy the
52
+ // review-monitor ownership gate (#3607).
53
+ if ((fields.kind ?? "") === PASS_MARKER_KIND) {
54
+ return null;
55
+ }
47
56
  const owner = fields.owner ?? "";
48
57
  const monitorAgentId = fields.monitor_agent_id ?? "";
49
58
  const startedAt = fields.started_at ?? "";
@@ -128,6 +137,11 @@ export function mapCommentEntry(entry) {
128
137
  if (!hasReviewOwnerMarker(rec.body)) {
129
138
  return null;
130
139
  }
140
+ // Pass marks are a disjoint population on the same marker; excluding them here
141
+ // keeps `registerReviewMonitor` from overwriting one as its lease anchor (#3607).
142
+ if (markerKind(rec.body) === PASS_MARKER_KIND) {
143
+ return null;
144
+ }
131
145
  return {
132
146
  id: rec.id,
133
147
  body: rec.body,
@@ -149,4 +163,91 @@ export function findActiveLeaseComment(comments, options = {}) {
149
163
  }
150
164
  return selectWinningReviewOwnerComment(active);
151
165
  }
166
+ export function parsePassOpenMarker(body) {
167
+ if (!hasReviewOwnerMarker(body)) {
168
+ return null;
169
+ }
170
+ const fields = parseFieldBlock(body);
171
+ if ((fields.kind ?? "") !== PASS_MARKER_KIND) {
172
+ return null;
173
+ }
174
+ const owner = fields.owner ?? "";
175
+ const passKind = fields.pass_kind ?? "";
176
+ const startedAt = fields.started_at ?? "";
177
+ const expiresAt = fields.expires_at ?? "";
178
+ if (owner.length === 0 ||
179
+ passKind.length === 0 ||
180
+ startedAt.length === 0 ||
181
+ expiresAt.length === 0) {
182
+ return null;
183
+ }
184
+ const agentId = fields.agent_id ?? "";
185
+ const ceiling = fields.ceiling ?? "";
186
+ const endedAt = fields.ended_at ?? "";
187
+ return {
188
+ kind: PASS_MARKER_KIND,
189
+ pass_kind: passKind,
190
+ owner,
191
+ agent_id: agentId.length > 0 ? agentId : null,
192
+ ceiling: ceiling.length > 0 ? ceiling : null,
193
+ started_at: startedAt,
194
+ expires_at: expiresAt,
195
+ ended_at: endedAt.length > 0 ? endedAt : null,
196
+ };
197
+ }
198
+ export function renderPassOpenComment(marker) {
199
+ const optional = (name, value) => value !== null && value.length > 0 ? `${name}: ${value}\n` : "";
200
+ return (`${REVIEW_OWNER_MARKER_START}\n` +
201
+ `kind: ${PASS_MARKER_KIND}\n` +
202
+ `pass_kind: ${marker.pass_kind}\n` +
203
+ `owner: ${marker.owner}\n` +
204
+ optional("agent_id", marker.agent_id) +
205
+ optional("ceiling", marker.ceiling) +
206
+ `started_at: ${marker.started_at}\n` +
207
+ `expires_at: ${marker.expires_at}\n` +
208
+ optional("ended_at", marker.ended_at) +
209
+ `${REVIEW_OWNER_MARKER_END}`);
210
+ }
211
+ /** Expired or synthesis-cleared marks are ignored on read; a mark self-clears (#3607). */
212
+ export function isPassMarkerActive(marker, now = new Date()) {
213
+ if (marker.ended_at !== null) {
214
+ return false;
215
+ }
216
+ const expires = parseIso8601Utc(marker.expires_at);
217
+ if (expires === null) {
218
+ return false;
219
+ }
220
+ return now.getTime() <= expires.getTime();
221
+ }
222
+ export function mapPassCommentEntry(entry) {
223
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
224
+ return null;
225
+ }
226
+ const rec = entry;
227
+ if (typeof rec.id !== "number" || typeof rec.body !== "string") {
228
+ return null;
229
+ }
230
+ const marker = parsePassOpenMarker(rec.body);
231
+ if (marker === null) {
232
+ return null;
233
+ }
234
+ return {
235
+ id: rec.id,
236
+ body: rec.body,
237
+ createdAt: typeof rec.created_at === "string" ? rec.created_at : "",
238
+ authorLogin: typeof rec.author_login === "string" ? rec.author_login : "",
239
+ marker,
240
+ };
241
+ }
242
+ /** Oldest comment id wins when two marks race, matching the lease (#2814 / #3607). */
243
+ export function selectWinningPassComment(comments) {
244
+ if (comments.length === 0) {
245
+ return null;
246
+ }
247
+ return [...comments].sort((a, b) => a.id - b.id)[0] ?? null;
248
+ }
249
+ export function findActivePassComment(comments, options = {}) {
250
+ const active = comments.filter((comment) => comment.marker !== null && isPassMarkerActive(comment.marker, options.now));
251
+ return selectWinningPassComment(active);
252
+ }
152
253
  //# sourceMappingURL=lease-comment.js.map
package/dist/scm/call.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { spawnSync } from "node:child_process";
2
+ import { resolveCaptureFailureStderr, SUBPROCESS_MAX_BUFFER } from "../subprocess/max-buffer.js";
2
3
  import { resolveBinary } from "./binary.js";
3
4
  import { SUPPORTED_CALL_SOURCES } from "./constants.js";
4
5
  import { pyRepr } from "./py-format.js";
@@ -26,18 +27,26 @@ export function call(source, verb, args = null, options = {}) {
26
27
  input: options.input,
27
28
  encoding: (options.text ?? true) ? "utf8" : undefined,
28
29
  timeout: timeoutMs,
30
+ maxBuffer: SUBPROCESS_MAX_BUFFER,
29
31
  stdio: captureOutput ? ["pipe", "pipe", "pipe"] : "inherit",
30
32
  });
33
+ // A spawn-level failure (ENOBUFS past maxBuffer, timeout kill) yields a null
34
+ // status and empty stderr; surface error.message so callers never report a
35
+ // bare exit 1 with no reason (#1867 / #3903).
36
+ const stderr = resolveCaptureFailureStderr({
37
+ captured: typeof result.stderr === "string" ? result.stderr : "",
38
+ status: result.status,
39
+ message: result.error?.message,
40
+ });
31
41
  if (options.check && result.status !== 0) {
32
- const message = typeof result.stderr === "string" ? result.stderr : "";
33
- const error = new Error(message || `Process exited with code ${result.status}`);
42
+ const error = new Error(stderr || `Process exited with code ${result.status}`);
34
43
  throw error;
35
44
  }
36
45
  return {
37
46
  args: argv,
38
47
  returncode: result.status ?? 1,
39
48
  stdout: typeof result.stdout === "string" ? result.stdout : "",
40
- stderr: typeof result.stderr === "string" ? result.stderr : "",
49
+ stderr,
41
50
  };
42
51
  }
43
52
  //# sourceMappingURL=call.js.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Chip-only remaining-set write for design-critique catalog labels (#3642).
3
+ *
4
+ * Parent attach of triage-ready / recut mechanism-shaped MUST use this verb,
5
+ * not `gh api POST .../labels` and not additive `scm:issue:edit --add-label`.
6
+ */
7
+ import { type DesignCritiqueCatalogChip } from "../design-critique/exclusive-chip.js";
8
+ import type { LabelClient } from "../vbrief-reconcile/types.js";
9
+ export declare const DESIGN_CRITIQUE_CHIP_VERB: "design-critique-chip";
10
+ export declare const CHIP_APPLY_MISS_TOKEN = "chip apply missed (non-blocking convenience)";
11
+ export declare const DESIGN_CRITIQUE_CHIP_USAGE: string;
12
+ export interface DesignCritiqueChipArgs {
13
+ readonly issue: number;
14
+ readonly chip: DesignCritiqueCatalogChip;
15
+ readonly repo: string | null;
16
+ readonly json: boolean;
17
+ }
18
+ export interface DesignCritiqueChipSeams {
19
+ readonly client?: LabelClient;
20
+ /** Default OWNER/NAME when --repo is omitted (git origin). */
21
+ readonly resolveDefaultRepo?: () => string | null;
22
+ }
23
+ export interface DesignCritiqueChipResult {
24
+ readonly exitCode: number;
25
+ readonly stdout: string;
26
+ readonly stderr: string;
27
+ }
28
+ /** Fail-closed chip name. Closed catalog only. */
29
+ export declare function resolveDesignCritiqueChipArg(raw: string): DesignCritiqueCatalogChip;
30
+ export declare function parseDesignCritiqueChipArgs(extra: readonly string[]): DesignCritiqueChipArgs;
31
+ /** Resolve OWNER/NAME from `git remote get-url origin`. */
32
+ export declare function resolveRepoFromGitOrigin(): string | null;
33
+ /**
34
+ * GET current labels, remaining-set replace via applyDesignCritiqueCatalogChip.
35
+ * One LabelClient.apply write. Other facets stay.
36
+ */
37
+ export declare function runDesignCritiqueChip(extra: readonly string[], seams?: DesignCritiqueChipSeams): DesignCritiqueChipResult;
38
+ //# sourceMappingURL=design-critique-chip.d.ts.map
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Chip-only remaining-set write for design-critique catalog labels (#3642).
3
+ *
4
+ * Parent attach of triage-ready / recut mechanism-shaped MUST use this verb,
5
+ * not `gh api POST .../labels` and not additive `scm:issue:edit --add-label`.
6
+ */
7
+ import { spawnSync } from "node:child_process";
8
+ import { applyDesignCritiqueCatalogChip, } from "../design-critique/exclusive-chip.js";
9
+ import { parseGithubOwnerRepo } from "../policy/sync-default.js";
10
+ import { ScmLabelClient } from "../vbrief-reconcile/labels.js";
11
+ import { extractFlag, extractValueFlag } from "./argv.js";
12
+ import { InvalidRepoError, splitRepo } from "./gh-rest.js";
13
+ import { pyRepr } from "./py-format.js";
14
+ export const DESIGN_CRITIQUE_CHIP_VERB = "design-critique-chip";
15
+ export const CHIP_APPLY_MISS_TOKEN = "chip apply missed (non-blocking convenience)";
16
+ export const DESIGN_CRITIQUE_CHIP_USAGE = "usage: scm issue design-critique-chip --issue N --chip triage-ready|mechanism-shaped [--repo OWNER/NAME] [--json]\n" +
17
+ " Parent attach of design-critique:triage-ready / recut mechanism-shaped.\n" +
18
+ " Closed catalog remaining-set replace. One write. Other facets stay.\n" +
19
+ " Apply miss is non-blocking convenience; ingest is not blocked.\n";
20
+ const CHIP_ALIASES = {
21
+ "triage-ready": "design-critique:triage-ready",
22
+ "mechanism-shaped": "design-critique:mechanism-shaped",
23
+ "design-critique:triage-ready": "design-critique:triage-ready",
24
+ "design-critique:mechanism-shaped": "design-critique:mechanism-shaped",
25
+ };
26
+ /** Fail-closed chip name. Closed catalog only. */
27
+ export function resolveDesignCritiqueChipArg(raw) {
28
+ const chip = CHIP_ALIASES[raw];
29
+ if (chip === undefined) {
30
+ throw new Error(`unknown design-critique chip ${pyRepr(raw)}; expected triage-ready|mechanism-shaped ` +
31
+ "(or design-critique:triage-ready|design-critique:mechanism-shaped)");
32
+ }
33
+ return chip;
34
+ }
35
+ function parseIssueNumber(raw, source) {
36
+ const issueN = Number.parseInt(raw, 10);
37
+ if (Number.isNaN(issueN) || issueN <= 0 || String(issueN) !== raw) {
38
+ throw new Error(`${source} must be a positive integer; got ${pyRepr(raw)}`);
39
+ }
40
+ return issueN;
41
+ }
42
+ export function parseDesignCritiqueChipArgs(extra) {
43
+ let remainder = [...extra];
44
+ const [help] = extractFlag(remainder, "--help");
45
+ const [helpShort] = extractFlag(remainder, "-h");
46
+ if (help || helpShort) {
47
+ throw new ChipUsageError(DESIGN_CRITIQUE_CHIP_USAGE.trimEnd());
48
+ }
49
+ const [json, afterJson] = extractFlag(remainder, "--json");
50
+ remainder = afterJson;
51
+ const [repoRaw, afterRepo] = extractValueFlag(remainder, "--repo");
52
+ remainder = afterRepo;
53
+ const [chipRaw, afterChip] = extractValueFlag(remainder, "--chip");
54
+ remainder = afterChip;
55
+ const [issueFlag, afterIssue] = extractValueFlag(remainder, "--issue");
56
+ remainder = afterIssue;
57
+ const leftoverFlags = remainder.filter((t) => t.startsWith("-"));
58
+ if (leftoverFlags.length > 0) {
59
+ throw new Error(`unrecognized flags: ${pyRepr(leftoverFlags)}. Supported: --issue, --chip, --repo, --json.`);
60
+ }
61
+ const positionals = remainder.filter((t) => !t.startsWith("-"));
62
+ if (chipRaw === null || chipRaw.length === 0) {
63
+ throw new Error("missing --chip triage-ready|mechanism-shaped");
64
+ }
65
+ const chip = resolveDesignCritiqueChipArg(chipRaw);
66
+ let issueRaw = issueFlag;
67
+ if (positionals.length > 1) {
68
+ throw new Error(`expected at most one positional issue number; got ${pyRepr(positionals)}`);
69
+ }
70
+ if (positionals.length === 1) {
71
+ const positional = positionals[0] ?? "";
72
+ if (issueRaw !== null && issueRaw !== positional) {
73
+ throw new Error(`--issue ${pyRepr(issueRaw)} conflicts with positional ${pyRepr(positional)}`);
74
+ }
75
+ issueRaw = positional;
76
+ }
77
+ if (issueRaw === null || issueRaw.length === 0) {
78
+ throw new Error("missing --issue N");
79
+ }
80
+ const issue = parseIssueNumber(issueRaw, "--issue");
81
+ if (repoRaw !== null && repoRaw.length > 0) {
82
+ splitRepo(repoRaw);
83
+ }
84
+ return { issue, chip, repo: repoRaw !== null && repoRaw.length > 0 ? repoRaw : null, json };
85
+ }
86
+ /** Resolve OWNER/NAME from `git remote get-url origin`. */
87
+ export function resolveRepoFromGitOrigin() {
88
+ const result = spawnSync("git", ["remote", "get-url", "origin"], {
89
+ encoding: "utf8",
90
+ env: process.env,
91
+ });
92
+ if (result.status !== 0)
93
+ return null;
94
+ const stdout = typeof result.stdout === "string" ? result.stdout : "";
95
+ return parseGithubOwnerRepo(stdout);
96
+ }
97
+ class ChipUsageError extends Error {
98
+ constructor(message) {
99
+ super(message);
100
+ this.name = "ChipUsageError";
101
+ }
102
+ }
103
+ /**
104
+ * GET current labels, remaining-set replace via applyDesignCritiqueCatalogChip.
105
+ * One LabelClient.apply write. Other facets stay.
106
+ */
107
+ export function runDesignCritiqueChip(extra, seams = {}) {
108
+ let args;
109
+ try {
110
+ args = parseDesignCritiqueChipArgs(extra);
111
+ }
112
+ catch (err) {
113
+ if (err instanceof ChipUsageError) {
114
+ return { exitCode: 0, stdout: `${err.message}\n`, stderr: "" };
115
+ }
116
+ if (err instanceof InvalidRepoError) {
117
+ return { exitCode: 2, stdout: "", stderr: `error: invalid --repo value: ${err.message}\n` };
118
+ }
119
+ const message = err instanceof Error ? err.message : String(err);
120
+ return { exitCode: 2, stdout: "", stderr: `error: ${message}\n` };
121
+ }
122
+ const repo = args.repo ?? (seams.resolveDefaultRepo ?? resolveRepoFromGitOrigin)();
123
+ if (repo === null || repo.length === 0) {
124
+ return {
125
+ exitCode: 2,
126
+ stdout: "",
127
+ stderr: "error: missing --repo OWNER/NAME (could not resolve from git origin)\n",
128
+ };
129
+ }
130
+ try {
131
+ splitRepo(repo);
132
+ }
133
+ catch (err) {
134
+ if (err instanceof InvalidRepoError) {
135
+ return { exitCode: 2, stdout: "", stderr: `error: invalid --repo value: ${err.message}\n` };
136
+ }
137
+ throw err;
138
+ }
139
+ const client = seams.client ?? new ScmLabelClient();
140
+ try {
141
+ const applied = applyDesignCritiqueCatalogChip(client, repo, args.issue, args.chip);
142
+ const payload = {
143
+ repo,
144
+ issue: args.issue,
145
+ chip: args.chip,
146
+ add: [...applied.add],
147
+ remove: [...applied.remove],
148
+ remaining: [...applied.remaining],
149
+ };
150
+ if (args.json) {
151
+ return { exitCode: 0, stdout: `${JSON.stringify(payload)}\n`, stderr: "" };
152
+ }
153
+ const wrote = applied.add.length > 0 || applied.remove.length > 0;
154
+ const detail = applied.remove.length > 0
155
+ ? `removed ${applied.remove.join(", ")}`
156
+ : wrote
157
+ ? "added"
158
+ : "already exclusive";
159
+ return {
160
+ exitCode: 0,
161
+ stdout: `${wrote ? "applied" : "unchanged"} ${args.chip} on ${repo}#${args.issue} (${detail})\n`,
162
+ stderr: "",
163
+ };
164
+ }
165
+ catch (err) {
166
+ const message = err instanceof Error ? err.message : String(err);
167
+ const payload = {
168
+ repo,
169
+ issue: args.issue,
170
+ chip: args.chip,
171
+ applied: false,
172
+ miss: true,
173
+ blocking: false,
174
+ error: message,
175
+ };
176
+ if (args.json) {
177
+ return { exitCode: 0, stdout: `${JSON.stringify(payload)}\n`, stderr: "" };
178
+ }
179
+ return {
180
+ exitCode: 0,
181
+ stdout: "",
182
+ stderr: `${CHIP_APPLY_MISS_TOKEN}: ${message}\n` +
183
+ "ingest is not blocked; remaining-set hygiene is optional for a write-capable identity\n",
184
+ };
185
+ }
186
+ }
187
+ //# sourceMappingURL=design-critique-chip.js.map
@@ -53,7 +53,7 @@ export interface RestIssueListOptions {
53
53
  export declare function restIssueList(repo: string, options?: RestIssueListOptions, seams?: GhRestSeams): Record<string, unknown>[];
54
54
  export declare const REST_MAX_PER_PAGE = 100;
55
55
  export declare const REST_PAGINATION_MAX_PAGES = 100;
56
- export declare const PUBLIC_HELPERS: readonly ["restCreateIssue", "restPostComment", "restUpdateComment", "restDeleteComment", "restGetUser", "restUpdateIssue", "restCreateLabel", "restCloseIssue", "restOpenPr", "restMergePr", "restIssueView", "restPrView", "restIssueList", "restIssueListPaginated"];
56
+ export declare const PUBLIC_HELPERS: readonly ["restCreateIssue", "restPostComment", "restUpdateComment", "restDeleteComment", "restGetUser", "restUpdateIssue", "restCreateLabel", "restCloseIssue", "restOpenPr", "restMergePr", "restIssueView", "restPrView", "restIssueList", "restIssueListPaginated", "restIssueListOpenInventory"];
57
57
  export declare function restCreateIssue(repo: string, title: string, body: string, labels?: readonly string[], seams?: GhRestSeams): Record<string, unknown>;
58
58
  export declare function restPostComment(repo: string, n: number, body: string, seams?: GhRestSeams): Record<string, unknown>;
59
59
  /** `PATCH /repos/{owner}/{repo}/issues/comments/{id}` -- edit a PR/issue comment in place. */
@@ -78,5 +78,13 @@ export interface RestIssueListPaginatedOptions extends RestIssueListOptions {
78
78
  readonly limit?: number | null;
79
79
  readonly excludePulls?: boolean;
80
80
  }
81
+ /** Flatten `gh api --paginate --slurp` issue-list output (pages or single page). */
82
+ export declare function flattenOpenInventoryPayload(parsed: unknown[], endpoint: string): Record<string, unknown>[];
83
+ /**
84
+ * Complete open-issue inventory in one `gh api --paginate --slurp` subprocess (#3752).
85
+ * Fail-closed on command failure, non-array JSON, buffer exhaustion, or cap hit.
86
+ * Pull-request rows are excluded.
87
+ */
88
+ export declare function restIssueListOpenInventory(repo: string, seams?: GhRestSeams): Record<string, unknown>[];
81
89
  export declare function restIssueListPaginated(repo: string, options?: RestIssueListPaginatedOptions, seams?: GhRestSeams): Record<string, unknown>[];
82
90
  //# sourceMappingURL=gh-rest.d.ts.map
@@ -183,6 +183,7 @@ export const PUBLIC_HELPERS = [
183
183
  "restPrView",
184
184
  "restIssueList",
185
185
  "restIssueListPaginated",
186
+ "restIssueListOpenInventory",
186
187
  ];
187
188
  function writeJsonPayload(payload) {
188
189
  const dir = mkdtempSync(join(tmpdir(), "gh_rest_payload_"));
@@ -331,6 +332,108 @@ export function restPrView(repo, n, seams = {}) {
331
332
  whichFn: seams.whichFn,
332
333
  });
333
334
  }
335
+ const OPEN_INVENTORY_MAX_ISSUES = REST_PAGINATION_MAX_PAGES * REST_MAX_PER_PAGE;
336
+ function issueRowOrThrow(item, endpoint) {
337
+ if (typeof item !== "object" || item === null || Array.isArray(item)) {
338
+ throw new GhRestError({
339
+ stderr: "open-issue inventory row is not an object",
340
+ exitCode: 0,
341
+ endpoint,
342
+ payload: null,
343
+ hint: "REST issue list rows must be objects",
344
+ });
345
+ }
346
+ return item;
347
+ }
348
+ /** Flatten `gh api --paginate --slurp` issue-list output (pages or single page). */
349
+ export function flattenOpenInventoryPayload(parsed, endpoint) {
350
+ if (parsed.length === 0) {
351
+ return [];
352
+ }
353
+ const out = [];
354
+ const allPages = parsed.every((item) => Array.isArray(item));
355
+ if (allPages) {
356
+ for (const page of parsed) {
357
+ if (!Array.isArray(page)) {
358
+ continue;
359
+ }
360
+ for (const item of page) {
361
+ const row = issueRowOrThrow(item, endpoint);
362
+ if ("pull_request" in row) {
363
+ continue;
364
+ }
365
+ out.push(row);
366
+ }
367
+ }
368
+ return out;
369
+ }
370
+ for (const item of parsed) {
371
+ const row = issueRowOrThrow(item, endpoint);
372
+ if ("pull_request" in row) {
373
+ continue;
374
+ }
375
+ out.push(row);
376
+ }
377
+ return out;
378
+ }
379
+ /**
380
+ * Complete open-issue inventory in one `gh api --paginate --slurp` subprocess (#3752).
381
+ * Fail-closed on command failure, non-array JSON, buffer exhaustion, or cap hit.
382
+ * Pull-request rows are excluded.
383
+ */
384
+ export function restIssueListOpenInventory(repo, seams = {}) {
385
+ const [owner, name] = splitRepo(repo);
386
+ const endpoint = `repos/${owner}/${name}/issues?state=open&per_page=${REST_MAX_PER_PAGE}`;
387
+ const runner = seams.runGhApiFn ?? runGhApi;
388
+ const result = runner(["--paginate", "--slurp", endpoint], { timeout: 120 });
389
+ if (result.returncode !== 0) {
390
+ throw new GhRestError({
391
+ stderr: result.stderr.trim(),
392
+ exitCode: result.returncode,
393
+ endpoint,
394
+ payload: null,
395
+ hint: "verify gh auth and core REST quota; open-issue inventory must be complete",
396
+ });
397
+ }
398
+ const stdout = result.stdout.trim();
399
+ if (stdout.length === 0) {
400
+ return [];
401
+ }
402
+ let parsed;
403
+ try {
404
+ parsed = JSON.parse(stdout);
405
+ }
406
+ catch (exc) {
407
+ const message = exc instanceof Error ? exc.message : String(exc);
408
+ throw new GhRestError({
409
+ stderr: `non-JSON open-issue inventory: ${message}`,
410
+ exitCode: 0,
411
+ endpoint,
412
+ payload: null,
413
+ hint: "gh api --paginate --slurp must return a JSON array",
414
+ });
415
+ }
416
+ if (!Array.isArray(parsed)) {
417
+ throw new GhRestError({
418
+ stderr: `unexpected top-level type ${typeof parsed}`,
419
+ exitCode: 0,
420
+ endpoint,
421
+ payload: null,
422
+ hint: "open-issue inventory must be a JSON array",
423
+ });
424
+ }
425
+ const out = flattenOpenInventoryPayload(parsed, endpoint);
426
+ if (out.length >= OPEN_INVENTORY_MAX_ISSUES) {
427
+ throw new GhRestError({
428
+ stderr: `open-issue inventory reached cap ${OPEN_INVENTORY_MAX_ISSUES}; pagination may be incomplete`,
429
+ exitCode: 0,
430
+ endpoint,
431
+ payload: null,
432
+ hint: "repo may exceed supported open-issue count; fail closed rather than truncate",
433
+ });
434
+ }
435
+ return out;
436
+ }
334
437
  export function restIssueListPaginated(repo, options = {}, seams = {}) {
335
438
  const cappedPerPage = Math.min(Math.max(1, options.perPage ?? REST_MAX_PER_PAGE), REST_MAX_PER_PAGE);
336
439
  const [owner, name] = splitRepo(repo);
@@ -3,6 +3,7 @@ export * from "./binary.js";
3
3
  export * from "./build-command.js";
4
4
  export * from "./call.js";
5
5
  export * from "./constants.js";
6
+ export * from "./design-critique-chip.js";
6
7
  export * from "./errors.js";
7
8
  export * from "./gh-rest.js";
8
9
  export * from "./main.js";
package/dist/scm/index.js CHANGED
@@ -3,6 +3,7 @@ export * from "./binary.js";
3
3
  export * from "./build-command.js";
4
4
  export * from "./call.js";
5
5
  export * from "./constants.js";
6
+ export * from "./design-critique-chip.js";
6
7
  export * from "./errors.js";
7
8
  export * from "./gh-rest.js";
8
9
  export * from "./main.js";
@@ -1,3 +1,4 @@
1
+ import type { LabelClient } from "../vbrief-reconcile/types.js";
1
2
  import type { GhRestSeams } from "./gh-rest.js";
2
3
  export interface MainOptions {
3
4
  readonly whichFn?: Parameters<typeof import("./binary.js").resolveBinary>[0];
@@ -8,6 +9,8 @@ export interface MainOptions {
8
9
  * Production CLI always probes.
9
10
  */
10
11
  readonly skipReadiness?: boolean;
12
+ /** LabelClient seam for `issue design-critique-chip` (#3642). */
13
+ readonly labelClient?: LabelClient;
11
14
  }
12
15
  /**
13
16
  * CLI entry point. Returns the underlying binary's exit code (or 2 on arg error).
package/dist/scm/main.js CHANGED
@@ -2,6 +2,7 @@ import { spawnSync } from "node:child_process";
2
2
  import { extractFlag } from "./argv.js";
3
3
  import { buildCommand } from "./build-command.js";
4
4
  import { REST_OPT_IN_VERBS } from "./constants.js";
5
+ import { DESIGN_CRITIQUE_CHIP_VERB, runDesignCritiqueChip } from "./design-critique-chip.js";
5
6
  import { ScmStubError } from "./errors.js";
6
7
  import { requireScmReady } from "./readiness.js";
7
8
  import { runRestList, runRestView } from "./rest-dispatch.js";
@@ -30,13 +31,26 @@ function guardScmReady(options) {
30
31
  export function main(argv, options = {}) {
31
32
  if (argv.length < 2) {
32
33
  process.stderr.write("usage: scm.py <namespace> <verb> [pass-through args...]\n" +
33
- " (v1 stub: namespace=issue, verb=list|view|close|edit)\n" +
34
+ " (v1 stub: namespace=issue, verb=list|view|close|edit|design-critique-chip)\n" +
34
35
  " --rest opt-in is supported on issue view/list (#976)\n");
35
36
  return 2;
36
37
  }
37
38
  const namespace = argv[0] ?? "";
38
39
  const verb = argv[1] ?? "";
39
40
  let extra = argv.slice(2);
41
+ if (namespace === "issue" && verb === DESIGN_CRITIQUE_CHIP_VERB) {
42
+ const blocked = guardScmReady(options);
43
+ if (blocked !== null)
44
+ return blocked;
45
+ const result = runDesignCritiqueChip(extra, { client: options.labelClient });
46
+ if (result.stdout.length > 0) {
47
+ process.stdout.write(result.stdout);
48
+ }
49
+ if (result.stderr.length > 0) {
50
+ process.stderr.write(result.stderr);
51
+ }
52
+ return result.exitCode;
53
+ }
40
54
  const [restMode, afterRest] = extractFlag(extra, "--rest");
41
55
  extra = afterRest;
42
56
  if (restMode) {
@@ -10,6 +10,8 @@ export interface ScmReadinessCliArgs {
10
10
  readonly deep?: boolean;
11
11
  readonly depth?: ScmProbeDepth;
12
12
  readonly help?: boolean;
13
+ readonly repo?: string;
14
+ readonly expectedLogin?: string;
13
15
  }
14
16
  export declare function parseScmReadinessArgs(argv: readonly string[]): {
15
17
  args: ScmReadinessCliArgs;