@deftai/directive-core 0.91.0 → 0.93.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 (92) hide show
  1. package/dist/cache/fetch.js +3 -2
  2. package/dist/cache/io.d.ts +13 -2
  3. package/dist/cache/io.js +36 -7
  4. package/dist/cache/operations.js +5 -3
  5. package/dist/doctor/index.d.ts +1 -0
  6. package/dist/doctor/index.js +1 -0
  7. package/dist/doctor/main.js +49 -0
  8. package/dist/doctor/openclaw-l2-adapter.d.ts +26 -0
  9. package/dist/doctor/openclaw-l2-adapter.js +199 -0
  10. package/dist/hooks/dispatcher.d.ts +6 -1
  11. package/dist/hooks/dispatcher.js +30 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +2 -0
  14. package/dist/init-deposit/gitignore.js +3 -0
  15. package/dist/init-deposit/hygiene.d.ts +43 -1
  16. package/dist/init-deposit/hygiene.js +134 -10
  17. package/dist/init-deposit/index.d.ts +3 -0
  18. package/dist/init-deposit/index.js +3 -0
  19. package/dist/init-deposit/init-deposit.js +10 -0
  20. package/dist/init-deposit/refresh.js +11 -0
  21. package/dist/init-deposit/scaffold.js +6 -134
  22. package/dist/init-deposit/skill-discovery-deposit.d.ts +65 -0
  23. package/dist/init-deposit/skill-discovery-deposit.js +287 -0
  24. package/dist/init-deposit/skill-discovery-hosts.d.ts +94 -0
  25. package/dist/init-deposit/skill-discovery-hosts.js +217 -0
  26. package/dist/init-deposit/slash-deposit.d.ts +46 -0
  27. package/dist/init-deposit/slash-deposit.js +174 -0
  28. package/dist/orchestration/probe-session.d.ts +5 -1
  29. package/dist/orchestration/probe-session.js +24 -13
  30. package/dist/platform/agents-md.js +1 -1
  31. package/dist/policy/deft-directive-disable.d.ts +86 -0
  32. package/dist/policy/deft-directive-disable.js +167 -0
  33. package/dist/policy/delivery-branch.d.ts +33 -0
  34. package/dist/policy/delivery-branch.js +124 -0
  35. package/dist/policy/host-slash-commands.d.ts +28 -0
  36. package/dist/policy/host-slash-commands.js +103 -0
  37. package/dist/policy/index.d.ts +3 -0
  38. package/dist/policy/index.js +61 -5
  39. package/dist/scope/brief-io.d.ts +3 -1
  40. package/dist/scope/brief-io.js +5 -3
  41. package/dist/scope/delivery-evidence.d.ts +112 -0
  42. package/dist/scope/delivery-evidence.js +419 -0
  43. package/dist/scope/index.d.ts +1 -0
  44. package/dist/scope/index.js +1 -0
  45. package/dist/scope/main.d.ts +5 -0
  46. package/dist/scope/main.js +98 -3
  47. package/dist/scope/registry-artifact-sync.js +4 -1
  48. package/dist/scope/transition.d.ts +11 -1
  49. package/dist/scope/transition.js +30 -4
  50. package/dist/session/ritual-sentinel.js +21 -12
  51. package/dist/session/session-start-hook.d.ts +3 -0
  52. package/dist/session/session-start-hook.js +21 -0
  53. package/dist/session/session-start.js +31 -0
  54. package/dist/slash/emitters.d.ts +102 -0
  55. package/dist/slash/emitters.js +148 -0
  56. package/dist/slash/generator.d.ts +98 -0
  57. package/dist/slash/generator.js +145 -0
  58. package/dist/slash/index.d.ts +16 -0
  59. package/dist/slash/index.js +16 -0
  60. package/dist/slash/openclaw-adapter.d.ts +64 -0
  61. package/dist/slash/openclaw-adapter.js +198 -0
  62. package/dist/slash/openclaw-deposit.d.ts +73 -0
  63. package/dist/slash/openclaw-deposit.js +279 -0
  64. package/dist/slash/openclaw-slugs.d.ts +52 -0
  65. package/dist/slash/openclaw-slugs.js +126 -0
  66. package/dist/slash/product-set.d.ts +50 -0
  67. package/dist/slash/product-set.js +142 -0
  68. package/dist/swarm/complete-cohort.d.ts +20 -1
  69. package/dist/swarm/complete-cohort.js +56 -9
  70. package/dist/swarm/finalize-cohort-cli.js +9 -0
  71. package/dist/swarm/finalize-cohort.d.ts +8 -0
  72. package/dist/swarm/finalize-cohort.js +217 -21
  73. package/dist/user-config/experimental-rules.d.ts +43 -0
  74. package/dist/user-config/experimental-rules.js +162 -0
  75. package/dist/user-config/index.d.ts +1 -0
  76. package/dist/user-config/index.js +1 -0
  77. package/dist/vbrief-validate/plan-hooks.d.ts +4 -0
  78. package/dist/vbrief-validate/plan-hooks.js +50 -0
  79. package/dist/verify-source/contained-writes.js +1 -1
  80. package/dist/xbrief/create.d.ts +36 -0
  81. package/dist/xbrief/create.js +285 -0
  82. package/dist/xbrief/index.d.ts +14 -0
  83. package/dist/xbrief/index.js +42 -0
  84. package/dist/xbrief/paths.d.ts +37 -0
  85. package/dist/xbrief/paths.js +123 -0
  86. package/dist/xbrief/styles.d.ts +36 -0
  87. package/dist/xbrief/styles.js +235 -0
  88. package/dist/xbrief/types.d.ts +50 -0
  89. package/dist/xbrief/types.js +17 -0
  90. package/dist/xbrief/verify.d.ts +30 -0
  91. package/dist/xbrief/verify.js +251 -0
  92. package/package.json +11 -3
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Per-host slash-command deposit policy (#3054 / epic #55 L6).
3
+ *
4
+ * Parallel to {@link plan.policy.hostHooks}: default multi-host enablement for
5
+ * every host that has a real emitter (no stubs). Per-host `false` opts out.
6
+ */
7
+ import { type SlashEmitterHostId } from "../slash/emitters.js";
8
+ export declare const FIELD_HOST_SLASH_COMMANDS = "plan.policy.hostSlashCommands";
9
+ export declare const FIELD_HOST_SLASH_COMMANDS_CLI_ALIAS = "hostSlashCommands";
10
+ /** Per-host Directive slash-command deposit toggles (#3054). */
11
+ export type HostSlashCommandsPolicy = Record<SlashEmitterHostId, boolean>;
12
+ /** Default = all hosts with real emitters enabled (L6; not single-host-only). */
13
+ export declare const DEFAULT_HOST_SLASH_COMMANDS_POLICY: HostSlashCommandsPolicy;
14
+ export interface HostSlashCommandsPolicyField {
15
+ readonly name: string;
16
+ readonly current: HostSlashCommandsPolicy;
17
+ readonly default: HostSlashCommandsPolicy;
18
+ readonly source: string;
19
+ }
20
+ /** Resolve typed slash-command deposit policy from raw PROJECT-DEFINITION value. */
21
+ export declare function resolveHostSlashCommandsPolicy(raw: unknown): HostSlashCommandsPolicy;
22
+ export declare function validateHostSlashCommands(value: unknown): string[];
23
+ export declare function isHostSlashCommandDepositEnabled(host: SlashEmitterHostId, policy?: HostSlashCommandsPolicy): boolean;
24
+ /** Inspector row for `policy:show --field=hostSlashCommands`. */
25
+ export declare function inspectHostSlashCommands(data: Record<string, unknown> | null): HostSlashCommandsPolicyField;
26
+ /** Resolve slash-command deposit policy from PROJECT-DEFINITION on disk. */
27
+ export declare function loadHostSlashCommandsPolicyFromProject(projectRoot: string): HostSlashCommandsPolicy;
28
+ //# sourceMappingURL=host-slash-commands.d.ts.map
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Per-host slash-command deposit policy (#3054 / epic #55 L6).
3
+ *
4
+ * Parallel to {@link plan.policy.hostHooks}: default multi-host enablement for
5
+ * every host that has a real emitter (no stubs). Per-host `false` opts out.
6
+ */
7
+ import { isSlashEmitterHostId, SLASH_EMITTER_HOSTS, } from "../slash/emitters.js";
8
+ import { readPlanPolicy } from "./plan-extensions.js";
9
+ import { loadProjectDefinition } from "./resolve.js";
10
+ export const FIELD_HOST_SLASH_COMMANDS = "plan.policy.hostSlashCommands";
11
+ export const FIELD_HOST_SLASH_COMMANDS_CLI_ALIAS = "hostSlashCommands";
12
+ /** Default = all hosts with real emitters enabled (L6; not single-host-only). */
13
+ export const DEFAULT_HOST_SLASH_COMMANDS_POLICY = Object.freeze({
14
+ claude: true,
15
+ cursor: true,
16
+ grok: true,
17
+ codex: true,
18
+ });
19
+ function readHostBoolean(rec, host, fallback) {
20
+ if (host in rec && typeof rec[host] === "boolean") {
21
+ return rec[host];
22
+ }
23
+ return fallback;
24
+ }
25
+ /** Resolve typed slash-command deposit policy from raw PROJECT-DEFINITION value. */
26
+ export function resolveHostSlashCommandsPolicy(raw) {
27
+ if (raw === null || raw === undefined) {
28
+ return { ...DEFAULT_HOST_SLASH_COMMANDS_POLICY };
29
+ }
30
+ if (typeof raw !== "object" || Array.isArray(raw)) {
31
+ return { ...DEFAULT_HOST_SLASH_COMMANDS_POLICY };
32
+ }
33
+ const rec = raw;
34
+ return {
35
+ claude: readHostBoolean(rec, "claude", DEFAULT_HOST_SLASH_COMMANDS_POLICY.claude),
36
+ cursor: readHostBoolean(rec, "cursor", DEFAULT_HOST_SLASH_COMMANDS_POLICY.cursor),
37
+ grok: readHostBoolean(rec, "grok", DEFAULT_HOST_SLASH_COMMANDS_POLICY.grok),
38
+ codex: readHostBoolean(rec, "codex", DEFAULT_HOST_SLASH_COMMANDS_POLICY.codex),
39
+ };
40
+ }
41
+ export function validateHostSlashCommands(value) {
42
+ if (value === null || value === undefined) {
43
+ return [];
44
+ }
45
+ if (typeof value !== "object" || Array.isArray(value)) {
46
+ return [`${FIELD_HOST_SLASH_COMMANDS} must be an object; got ${typeof value}`];
47
+ }
48
+ const rec = value;
49
+ const errors = [];
50
+ for (const host of SLASH_EMITTER_HOSTS) {
51
+ if (host in rec && typeof rec[host] !== "boolean") {
52
+ errors.push(`${FIELD_HOST_SLASH_COMMANDS}.${host} must be a boolean`);
53
+ }
54
+ }
55
+ for (const key of Object.keys(rec)) {
56
+ if (!isSlashEmitterHostId(key)) {
57
+ errors.push(`${FIELD_HOST_SLASH_COMMANDS}.${key} is not a slash emitter host (${SLASH_EMITTER_HOSTS.join(", ")})`);
58
+ }
59
+ }
60
+ return errors;
61
+ }
62
+ export function isHostSlashCommandDepositEnabled(host, policy = DEFAULT_HOST_SLASH_COMMANDS_POLICY) {
63
+ return policy[host];
64
+ }
65
+ function fieldFromResolved(resolved, source) {
66
+ return {
67
+ name: FIELD_HOST_SLASH_COMMANDS,
68
+ current: resolved,
69
+ default: { ...DEFAULT_HOST_SLASH_COMMANDS_POLICY },
70
+ source,
71
+ };
72
+ }
73
+ /** Inspector row for `policy:show --field=hostSlashCommands`. */
74
+ export function inspectHostSlashCommands(data) {
75
+ if (data === null) {
76
+ return fieldFromResolved({ ...DEFAULT_HOST_SLASH_COMMANDS_POLICY }, "default");
77
+ }
78
+ const policyBlock = readPlanPolicy(data.plan);
79
+ if (typeof policyBlock !== "object" ||
80
+ policyBlock === null ||
81
+ Array.isArray(policyBlock) ||
82
+ !("hostSlashCommands" in policyBlock)) {
83
+ return fieldFromResolved({ ...DEFAULT_HOST_SLASH_COMMANDS_POLICY }, "default");
84
+ }
85
+ const resolved = resolveHostSlashCommandsPolicy(policyBlock.hostSlashCommands);
86
+ return fieldFromResolved(resolved, "typed");
87
+ }
88
+ /** Resolve slash-command deposit policy from PROJECT-DEFINITION on disk. */
89
+ export function loadHostSlashCommandsPolicyFromProject(projectRoot) {
90
+ const [data] = loadProjectDefinition(projectRoot);
91
+ if (data === null) {
92
+ return { ...DEFAULT_HOST_SLASH_COMMANDS_POLICY };
93
+ }
94
+ const policyBlock = readPlanPolicy(data.plan);
95
+ if (typeof policyBlock !== "object" ||
96
+ policyBlock === null ||
97
+ Array.isArray(policyBlock) ||
98
+ !("hostSlashCommands" in policyBlock)) {
99
+ return { ...DEFAULT_HOST_SLASH_COMMANDS_POLICY };
100
+ }
101
+ return resolveHostSlashCommandsPolicy(policyBlock.hostSlashCommands);
102
+ }
103
+ //# sourceMappingURL=host-slash-commands.js.map
@@ -2,8 +2,11 @@ export * from "./agents-md-advisory.js";
2
2
  export * from "./autonomy.js";
3
3
  export * from "./capacity.js";
4
4
  export * from "./decisions.js";
5
+ export * from "./deft-directive-disable.js";
6
+ export * from "./delivery-branch.js";
5
7
  export * from "./disclosure.js";
6
8
  export * from "./host-hooks.js";
9
+ export * from "./host-slash-commands.js";
7
10
  export * from "./hotfix-criteria.js";
8
11
  export * from "./intent-ceiling.js";
9
12
  export * from "./no-deft-directive.js";
@@ -1,4 +1,8 @@
1
+ import { FIELD_HOST_SKILL_DISCOVERY, FIELD_HOST_SKILL_DISCOVERY_CLI_ALIAS, inspectHostSkillDiscovery, } from "../init-deposit/skill-discovery-hosts.js";
2
+ import { FIELD_OPENCLAW_PRODUCT_COMMANDS, FIELD_OPENCLAW_PRODUCT_COMMANDS_CLI_ALIAS, inspectOpenClawProductCommands, } from "../slash/openclaw-deposit.js";
3
+ import { FIELD_DELIVERY_BRANCH, FIELD_DELIVERY_BRANCH_CLI_ALIAS, inspectDeliveryBranch, } from "./delivery-branch.js";
1
4
  import { FIELD_HOST_HOOKS, FIELD_HOST_HOOKS_CLI_ALIAS, inspectHostHooks } from "./host-hooks.js";
5
+ import { FIELD_HOST_SLASH_COMMANDS, FIELD_HOST_SLASH_COMMANDS_CLI_ALIAS, inspectHostSlashCommands, } from "./host-slash-commands.js";
2
6
  import { FIELD_HOTFIX_CRITERIA, FIELD_HOTFIX_CRITERIA_CLI_ALIAS, inspectHotfixCriteria, } from "./hotfix-criteria.js";
3
7
  import { readPlanPolicy } from "./plan-extensions.js";
4
8
  import { FIELD_PRODUCT_SIGNAL, FIELD_PRODUCT_SIGNAL_CLI_ALIAS, inspectProductSignal, } from "./product-signal.js";
@@ -12,8 +16,11 @@ export * from "./agents-md-advisory.js";
12
16
  export * from "./autonomy.js";
13
17
  export * from "./capacity.js";
14
18
  export * from "./decisions.js";
19
+ export * from "./deft-directive-disable.js";
20
+ export * from "./delivery-branch.js";
15
21
  export * from "./disclosure.js";
16
22
  export * from "./host-hooks.js";
23
+ export * from "./host-slash-commands.js";
17
24
  export * from "./hotfix-criteria.js";
18
25
  export * from "./intent-ceiling.js";
19
26
  export * from "./no-deft-directive.js";
@@ -38,6 +45,7 @@ export const FIELD_TRIAGE_RANKING_LABELS = "plan.policy.triageRankingLabels";
38
45
  export const FIELD_TRIAGE_AUTO_CLASSIFY = "plan.policy.triageAutoClassify";
39
46
  export const FIELD_TRIAGE_HOLD_MARKERS = "plan.policy.triageHoldMarkers";
40
47
  export const FIELD_SWARM_SUBAGENT_BACKEND = "plan.policy.swarmSubagentBackend";
48
+ // deliveryBranch also exported from delivery-branch.js via export *
41
49
  export const DEFAULT_SESSION_RITUAL_STALENESS_HOURS = 4;
42
50
  export const DEFAULT_TRIAGE_SCOPE_VALUE = [
43
51
  { rule: "all-open" },
@@ -278,6 +286,33 @@ function inspectHostHooksField(data) {
278
286
  source: field.source,
279
287
  };
280
288
  }
289
+ function inspectHostSlashCommandsField(data) {
290
+ const field = inspectHostSlashCommands(data);
291
+ return {
292
+ name: field.name,
293
+ current: field.current,
294
+ default: field.default,
295
+ source: field.source,
296
+ };
297
+ }
298
+ function inspectOpenClawProductCommandsField(data) {
299
+ const field = inspectOpenClawProductCommands(data);
300
+ return {
301
+ name: field.name,
302
+ current: field.current,
303
+ default: field.default,
304
+ source: field.source,
305
+ };
306
+ }
307
+ function inspectHostSkillDiscoveryField(data) {
308
+ const field = inspectHostSkillDiscovery(data);
309
+ return {
310
+ name: field.name,
311
+ current: field.current,
312
+ default: field.default,
313
+ source: field.source,
314
+ };
315
+ }
281
316
  function inspectRequireHumanMergeField(data, projectRoot) {
282
317
  const field = inspectRequireHumanMerge(data, projectRoot);
283
318
  return {
@@ -296,6 +331,15 @@ function inspectHotfixCriteriaField(data) {
296
331
  source: field.source,
297
332
  };
298
333
  }
334
+ function inspectDeliveryBranchField(data, projectRoot) {
335
+ const field = inspectDeliveryBranch(data, projectRoot);
336
+ return {
337
+ name: field.name,
338
+ current: field.current,
339
+ default: field.default,
340
+ source: field.source,
341
+ };
342
+ }
299
343
  const REGISTERED_POLICIES = [
300
344
  inspectAllowDirectCommits,
301
345
  inspectWipCap,
@@ -308,7 +352,11 @@ const REGISTERED_POLICIES = [
308
352
  emptyIsTyped: true,
309
353
  }),
310
354
  inspectSwarmSubagentBackend,
355
+ inspectDeliveryBranchField,
311
356
  inspectHostHooksField,
357
+ inspectHostSlashCommandsField,
358
+ inspectOpenClawProductCommandsField,
359
+ inspectHostSkillDiscoveryField,
312
360
  inspectStalenessTicklerField,
313
361
  inspectRuntimeAuthorityField,
314
362
  inspectProductSignalField,
@@ -333,11 +381,19 @@ export function inspectOnePolicy(name, projectRoot) {
333
381
  ? FIELD_RUNTIME_AUTHORITY
334
382
  : name === FIELD_HOST_HOOKS_CLI_ALIAS
335
383
  ? FIELD_HOST_HOOKS
336
- : name === FIELD_REQUIRE_HUMAN_MERGE_CLI_ALIAS
337
- ? FIELD_REQUIRE_HUMAN_MERGE
338
- : name === FIELD_HOTFIX_CRITERIA_CLI_ALIAS
339
- ? FIELD_HOTFIX_CRITERIA
340
- : name;
384
+ : name === FIELD_HOST_SLASH_COMMANDS_CLI_ALIAS
385
+ ? FIELD_HOST_SLASH_COMMANDS
386
+ : name === FIELD_OPENCLAW_PRODUCT_COMMANDS_CLI_ALIAS
387
+ ? FIELD_OPENCLAW_PRODUCT_COMMANDS
388
+ : name === FIELD_HOST_SKILL_DISCOVERY_CLI_ALIAS
389
+ ? FIELD_HOST_SKILL_DISCOVERY
390
+ : name === FIELD_REQUIRE_HUMAN_MERGE_CLI_ALIAS
391
+ ? FIELD_REQUIRE_HUMAN_MERGE
392
+ : name === FIELD_HOTFIX_CRITERIA_CLI_ALIAS
393
+ ? FIELD_HOTFIX_CRITERIA
394
+ : name === FIELD_DELIVERY_BRANCH_CLI_ALIAS
395
+ ? FIELD_DELIVERY_BRANCH
396
+ : name;
341
397
  for (const field of inspectAllPolicies(projectRoot)) {
342
398
  if (field.name === normalized)
343
399
  return field;
@@ -22,5 +22,7 @@ export type AtomicWriteBriefResult = {
22
22
  readonly message: string;
23
23
  };
24
24
  /** Validate then atomically persist a brief (temp file + rename). */
25
- export declare function atomicWriteBrief(filePath: string, data: JsonObject, vbriefRoot: string): AtomicWriteBriefResult;
25
+ export declare function atomicWriteBrief(filePath: string, data: JsonObject, vbriefRoot: string, options?: {
26
+ readonly projectRoot?: string;
27
+ }): AtomicWriteBriefResult;
26
28
  //# sourceMappingURL=brief-io.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
- import { resolve } from "node:path";
2
+ import { dirname, resolve } from "node:path";
3
3
  import { atomicWriteText } from "../cache/io.js";
4
4
  import { hasArtifactSuffix } from "../layout/resolve.js";
5
5
  import { pythonJsonPretty } from "../vbrief-build/json.js";
@@ -60,13 +60,15 @@ export function validateBriefForPersist(filePath, data, vbriefRoot) {
60
60
  return errors.join("; ");
61
61
  }
62
62
  /** Validate then atomically persist a brief (temp file + rename). */
63
- export function atomicWriteBrief(filePath, data, vbriefRoot) {
63
+ export function atomicWriteBrief(filePath, data, vbriefRoot, options = {}) {
64
64
  const validationError = validateBriefForPersist(filePath, data, vbriefRoot);
65
65
  if (validationError !== null) {
66
66
  return { ok: false, message: validationError };
67
67
  }
68
+ // #3042: contain against projectRoot (parent of xbrief/), not dirname(filePath).
69
+ const projectRoot = options.projectRoot ?? dirname(resolve(vbriefRoot));
68
70
  try {
69
- atomicWriteText(filePath, formatBriefJson(data));
71
+ atomicWriteText(filePath, formatBriefJson(data), { projectRoot });
70
72
  return { ok: true };
71
73
  }
72
74
  catch (err) {
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Delivery integrity for scope completion (#3041).
3
+ *
4
+ * A code-bearing scope must not acquire a delivered disposition unless the
5
+ * merge/delivered commit is an ancestor of the refreshed remote delivery ref,
6
+ * or an explicit auditable non-delivery disposition is recorded.
7
+ *
8
+ * Deploy / UAT are separate axes and MUST NOT be inferred from Git alone.
9
+ */
10
+ import { type GitRunner } from "../session/git.js";
11
+ /** Handoff states that Git delivery can assert (deploy/UAT never inferred). */
12
+ export declare const HANDOFF_STATES: readonly ["implemented", "pr_open", "merged_to_integration", "delivered"];
13
+ export type HandoffState = (typeof HANDOFF_STATES)[number];
14
+ /** Explicit non-delivery terminal dispositions (never render as shipped). */
15
+ export declare const NON_DELIVERY_DISPOSITIONS: readonly ["cancelled", "superseded", "experiment_archived", "accepted_not_delivered"];
16
+ export type NonDeliveryDisposition = (typeof NON_DELIVERY_DISPOSITIONS)[number];
17
+ /** Delivery verification outcome for completion provenance. */
18
+ export type DeliveryDisposition = "delivered" | "merged_to_integration" | "not_delivered" | NonDeliveryDisposition | "unknown" | "unverified";
19
+ export interface CompletionProvenance {
20
+ readonly repository: string | null;
21
+ readonly implementationCommit: string | null;
22
+ readonly prNumber: number | null;
23
+ readonly prBase: string | null;
24
+ readonly mergeCommit: string | null;
25
+ readonly deliveryBranch: string;
26
+ readonly deliveryCommit: string | null;
27
+ readonly verifiedAt: string;
28
+ readonly verifier: string;
29
+ readonly disposition: DeliveryDisposition;
30
+ readonly handoffState: HandoffState | "unknown";
31
+ /** Always null unless explicitly supplied — never inferred from Git (#3041). */
32
+ readonly deployed: boolean | null;
33
+ /** Always null unless explicitly supplied — never inferred from Git (#3041). */
34
+ readonly uatVerified: boolean | null;
35
+ }
36
+ export interface DeliveryEvidenceInput {
37
+ readonly repository?: string | null;
38
+ readonly implementationCommit?: string | null;
39
+ readonly prNumber?: number | null;
40
+ readonly prBase?: string | null;
41
+ readonly mergeCommit?: string | null;
42
+ readonly deliveryBranch?: string | null;
43
+ readonly deliveryCommit?: string | null;
44
+ readonly mergedAt?: string | null;
45
+ /** Explicit deploy/UAT (optional; never auto-filled from Git). */
46
+ readonly deployed?: boolean | null;
47
+ readonly uatVerified?: boolean | null;
48
+ readonly verifier?: string | null;
49
+ }
50
+ export interface DeliveryGateOptions {
51
+ readonly projectRoot: string;
52
+ readonly plan: Record<string, unknown>;
53
+ readonly nowIso: string;
54
+ readonly evidence?: DeliveryEvidenceInput | null;
55
+ readonly nonDeliveryDisposition?: NonDeliveryDisposition | null;
56
+ readonly runGit?: GitRunner;
57
+ readonly verifier?: string;
58
+ /**
59
+ * When true, skip remote refresh + ancestry (tests only that inject pre-validated
60
+ * evidence). Production callers leave this false.
61
+ */
62
+ readonly assumeEvidenceValidated?: boolean;
63
+ }
64
+ export interface DeliveryGateResult {
65
+ readonly ok: boolean;
66
+ readonly message: string;
67
+ readonly provenance: CompletionProvenance | null;
68
+ readonly codeBearing: boolean;
69
+ }
70
+ export declare function isNonDeliveryDisposition(value: unknown): value is NonDeliveryDisposition;
71
+ /** True when the brief is treated as code-bearing for the delivery gate (#3041). */
72
+ export declare function isCodeBearingScope(plan: Record<string, unknown>): boolean;
73
+ export declare function hasGithubIssueRef(plan: Record<string, unknown>): boolean;
74
+ /**
75
+ * Classify stored completion provenance for read paths.
76
+ * Legacy completed records without provenance → unknown/unverified (not delivered).
77
+ */
78
+ export declare function classifyStoredDeliveryDisposition(plan: Record<string, unknown>): DeliveryDisposition;
79
+ /**
80
+ * Refresh the remote delivery ref. Failure blocks delivered completion (#3041).
81
+ */
82
+ export declare function refreshRemoteDeliveryRef(projectRoot: string, deliveryBranch: string, runGit?: GitRunner): {
83
+ ok: boolean;
84
+ error: string | null;
85
+ remoteRef: string;
86
+ };
87
+ /**
88
+ * Validate that mergeCommit is an ancestor of the refreshed remote delivery ref.
89
+ */
90
+ export declare function verifyDeliveryAncestry(projectRoot: string, mergeCommit: string, deliveryBranch: string, runGit?: GitRunner): {
91
+ ok: boolean;
92
+ error: string | null;
93
+ remoteTip: string | null;
94
+ };
95
+ /**
96
+ * Gate delivered completion for a code-bearing scope (#3041).
97
+ *
98
+ * Returns ok=true with provenance when:
99
+ * - scope is not code-bearing (provenance may be null or non-code note), OR
100
+ * - explicit non-delivery disposition is provided, OR
101
+ * - durable delivery evidence validates (PR base == deliveryBranch, merge commit
102
+ * ancestor of refreshed remote delivery ref).
103
+ */
104
+ export declare function evaluateDeliveryGate(options: DeliveryGateOptions): DeliveryGateResult;
105
+ /** Stamp completion provenance onto plan.metadata (mutates plan). */
106
+ export declare function stampDeliveryProvenance(plan: Record<string, unknown>, provenance: CompletionProvenance): void;
107
+ /**
108
+ * Parse a PR REST payload into delivery evidence fields.
109
+ * Expects GitHub pulls API shape (merged_at, base.ref, merge_commit_sha, …).
110
+ */
111
+ export declare function evidenceFromPrPayload(payload: Record<string, unknown>, prNumber: number, repository: string | null, deliveryBranch?: string | null): DeliveryEvidenceInput;
112
+ //# sourceMappingURL=delivery-evidence.d.ts.map