@deftai/directive 0.119.13 → 0.121.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.
@@ -0,0 +1,514 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Agent-facing pre-PR controller entry (#4912 Limb 3).
4
+ * `deft pre-pr:run` starts the prescribed workflow. Opening the skill file
5
+ * is not completion. Generic mark-complete cannot mint a pass.
6
+ */
7
+ import { completeRun, computeControllerObservedHash, controllerPublisher, digestApprovedCriteria, evaluateLivePrePrCheck, getDefaultPrePrStore, markComplete, noteSkillFileOpen, observeCommandPhase, PRE_PR_PHASE_IDS, phaseSpec, resolveRecordFromStore, startControllerRun, submitReviewerReport, } from "@deftai/directive-core/pre-pr-controller";
8
+ import { isDirectEntrypoint } from "./entrypoint.js";
9
+ const USAGE = `Usage: deft pre-pr:run [options]
10
+
11
+ Start the repository-controlled pre-PR workflow. Opening the skill file is
12
+ not completion. A generic mark-complete cannot mint a pass.
13
+
14
+ Options:
15
+ --repo <owner/name>
16
+ --base-sha <sha>
17
+ --head-sha <sha>
18
+ --tree-hash <sha>
19
+ --pr-body-hash <hex>
20
+ --pr-node-id <id>
21
+ --approved-revision <sha>
22
+ --scope <path> (repeatable)
23
+ --acceptance <text>
24
+ --generation <n>
25
+ --skill-version <ver>
26
+ --policy-version <ver>
27
+ --run-id <id> lookup hint only
28
+ --complete publisher-backed complete (fails without observables)
29
+ --observe-command record a command-observable phase before --complete
30
+ --observe-semantic record semantic / final-no-change evidence
31
+ --phase <id>
32
+ --command <text>
33
+ --exit-code <n> required with --observe-command; omit is a parse error
34
+ --input-hash <hex>
35
+ --skip-reason <text> skip also requires a non-zero --exit-code
36
+ --supplied-contents-hash <hex>
37
+ --controller-observed-hash <hex>
38
+ optional; must match independently hashed reviewed files
39
+ --criteria-digest <hex>
40
+ --reviewed-file <path> (repeatable)
41
+ --reviewer-report-ref <ref>
42
+ --mark-complete always refuses; cannot mint a pass
43
+ --skill-open always refuses; opening the skill is not completion
44
+ --evaluate evaluate live binding against the private store
45
+ --json
46
+ --help
47
+ `;
48
+ export function parseArgs(argv) {
49
+ const parsed = {
50
+ repo: "",
51
+ baseSha: "",
52
+ headSha: "",
53
+ treeHash: "",
54
+ prBodyHash: "",
55
+ prNodeId: null,
56
+ approvedRevision: "",
57
+ scope: [],
58
+ acceptance: "",
59
+ generation: 1,
60
+ skillVersion: "0.1",
61
+ policyVersion: "1",
62
+ runId: null,
63
+ complete: false,
64
+ observeCommand: false,
65
+ observeSemantic: false,
66
+ phase: null,
67
+ command: "",
68
+ exitCode: null,
69
+ inputHash: null,
70
+ skipReason: null,
71
+ suppliedContentsHash: "",
72
+ controllerObservedHash: "",
73
+ criteriaDigest: null,
74
+ reviewedFiles: [],
75
+ reviewerReportRef: null,
76
+ markComplete: false,
77
+ skillOpen: false,
78
+ evaluate: false,
79
+ json: false,
80
+ help: false,
81
+ };
82
+ for (let i = 0; i < argv.length; i += 1) {
83
+ const arg = argv[i];
84
+ if (arg === "--help" || arg === "-h") {
85
+ parsed.help = true;
86
+ }
87
+ else if (arg === "--json") {
88
+ parsed.json = true;
89
+ }
90
+ else if (arg === "--complete") {
91
+ parsed.complete = true;
92
+ }
93
+ else if (arg === "--observe-command") {
94
+ parsed.observeCommand = true;
95
+ }
96
+ else if (arg === "--observe-semantic") {
97
+ parsed.observeSemantic = true;
98
+ }
99
+ else if (arg === "--phase" || arg?.startsWith("--phase=")) {
100
+ const value = arg === "--phase" ? argv[i + 1] : arg.slice("--phase=".length);
101
+ if (value === undefined)
102
+ return { ...parsed, error: "argument --phase: expected one argument" };
103
+ parsed.phase = value;
104
+ if (arg === "--phase")
105
+ i += 1;
106
+ }
107
+ else if (arg === "--command" || arg?.startsWith("--command=")) {
108
+ const value = arg === "--command" ? argv[i + 1] : arg.slice("--command=".length);
109
+ if (value === undefined)
110
+ return { ...parsed, error: "argument --command: expected one argument" };
111
+ parsed.command = value;
112
+ if (arg === "--command")
113
+ i += 1;
114
+ }
115
+ else if (arg === "--exit-code" || arg?.startsWith("--exit-code=")) {
116
+ const value = arg === "--exit-code" ? argv[i + 1] : arg.slice("--exit-code=".length);
117
+ if (value === undefined) {
118
+ return { ...parsed, error: "argument --exit-code: expected one argument" };
119
+ }
120
+ const n = Number.parseInt(value, 10);
121
+ if (!Number.isFinite(n)) {
122
+ return { ...parsed, error: "argument --exit-code: expected an integer" };
123
+ }
124
+ parsed.exitCode = n;
125
+ if (arg === "--exit-code")
126
+ i += 1;
127
+ }
128
+ else if (arg === "--input-hash" || arg?.startsWith("--input-hash=")) {
129
+ const value = arg === "--input-hash" ? argv[i + 1] : arg.slice("--input-hash=".length);
130
+ if (value === undefined) {
131
+ return { ...parsed, error: "argument --input-hash: expected one argument" };
132
+ }
133
+ parsed.inputHash = value;
134
+ if (arg === "--input-hash")
135
+ i += 1;
136
+ }
137
+ else if (arg === "--skip-reason" || arg?.startsWith("--skip-reason=")) {
138
+ const value = arg === "--skip-reason" ? argv[i + 1] : arg.slice("--skip-reason=".length);
139
+ if (value === undefined) {
140
+ return { ...parsed, error: "argument --skip-reason: expected one argument" };
141
+ }
142
+ parsed.skipReason = value;
143
+ if (arg === "--skip-reason")
144
+ i += 1;
145
+ }
146
+ else if (arg === "--supplied-contents-hash" || arg?.startsWith("--supplied-contents-hash=")) {
147
+ const value = arg === "--supplied-contents-hash"
148
+ ? argv[i + 1]
149
+ : arg.slice("--supplied-contents-hash=".length);
150
+ if (value === undefined) {
151
+ return { ...parsed, error: "argument --supplied-contents-hash: expected one argument" };
152
+ }
153
+ parsed.suppliedContentsHash = value;
154
+ if (arg === "--supplied-contents-hash")
155
+ i += 1;
156
+ }
157
+ else if (arg === "--controller-observed-hash" ||
158
+ arg?.startsWith("--controller-observed-hash=")) {
159
+ const value = arg === "--controller-observed-hash"
160
+ ? argv[i + 1]
161
+ : arg.slice("--controller-observed-hash=".length);
162
+ if (value === undefined) {
163
+ return {
164
+ ...parsed,
165
+ error: "argument --controller-observed-hash: expected one argument",
166
+ };
167
+ }
168
+ parsed.controllerObservedHash = value;
169
+ if (arg === "--controller-observed-hash")
170
+ i += 1;
171
+ }
172
+ else if (arg === "--criteria-digest" || arg?.startsWith("--criteria-digest=")) {
173
+ const value = arg === "--criteria-digest" ? argv[i + 1] : arg.slice("--criteria-digest=".length);
174
+ if (value === undefined) {
175
+ return { ...parsed, error: "argument --criteria-digest: expected one argument" };
176
+ }
177
+ parsed.criteriaDigest = value;
178
+ if (arg === "--criteria-digest")
179
+ i += 1;
180
+ }
181
+ else if (arg === "--reviewed-file" || arg?.startsWith("--reviewed-file=")) {
182
+ const value = arg === "--reviewed-file" ? argv[i + 1] : arg.slice("--reviewed-file=".length);
183
+ if (value === undefined) {
184
+ return { ...parsed, error: "argument --reviewed-file: expected one argument" };
185
+ }
186
+ parsed.reviewedFiles.push(value);
187
+ if (arg === "--reviewed-file")
188
+ i += 1;
189
+ }
190
+ else if (arg === "--reviewer-report-ref" || arg?.startsWith("--reviewer-report-ref=")) {
191
+ const value = arg === "--reviewer-report-ref" ? argv[i + 1] : arg.slice("--reviewer-report-ref=".length);
192
+ if (value === undefined) {
193
+ return { ...parsed, error: "argument --reviewer-report-ref: expected one argument" };
194
+ }
195
+ parsed.reviewerReportRef = value;
196
+ if (arg === "--reviewer-report-ref")
197
+ i += 1;
198
+ }
199
+ else if (arg === "--mark-complete") {
200
+ parsed.markComplete = true;
201
+ }
202
+ else if (arg === "--skill-open") {
203
+ parsed.skillOpen = true;
204
+ }
205
+ else if (arg === "--evaluate") {
206
+ parsed.evaluate = true;
207
+ }
208
+ else if (arg === "--repo" || arg?.startsWith("--repo=")) {
209
+ const value = arg === "--repo" ? argv[i + 1] : arg.slice("--repo=".length);
210
+ if (value === undefined)
211
+ return { ...parsed, error: "argument --repo: expected one argument" };
212
+ parsed.repo = value;
213
+ if (arg === "--repo")
214
+ i += 1;
215
+ }
216
+ else if (arg === "--base-sha" || arg?.startsWith("--base-sha=")) {
217
+ const value = arg === "--base-sha" ? argv[i + 1] : arg.slice("--base-sha=".length);
218
+ if (value === undefined)
219
+ return { ...parsed, error: "argument --base-sha: expected one argument" };
220
+ parsed.baseSha = value;
221
+ if (arg === "--base-sha")
222
+ i += 1;
223
+ }
224
+ else if (arg === "--head-sha" || arg?.startsWith("--head-sha=")) {
225
+ const value = arg === "--head-sha" ? argv[i + 1] : arg.slice("--head-sha=".length);
226
+ if (value === undefined)
227
+ return { ...parsed, error: "argument --head-sha: expected one argument" };
228
+ parsed.headSha = value;
229
+ if (arg === "--head-sha")
230
+ i += 1;
231
+ }
232
+ else if (arg === "--tree-hash" || arg?.startsWith("--tree-hash=")) {
233
+ const value = arg === "--tree-hash" ? argv[i + 1] : arg.slice("--tree-hash=".length);
234
+ if (value === undefined)
235
+ return { ...parsed, error: "argument --tree-hash: expected one argument" };
236
+ parsed.treeHash = value;
237
+ if (arg === "--tree-hash")
238
+ i += 1;
239
+ }
240
+ else if (arg === "--pr-body-hash" || arg?.startsWith("--pr-body-hash=")) {
241
+ const value = arg === "--pr-body-hash" ? argv[i + 1] : arg.slice("--pr-body-hash=".length);
242
+ if (value === undefined) {
243
+ return { ...parsed, error: "argument --pr-body-hash: expected one argument" };
244
+ }
245
+ parsed.prBodyHash = value;
246
+ if (arg === "--pr-body-hash")
247
+ i += 1;
248
+ }
249
+ else if (arg === "--pr-node-id" || arg?.startsWith("--pr-node-id=")) {
250
+ const value = arg === "--pr-node-id" ? argv[i + 1] : arg.slice("--pr-node-id=".length);
251
+ if (value === undefined) {
252
+ return { ...parsed, error: "argument --pr-node-id: expected one argument" };
253
+ }
254
+ parsed.prNodeId = value;
255
+ if (arg === "--pr-node-id")
256
+ i += 1;
257
+ }
258
+ else if (arg === "--approved-revision" || arg?.startsWith("--approved-revision=")) {
259
+ const value = arg === "--approved-revision" ? argv[i + 1] : arg.slice("--approved-revision=".length);
260
+ if (value === undefined) {
261
+ return { ...parsed, error: "argument --approved-revision: expected one argument" };
262
+ }
263
+ parsed.approvedRevision = value;
264
+ if (arg === "--approved-revision")
265
+ i += 1;
266
+ }
267
+ else if (arg === "--scope" || arg?.startsWith("--scope=")) {
268
+ const value = arg === "--scope" ? argv[i + 1] : arg.slice("--scope=".length);
269
+ if (value === undefined)
270
+ return { ...parsed, error: "argument --scope: expected one argument" };
271
+ parsed.scope.push(value);
272
+ if (arg === "--scope")
273
+ i += 1;
274
+ }
275
+ else if (arg === "--acceptance" || arg?.startsWith("--acceptance=")) {
276
+ const value = arg === "--acceptance" ? argv[i + 1] : arg.slice("--acceptance=".length);
277
+ if (value === undefined) {
278
+ return { ...parsed, error: "argument --acceptance: expected one argument" };
279
+ }
280
+ parsed.acceptance = value;
281
+ if (arg === "--acceptance")
282
+ i += 1;
283
+ }
284
+ else if (arg === "--generation" || arg?.startsWith("--generation=")) {
285
+ const value = arg === "--generation" ? argv[i + 1] : arg.slice("--generation=".length);
286
+ if (value === undefined) {
287
+ return { ...parsed, error: "argument --generation: expected one argument" };
288
+ }
289
+ const n = Number.parseInt(value, 10);
290
+ if (!Number.isFinite(n) || n < 1) {
291
+ return { ...parsed, error: "argument --generation: expected a positive integer" };
292
+ }
293
+ parsed.generation = n;
294
+ if (arg === "--generation")
295
+ i += 1;
296
+ }
297
+ else if (arg === "--skill-version" || arg?.startsWith("--skill-version=")) {
298
+ const value = arg === "--skill-version" ? argv[i + 1] : arg.slice("--skill-version=".length);
299
+ if (value === undefined) {
300
+ return { ...parsed, error: "argument --skill-version: expected one argument" };
301
+ }
302
+ parsed.skillVersion = value;
303
+ if (arg === "--skill-version")
304
+ i += 1;
305
+ }
306
+ else if (arg === "--policy-version" || arg?.startsWith("--policy-version=")) {
307
+ const value = arg === "--policy-version" ? argv[i + 1] : arg.slice("--policy-version=".length);
308
+ if (value === undefined) {
309
+ return { ...parsed, error: "argument --policy-version: expected one argument" };
310
+ }
311
+ parsed.policyVersion = value;
312
+ if (arg === "--policy-version")
313
+ i += 1;
314
+ }
315
+ else if (arg === "--run-id" || arg?.startsWith("--run-id=")) {
316
+ const value = arg === "--run-id" ? argv[i + 1] : arg.slice("--run-id=".length);
317
+ if (value === undefined)
318
+ return { ...parsed, error: "argument --run-id: expected one argument" };
319
+ parsed.runId = value;
320
+ if (arg === "--run-id")
321
+ i += 1;
322
+ }
323
+ else {
324
+ return { ...parsed, error: `unrecognized argument: ${arg}` };
325
+ }
326
+ }
327
+ return parsed;
328
+ }
329
+ function emit(json, payload, text, err) {
330
+ const line = json ? `${JSON.stringify(payload)}\n` : `${text}\n`;
331
+ if (err)
332
+ process.stderr.write(line);
333
+ else
334
+ process.stdout.write(line);
335
+ }
336
+ function asPhaseId(value) {
337
+ return PRE_PR_PHASE_IDS.includes(value) ? value : null;
338
+ }
339
+ export function run(argv) {
340
+ const args = parseArgs(argv);
341
+ if (args.help) {
342
+ process.stdout.write(USAGE);
343
+ return 0;
344
+ }
345
+ if (args.error !== undefined) {
346
+ process.stderr.write(`pre_pr_run: ${args.error}\n`);
347
+ return 2;
348
+ }
349
+ if (args.skillOpen) {
350
+ const d = noteSkillFileOpen();
351
+ emit(args.json, d, d.message, true);
352
+ return 1;
353
+ }
354
+ const store = getDefaultPrePrStore();
355
+ if (args.markComplete) {
356
+ const d = markComplete(store, args.runId ?? "");
357
+ emit(args.json, d, d.message, true);
358
+ return 1;
359
+ }
360
+ if (args.observeCommand || args.observeSemantic) {
361
+ if (args.runId === null || args.runId.length === 0) {
362
+ process.stderr.write("pre_pr_run: observe requires --run-id\n");
363
+ return 2;
364
+ }
365
+ if (args.phase === null || args.phase.length === 0) {
366
+ process.stderr.write("pre_pr_run: observe requires --phase\n");
367
+ return 2;
368
+ }
369
+ const phase = asPhaseId(args.phase);
370
+ if (phase === null) {
371
+ process.stderr.write(`pre_pr_run: unknown phase ${args.phase}\n`);
372
+ return 2;
373
+ }
374
+ const rec = store.getById(args.runId);
375
+ if (args.observeCommand) {
376
+ if (args.exitCode === null) {
377
+ process.stderr.write("pre_pr_run: --observe-command requires --exit-code\n");
378
+ return 2;
379
+ }
380
+ if (args.skipReason !== null && args.skipReason.length > 0 && args.exitCode === 0) {
381
+ process.stderr.write("pre_pr_run: skip requires a non-zero --exit-code plus --skip-reason\n");
382
+ return 2;
383
+ }
384
+ const spec = phaseSpec(phase);
385
+ const d = observeCommandPhase(store, args.runId, {
386
+ phaseId: phase,
387
+ command: args.command.length > 0 ? args.command : (spec.command ?? ""),
388
+ exitCode: args.exitCode,
389
+ inputHash: args.inputHash ?? rec?.inputHash ?? "",
390
+ skipReason: args.skipReason,
391
+ });
392
+ emit(args.json, d, d.message, !d.ok);
393
+ return d.ok ? 0 : 1;
394
+ }
395
+ if (args.suppliedContentsHash.length === 0) {
396
+ process.stderr.write("pre_pr_run: --observe-semantic requires --supplied-contents-hash\n");
397
+ return 2;
398
+ }
399
+ if (args.reviewedFiles.length === 0) {
400
+ process.stderr.write("pre_pr_run: --observe-semantic requires --reviewed-file\n");
401
+ return 2;
402
+ }
403
+ const observed = computeControllerObservedHash({ reviewedFiles: args.reviewedFiles });
404
+ if (observed === null) {
405
+ process.stderr.write("pre_pr_run: --observe-semantic could not hash reviewed-file contents\n");
406
+ return 2;
407
+ }
408
+ if (args.controllerObservedHash.length > 0 && args.controllerObservedHash !== observed) {
409
+ process.stderr.write("pre_pr_run: --controller-observed-hash does not match independently hashed reviewed-file contents\n");
410
+ return 1;
411
+ }
412
+ if (args.suppliedContentsHash !== observed) {
413
+ process.stderr.write("pre_pr_run: --supplied-contents-hash does not match independently hashed reviewed-file contents\n");
414
+ return 1;
415
+ }
416
+ const d = submitReviewerReport(store, args.runId, {
417
+ phaseId: phase,
418
+ reviewedFileManifest: args.reviewedFiles,
419
+ suppliedContentsHash: args.suppliedContentsHash,
420
+ criteriaDigest: args.criteriaDigest ?? rec?.criteria.digest ?? "",
421
+ reviewerReportRef: args.reviewerReportRef,
422
+ controllerObservedHash: observed,
423
+ });
424
+ emit(args.json, d, d.message, !d.ok);
425
+ return d.ok ? 0 : 1;
426
+ }
427
+ if (args.evaluate) {
428
+ if (args.repo.length === 0 || args.baseSha.length === 0 || args.headSha.length === 0) {
429
+ process.stderr.write("pre_pr_run: --evaluate requires --repo --base-sha --head-sha\n");
430
+ return 2;
431
+ }
432
+ if (args.prBodyHash.length === 0) {
433
+ process.stderr.write("pre_pr_run: --evaluate requires --pr-body-hash\n");
434
+ return 2;
435
+ }
436
+ const record = resolveRecordFromStore(store, {
437
+ id: args.runId,
438
+ prNodeId: args.prNodeId,
439
+ });
440
+ const headSource = args.approvedRevision.length > 0
441
+ ? args.approvedRevision
442
+ : (record?.criteria.sourceRevisionSha ?? args.headSha);
443
+ const liveApproved = digestApprovedCriteria({
444
+ sourceRevisionSha: headSource,
445
+ scopePaths: args.scope,
446
+ acceptanceText: args.acceptance,
447
+ generation: args.generation,
448
+ });
449
+ const d = evaluateLivePrePrCheck({
450
+ store,
451
+ liveBinding: {
452
+ repo: args.repo,
453
+ baseSha: args.baseSha,
454
+ headSha: args.headSha,
455
+ prNodeId: args.prNodeId,
456
+ prBodyHash: args.prBodyHash,
457
+ },
458
+ presentedRunId: args.runId,
459
+ approvedCriteria: liveApproved,
460
+ currentGeneration: args.generation,
461
+ headCriteria: liveApproved,
462
+ });
463
+ emit(args.json, d, d.message, !d.ok);
464
+ return d.ok ? 0 : 1;
465
+ }
466
+ if (args.complete) {
467
+ if (args.runId === null || args.runId.length === 0) {
468
+ process.stderr.write("pre_pr_run: --complete requires --run-id\n");
469
+ return 2;
470
+ }
471
+ const d = completeRun(store, controllerPublisher(), args.runId);
472
+ emit(args.json, d, d.message, !d.ok);
473
+ return d.ok ? 0 : 1;
474
+ }
475
+ if (args.repo.length === 0 ||
476
+ args.baseSha.length === 0 ||
477
+ args.headSha.length === 0 ||
478
+ args.treeHash.length === 0 ||
479
+ args.prBodyHash.length === 0 ||
480
+ args.approvedRevision.length === 0) {
481
+ process.stderr.write("pre_pr_run: start requires --repo --base-sha --head-sha --tree-hash --pr-body-hash --approved-revision\n");
482
+ return 2;
483
+ }
484
+ const criteria = digestApprovedCriteria({
485
+ sourceRevisionSha: args.approvedRevision,
486
+ scopePaths: args.scope,
487
+ acceptanceText: args.acceptance,
488
+ generation: args.generation,
489
+ });
490
+ const started = startControllerRun(store, {
491
+ repo: args.repo,
492
+ baseSha: args.baseSha,
493
+ headSha: args.headSha,
494
+ treeHash: args.treeHash,
495
+ prBodyHash: args.prBodyHash,
496
+ prNodeId: args.prNodeId,
497
+ criteria,
498
+ skillVersion: args.skillVersion,
499
+ policyVersion: args.policyVersion,
500
+ approvedRevisionSha: args.approvedRevision,
501
+ runId: args.runId ?? undefined,
502
+ });
503
+ if (!started.ok) {
504
+ emit(args.json, started.decision, started.decision.message, true);
505
+ return 1;
506
+ }
507
+ const payload = { ok: started.ok, runId: started.runId, hint: "run id is a lookup hint only" };
508
+ emit(args.json, payload, `started ${started.runId} (lookup hint only; private store is authoritative)`, false);
509
+ return 0;
510
+ }
511
+ if (isDirectEntrypoint(import.meta.url)) {
512
+ process.exit(run(process.argv.slice(2)));
513
+ }
514
+ //# sourceMappingURL=pre-pr-run.js.map
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export declare function runSpecReconstructCliEntry(argv: string[]): number;
3
+ //# sourceMappingURL=spec-reconstruct-cli.d.ts.map
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import { fileURLToPath } from "node:url";
3
+ import { runSpecReconstructCli } from "@deftai/directive-core/spec-reconstruct";
4
+ export function runSpecReconstructCliEntry(argv) {
5
+ const result = runSpecReconstructCli(argv);
6
+ if (result.stdout.length > 0)
7
+ process.stdout.write(result.stdout);
8
+ if (result.stderr.length > 0)
9
+ process.stderr.write(result.stderr);
10
+ return result.exitCode;
11
+ }
12
+ if (process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1]) {
13
+ process.exit(runSpecReconstructCliEntry(process.argv.slice(2)));
14
+ }
15
+ //# sourceMappingURL=spec-reconstruct-cli.js.map
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ export declare const SUBAGENT_PRE_CANCEL_HELP = "subagent:pre-cancel \u2014 query-before-cancel gate (#5278)\n\nUsage:\n task subagent:pre-cancel -- --agent <id> --canceller-id <id> [options]\n\nExit 0 only when one ordered branch clears:\n (a) canceller-authored status steer (kind note|correction) + matching ack\n OR observed first-seen window (default 3 minutes; PA-18 forward skew only)\n (b) heartbeat STALE/missing under startup grace from --dispatch-started-at\n (c) --force --reason <text>\n\nOptions:\n --agent ID Target child agent_id (required)\n --canceller-id ID Canceller identity; must match steer writer_id for (a)\n --target-id PATH Worktree root (resolves steer/scratch/first-seen under it)\n --steer-dir PATH Steer inbox dir (default: <cwd|target>/.deft-scratch/subagent-steer)\n --scratch-dir PATH Heartbeat dir (default: <cwd|target>/.deft-scratch/subagent-status)\n --first-seen-dir PATH First-seen stamps (default: .../subagent-steer-firstseen)\n --dispatch-started-at ISO DeliveryAttemptRecord.startedAt for grace path (b)\n --expected-worker-id ID Refuse when agent does not match current attempt worker\n --observed-window-seconds N Default 180\n --force Explicit force clear (requires --reason)\n --reason TEXT Printed force reason\n --json Machine-readable verdict\n\nExit codes:\n 0 Pre-cancel green\n 1 Refused (gate red)\n 2 Config / usage error\n";
3
+ export interface SubagentPreCancelArgs {
4
+ agentId: string | null;
5
+ cancellerId: string | null;
6
+ targetId: string | null;
7
+ steerDir: string | null;
8
+ scratchDir: string | null;
9
+ firstSeenDir: string | null;
10
+ dispatchStartedAt: string | null;
11
+ expectedWorkerId: string | null;
12
+ observedWindowSeconds: number | null;
13
+ force: boolean;
14
+ forceReason: string | null;
15
+ emitJson: boolean;
16
+ help: boolean;
17
+ error?: string;
18
+ }
19
+ export declare function parseSubagentPreCancelArgs(argv: readonly string[]): SubagentPreCancelArgs;
20
+ export declare function run(argv: readonly string[], cwd?: string): number;
21
+ //# sourceMappingURL=subagent-pre-cancel.d.ts.map