@deftai/directive-core 0.92.0 → 0.94.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 (111) hide show
  1. package/dist/cache/fetch.d.ts +29 -0
  2. package/dist/cache/fetch.js +131 -4
  3. package/dist/cache/operations.d.ts +8 -0
  4. package/dist/cache/operations.js +67 -4
  5. package/dist/check/cached-orchestrator.js +11 -0
  6. package/dist/check/consumer-gate-integrity.d.ts +68 -0
  7. package/dist/check/consumer-gate-integrity.js +265 -0
  8. package/dist/check/index.d.ts +1 -0
  9. package/dist/check/index.js +1 -0
  10. package/dist/check/orchestrator.js +10 -0
  11. package/dist/content-contracts/skills/greptile-detector.d.ts +9 -0
  12. package/dist/content-contracts/skills/greptile-detector.js +9 -2
  13. package/dist/doctor/index.d.ts +1 -0
  14. package/dist/doctor/index.js +1 -0
  15. package/dist/doctor/main.js +69 -0
  16. package/dist/doctor/openclaw-l2-adapter.d.ts +26 -0
  17. package/dist/doctor/openclaw-l2-adapter.js +199 -0
  18. package/dist/finish-loop/pr-finish-loop.js +1 -0
  19. package/dist/hooks/dispatcher.d.ts +24 -2
  20. package/dist/hooks/dispatcher.js +122 -11
  21. package/dist/hooks/readonly.d.ts +14 -0
  22. package/dist/hooks/readonly.js +126 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.js +2 -0
  25. package/dist/init-deposit/hygiene.js +22 -0
  26. package/dist/init-deposit/index.d.ts +3 -0
  27. package/dist/init-deposit/index.js +3 -0
  28. package/dist/init-deposit/init-deposit.js +10 -0
  29. package/dist/init-deposit/refresh.js +11 -0
  30. package/dist/init-deposit/scaffold.js +3 -133
  31. package/dist/init-deposit/skill-discovery-deposit.d.ts +65 -0
  32. package/dist/init-deposit/skill-discovery-deposit.js +287 -0
  33. package/dist/init-deposit/skill-discovery-hosts.d.ts +94 -0
  34. package/dist/init-deposit/skill-discovery-hosts.js +217 -0
  35. package/dist/init-deposit/slash-deposit.d.ts +46 -0
  36. package/dist/init-deposit/slash-deposit.js +174 -0
  37. package/dist/intake/issue-ingest.d.ts +20 -0
  38. package/dist/intake/issue-ingest.js +58 -0
  39. package/dist/policy/host-slash-commands.d.ts +28 -0
  40. package/dist/policy/host-slash-commands.js +103 -0
  41. package/dist/policy/index.d.ts +2 -0
  42. package/dist/policy/index.js +61 -7
  43. package/dist/policy/min-greptile-confidence.d.ts +57 -0
  44. package/dist/policy/min-greptile-confidence.js +123 -0
  45. package/dist/pr-merge-readiness/compute.d.ts +11 -1
  46. package/dist/pr-merge-readiness/compute.js +17 -4
  47. package/dist/pr-merge-readiness/evaluate.d.ts +8 -1
  48. package/dist/pr-merge-readiness/evaluate.js +7 -4
  49. package/dist/pr-merge-readiness/mergeability.d.ts +7 -1
  50. package/dist/pr-merge-readiness/mergeability.js +14 -2
  51. package/dist/pr-monitor/main.d.ts +2 -0
  52. package/dist/pr-monitor/main.js +31 -1
  53. package/dist/pr-monitor/monitor.js +5 -1
  54. package/dist/pr-monitor/readiness.js +3 -1
  55. package/dist/pr-monitor/types.d.ts +8 -0
  56. package/dist/pr-wait-mergeable/cascade.d.ts +8 -0
  57. package/dist/pr-wait-mergeable/cascade.js +28 -1
  58. package/dist/pr-wait-mergeable/main.d.ts +2 -0
  59. package/dist/pr-wait-mergeable/main.js +16 -0
  60. package/dist/pr-wait-mergeable/types.d.ts +3 -1
  61. package/dist/pr-wait-mergeable/wrappers.d.ts +6 -0
  62. package/dist/pr-wait-mergeable/wrappers.js +3 -0
  63. package/dist/pr-watch/constants.d.ts +4 -1
  64. package/dist/pr-watch/constants.js +5 -2
  65. package/dist/pr-watch/main.js +1 -0
  66. package/dist/pr-watch/probe.d.ts +1 -1
  67. package/dist/pr-watch/probe.js +4 -1
  68. package/dist/pr-watch/types.d.ts +7 -1
  69. package/dist/pr-watch/watch.js +3 -2
  70. package/dist/review-monitor/index.d.ts +1 -0
  71. package/dist/review-monitor/index.js +1 -0
  72. package/dist/review-monitor/l4-owner.d.ts +46 -0
  73. package/dist/review-monitor/l4-owner.js +262 -0
  74. package/dist/slash/emitters.d.ts +102 -0
  75. package/dist/slash/emitters.js +148 -0
  76. package/dist/slash/generator.d.ts +98 -0
  77. package/dist/slash/generator.js +145 -0
  78. package/dist/slash/index.d.ts +16 -0
  79. package/dist/slash/index.js +16 -0
  80. package/dist/slash/openclaw-adapter.d.ts +64 -0
  81. package/dist/slash/openclaw-adapter.js +198 -0
  82. package/dist/slash/openclaw-deposit.d.ts +73 -0
  83. package/dist/slash/openclaw-deposit.js +279 -0
  84. package/dist/slash/openclaw-slugs.d.ts +52 -0
  85. package/dist/slash/openclaw-slugs.js +126 -0
  86. package/dist/slash/product-set.d.ts +50 -0
  87. package/dist/slash/product-set.js +142 -0
  88. package/dist/tool-events/classify.js +1 -0
  89. package/dist/triage/welcome/writers.js +16 -7
  90. package/dist/umbrella-current-shape/index.d.ts +45 -0
  91. package/dist/umbrella-current-shape/index.js +162 -8
  92. package/dist/vbrief-reconcile/index.d.ts +2 -2
  93. package/dist/vbrief-reconcile/index.js +1 -1
  94. package/dist/vbrief-reconcile/types.d.ts +14 -0
  95. package/dist/vbrief-reconcile/umbrellas.d.ts +31 -2
  96. package/dist/vbrief-reconcile/umbrellas.js +231 -19
  97. package/dist/vbrief-validate/plan-hooks.d.ts +4 -0
  98. package/dist/vbrief-validate/plan-hooks.js +50 -0
  99. package/dist/xbrief/create.d.ts +36 -0
  100. package/dist/xbrief/create.js +285 -0
  101. package/dist/xbrief/index.d.ts +14 -0
  102. package/dist/xbrief/index.js +42 -0
  103. package/dist/xbrief/paths.d.ts +37 -0
  104. package/dist/xbrief/paths.js +123 -0
  105. package/dist/xbrief/styles.d.ts +36 -0
  106. package/dist/xbrief/styles.js +235 -0
  107. package/dist/xbrief/types.d.ts +50 -0
  108. package/dist/xbrief/types.js +17 -0
  109. package/dist/xbrief/verify.d.ts +30 -0
  110. package/dist/xbrief/verify.js +251 -0
  111. 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
@@ -6,8 +6,10 @@ export * from "./deft-directive-disable.js";
6
6
  export * from "./delivery-branch.js";
7
7
  export * from "./disclosure.js";
8
8
  export * from "./host-hooks.js";
9
+ export * from "./host-slash-commands.js";
9
10
  export * from "./hotfix-criteria.js";
10
11
  export * from "./intent-ceiling.js";
12
+ export * from "./min-greptile-confidence.js";
11
13
  export * from "./no-deft-directive.js";
12
14
  export * from "./org-force-on-migration.js";
13
15
  export * from "./plan-extensions.js";
@@ -1,6 +1,10 @@
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";
1
3
  import { FIELD_DELIVERY_BRANCH, FIELD_DELIVERY_BRANCH_CLI_ALIAS, inspectDeliveryBranch, } from "./delivery-branch.js";
2
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";
3
6
  import { FIELD_HOTFIX_CRITERIA, FIELD_HOTFIX_CRITERIA_CLI_ALIAS, inspectHotfixCriteria, } from "./hotfix-criteria.js";
7
+ import { FIELD_MIN_GREPTILE_CONFIDENCE, FIELD_MIN_GREPTILE_CONFIDENCE_CLI_ALIAS, inspectMinGreptileConfidence, } from "./min-greptile-confidence.js";
4
8
  import { readPlanPolicy } from "./plan-extensions.js";
5
9
  import { FIELD_PRODUCT_SIGNAL, FIELD_PRODUCT_SIGNAL_CLI_ALIAS, inspectProductSignal, } from "./product-signal.js";
6
10
  import { FIELD_REQUIRE_HUMAN_MERGE, FIELD_REQUIRE_HUMAN_MERGE_CLI_ALIAS, inspectRequireHumanMerge, } from "./require-human-merge.js";
@@ -17,8 +21,10 @@ export * from "./deft-directive-disable.js";
17
21
  export * from "./delivery-branch.js";
18
22
  export * from "./disclosure.js";
19
23
  export * from "./host-hooks.js";
24
+ export * from "./host-slash-commands.js";
20
25
  export * from "./hotfix-criteria.js";
21
26
  export * from "./intent-ceiling.js";
27
+ export * from "./min-greptile-confidence.js";
22
28
  export * from "./no-deft-directive.js";
23
29
  export * from "./org-force-on-migration.js";
24
30
  export * from "./plan-extensions.js";
@@ -282,6 +288,33 @@ function inspectHostHooksField(data) {
282
288
  source: field.source,
283
289
  };
284
290
  }
291
+ function inspectHostSlashCommandsField(data) {
292
+ const field = inspectHostSlashCommands(data);
293
+ return {
294
+ name: field.name,
295
+ current: field.current,
296
+ default: field.default,
297
+ source: field.source,
298
+ };
299
+ }
300
+ function inspectOpenClawProductCommandsField(data) {
301
+ const field = inspectOpenClawProductCommands(data);
302
+ return {
303
+ name: field.name,
304
+ current: field.current,
305
+ default: field.default,
306
+ source: field.source,
307
+ };
308
+ }
309
+ function inspectHostSkillDiscoveryField(data) {
310
+ const field = inspectHostSkillDiscovery(data);
311
+ return {
312
+ name: field.name,
313
+ current: field.current,
314
+ default: field.default,
315
+ source: field.source,
316
+ };
317
+ }
285
318
  function inspectRequireHumanMergeField(data, projectRoot) {
286
319
  const field = inspectRequireHumanMerge(data, projectRoot);
287
320
  return {
@@ -309,6 +342,15 @@ function inspectDeliveryBranchField(data, projectRoot) {
309
342
  source: field.source,
310
343
  };
311
344
  }
345
+ function inspectMinGreptileConfidenceField(data, projectRoot) {
346
+ const field = inspectMinGreptileConfidence(data, projectRoot);
347
+ return {
348
+ name: field.name,
349
+ current: field.current,
350
+ default: field.default,
351
+ source: field.source,
352
+ };
353
+ }
312
354
  const REGISTERED_POLICIES = [
313
355
  inspectAllowDirectCommits,
314
356
  inspectWipCap,
@@ -322,7 +364,11 @@ const REGISTERED_POLICIES = [
322
364
  }),
323
365
  inspectSwarmSubagentBackend,
324
366
  inspectDeliveryBranchField,
367
+ inspectMinGreptileConfidenceField,
325
368
  inspectHostHooksField,
369
+ inspectHostSlashCommandsField,
370
+ inspectOpenClawProductCommandsField,
371
+ inspectHostSkillDiscoveryField,
326
372
  inspectStalenessTicklerField,
327
373
  inspectRuntimeAuthorityField,
328
374
  inspectProductSignalField,
@@ -347,13 +393,21 @@ export function inspectOnePolicy(name, projectRoot) {
347
393
  ? FIELD_RUNTIME_AUTHORITY
348
394
  : name === FIELD_HOST_HOOKS_CLI_ALIAS
349
395
  ? FIELD_HOST_HOOKS
350
- : name === FIELD_REQUIRE_HUMAN_MERGE_CLI_ALIAS
351
- ? FIELD_REQUIRE_HUMAN_MERGE
352
- : name === FIELD_HOTFIX_CRITERIA_CLI_ALIAS
353
- ? FIELD_HOTFIX_CRITERIA
354
- : name === FIELD_DELIVERY_BRANCH_CLI_ALIAS
355
- ? FIELD_DELIVERY_BRANCH
356
- : name;
396
+ : name === FIELD_HOST_SLASH_COMMANDS_CLI_ALIAS
397
+ ? FIELD_HOST_SLASH_COMMANDS
398
+ : name === FIELD_OPENCLAW_PRODUCT_COMMANDS_CLI_ALIAS
399
+ ? FIELD_OPENCLAW_PRODUCT_COMMANDS
400
+ : name === FIELD_HOST_SKILL_DISCOVERY_CLI_ALIAS
401
+ ? FIELD_HOST_SKILL_DISCOVERY
402
+ : name === FIELD_REQUIRE_HUMAN_MERGE_CLI_ALIAS
403
+ ? FIELD_REQUIRE_HUMAN_MERGE
404
+ : name === FIELD_HOTFIX_CRITERIA_CLI_ALIAS
405
+ ? FIELD_HOTFIX_CRITERIA
406
+ : name === FIELD_DELIVERY_BRANCH_CLI_ALIAS
407
+ ? FIELD_DELIVERY_BRANCH
408
+ : name === FIELD_MIN_GREPTILE_CONFIDENCE_CLI_ALIAS
409
+ ? FIELD_MIN_GREPTILE_CONFIDENCE
410
+ : name;
357
411
  for (const field of inspectAllPolicies(projectRoot)) {
358
412
  if (field.name === normalized)
359
413
  return field;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Typed plan.policy.review.minGreptileConfidence (#3095).
3
+ *
4
+ * CLEAN / merge-ready require Greptile confidence >= min (score out of 5).
5
+ * Resolution order: explicit project policy > framework dogfood detect > consumer default.
6
+ *
7
+ * - Consumer default: 4 (legacy bar confidence > 3, i.e. 4/5 or 5/5)
8
+ * - Directive dogfood (framework source checkout): 5 (5/5 required)
9
+ */
10
+ /** Canonical dotted path for policy:show / PROJECT-DEFINITION. */
11
+ export declare const FIELD_MIN_GREPTILE_CONFIDENCE = "plan.policy.review.minGreptileConfidence";
12
+ /** CLI alias for `task policy:show --field=minGreptileConfidence`. */
13
+ export declare const FIELD_MIN_GREPTILE_CONFIDENCE_CLI_ALIAS = "minGreptileConfidence";
14
+ /**
15
+ * Consumer default minimum confidence that still CLEANs (#3095).
16
+ * Matches the historical gate `confidence > 3` (i.e. score >= 4).
17
+ */
18
+ export declare const DEFAULT_CONSUMER_MIN_GREPTILE_CONFIDENCE = 4;
19
+ /** Directive dogfood bar: CLEAN requires confidence == 5/5. */
20
+ export declare const DOGFOOD_MIN_GREPTILE_CONFIDENCE = 5;
21
+ export declare const MIN_GREPTILE_CONFIDENCE_FLOOR = 1;
22
+ export declare const MIN_GREPTILE_CONFIDENCE_CEILING = 5;
23
+ export type MinGreptileConfidenceSource = "typed" | "dogfood" | "default" | "default-on-error";
24
+ export interface MinGreptileConfidenceResolved {
25
+ /** Minimum score (1–5) that satisfies CLEAN; score must be >= min. */
26
+ readonly min: number;
27
+ readonly source: MinGreptileConfidenceSource;
28
+ readonly error: string | null;
29
+ }
30
+ /** True when score is present and meets the minimum floor. */
31
+ export declare function meetsMinGreptileConfidence(confidence: number | null | undefined, min: number): boolean;
32
+ /** Human-facing phrase for the active bar (legacy "> 3" when min is 4). */
33
+ export declare function formatMinConfidenceRequirement(min: number): string;
34
+ /** Validate a raw integer-ish min confidence value. */
35
+ export declare function validateMinGreptileConfidence(raw: unknown): string | null;
36
+ /**
37
+ * Read nested plan.policy.review.minGreptileConfidence from a policy block.
38
+ * Returns undefined when the key is absent.
39
+ */
40
+ export declare function readMinGreptileConfidenceFromPolicyBlock(policyBlock: unknown): unknown | undefined;
41
+ /**
42
+ * Resolve min Greptile confidence for CLEAN gates (#3095).
43
+ *
44
+ * 1. Explicit typed plan.policy.review.minGreptileConfidence
45
+ * 2. Framework dogfood detection (framework source repo root) → 5
46
+ * 3. Consumer default → 4
47
+ */
48
+ export declare function resolveMinGreptileConfidence(projectRoot?: string | null): MinGreptileConfidenceResolved;
49
+ export interface MinGreptileConfidencePolicyField {
50
+ readonly name: typeof FIELD_MIN_GREPTILE_CONFIDENCE;
51
+ readonly current: number;
52
+ readonly default: number;
53
+ readonly source: string;
54
+ }
55
+ /** Inspector row for `task policy:show --field=minGreptileConfidence` (#3095). */
56
+ export declare function inspectMinGreptileConfidence(_data: Record<string, unknown> | null, projectRoot?: string): MinGreptileConfidencePolicyField;
57
+ //# sourceMappingURL=min-greptile-confidence.d.ts.map
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Typed plan.policy.review.minGreptileConfidence (#3095).
3
+ *
4
+ * CLEAN / merge-ready require Greptile confidence >= min (score out of 5).
5
+ * Resolution order: explicit project policy > framework dogfood detect > consumer default.
6
+ *
7
+ * - Consumer default: 4 (legacy bar confidence > 3, i.e. 4/5 or 5/5)
8
+ * - Directive dogfood (framework source checkout): 5 (5/5 required)
9
+ */
10
+ import { isFrameworkRepoRoot } from "../check/context.js";
11
+ import { readPlanPolicy } from "./plan-extensions.js";
12
+ import { loadProjectDefinition } from "./resolve.js";
13
+ /** Canonical dotted path for policy:show / PROJECT-DEFINITION. */
14
+ export const FIELD_MIN_GREPTILE_CONFIDENCE = "plan.policy.review.minGreptileConfidence";
15
+ /** CLI alias for `task policy:show --field=minGreptileConfidence`. */
16
+ export const FIELD_MIN_GREPTILE_CONFIDENCE_CLI_ALIAS = "minGreptileConfidence";
17
+ /**
18
+ * Consumer default minimum confidence that still CLEANs (#3095).
19
+ * Matches the historical gate `confidence > 3` (i.e. score >= 4).
20
+ */
21
+ export const DEFAULT_CONSUMER_MIN_GREPTILE_CONFIDENCE = 4;
22
+ /** Directive dogfood bar: CLEAN requires confidence == 5/5. */
23
+ export const DOGFOOD_MIN_GREPTILE_CONFIDENCE = 5;
24
+ export const MIN_GREPTILE_CONFIDENCE_FLOOR = 1;
25
+ export const MIN_GREPTILE_CONFIDENCE_CEILING = 5;
26
+ function defaultResolved(source, min, error = null) {
27
+ return { min, source, error };
28
+ }
29
+ /** True when score is present and meets the minimum floor. */
30
+ export function meetsMinGreptileConfidence(confidence, min) {
31
+ if (confidence === null || confidence === undefined) {
32
+ return false;
33
+ }
34
+ return confidence >= min;
35
+ }
36
+ /** Human-facing phrase for the active bar (legacy "> 3" when min is 4). */
37
+ export function formatMinConfidenceRequirement(min) {
38
+ if (min === DEFAULT_CONSUMER_MIN_GREPTILE_CONFIDENCE) {
39
+ return `> ${min - 1} (i.e. ${min}/5+)`;
40
+ }
41
+ return `>= ${min}/5`;
42
+ }
43
+ /** Validate a raw integer-ish min confidence value. */
44
+ export function validateMinGreptileConfidence(raw) {
45
+ if (typeof raw !== "number" || !Number.isInteger(raw)) {
46
+ return `${FIELD_MIN_GREPTILE_CONFIDENCE} must be an integer ${MIN_GREPTILE_CONFIDENCE_FLOOR}–${MIN_GREPTILE_CONFIDENCE_CEILING}; got ${typeof raw}`;
47
+ }
48
+ if (raw < MIN_GREPTILE_CONFIDENCE_FLOOR || raw > MIN_GREPTILE_CONFIDENCE_CEILING) {
49
+ return `${FIELD_MIN_GREPTILE_CONFIDENCE} must be between ${MIN_GREPTILE_CONFIDENCE_FLOOR} and ${MIN_GREPTILE_CONFIDENCE_CEILING}; got ${raw}`;
50
+ }
51
+ return null;
52
+ }
53
+ /**
54
+ * Read nested plan.policy.review.minGreptileConfidence from a policy block.
55
+ * Returns undefined when the key is absent.
56
+ */
57
+ export function readMinGreptileConfidenceFromPolicyBlock(policyBlock) {
58
+ if (typeof policyBlock !== "object" || policyBlock === null || Array.isArray(policyBlock)) {
59
+ return undefined;
60
+ }
61
+ const rec = policyBlock;
62
+ if (!("review" in rec)) {
63
+ return undefined;
64
+ }
65
+ const review = rec.review;
66
+ if (typeof review !== "object" || review === null || Array.isArray(review)) {
67
+ return undefined;
68
+ }
69
+ const reviewRec = review;
70
+ if (!("minGreptileConfidence" in reviewRec)) {
71
+ return undefined;
72
+ }
73
+ return reviewRec.minGreptileConfidence;
74
+ }
75
+ /**
76
+ * Resolve min Greptile confidence for CLEAN gates (#3095).
77
+ *
78
+ * 1. Explicit typed plan.policy.review.minGreptileConfidence
79
+ * 2. Framework dogfood detection (framework source repo root) → 5
80
+ * 3. Consumer default → 4
81
+ */
82
+ export function resolveMinGreptileConfidence(projectRoot) {
83
+ if (projectRoot !== undefined && projectRoot !== null && projectRoot.length > 0) {
84
+ const [data, err] = loadProjectDefinition(projectRoot);
85
+ if (data !== null) {
86
+ const policyBlock = readPlanPolicy(data.plan);
87
+ const raw = readMinGreptileConfidenceFromPolicyBlock(policyBlock);
88
+ if (raw !== undefined) {
89
+ const validationError = validateMinGreptileConfidence(raw);
90
+ if (validationError !== null) {
91
+ // Invalid typed value: fall through to dogfood/default with error recorded.
92
+ if (isFrameworkRepoRoot(projectRoot)) {
93
+ return defaultResolved("dogfood", DOGFOOD_MIN_GREPTILE_CONFIDENCE, validationError);
94
+ }
95
+ return defaultResolved("default-on-error", DEFAULT_CONSUMER_MIN_GREPTILE_CONFIDENCE, validationError);
96
+ }
97
+ return defaultResolved("typed", raw, null);
98
+ }
99
+ }
100
+ else if (err !== null && err.length > 0) {
101
+ // Missing PROJECT-DEFINITION is not fatal; dogfood/default still apply.
102
+ if (isFrameworkRepoRoot(projectRoot)) {
103
+ return defaultResolved("dogfood", DOGFOOD_MIN_GREPTILE_CONFIDENCE, null);
104
+ }
105
+ return defaultResolved("default", DEFAULT_CONSUMER_MIN_GREPTILE_CONFIDENCE, err);
106
+ }
107
+ if (isFrameworkRepoRoot(projectRoot)) {
108
+ return defaultResolved("dogfood", DOGFOOD_MIN_GREPTILE_CONFIDENCE, null);
109
+ }
110
+ }
111
+ return defaultResolved("default", DEFAULT_CONSUMER_MIN_GREPTILE_CONFIDENCE, null);
112
+ }
113
+ /** Inspector row for `task policy:show --field=minGreptileConfidence` (#3095). */
114
+ export function inspectMinGreptileConfidence(_data, projectRoot) {
115
+ const resolved = resolveMinGreptileConfidence(projectRoot);
116
+ return {
117
+ name: FIELD_MIN_GREPTILE_CONFIDENCE,
118
+ current: resolved.min,
119
+ default: DEFAULT_CONSUMER_MIN_GREPTILE_CONFIDENCE,
120
+ source: resolved.source,
121
+ };
122
+ }
123
+ //# sourceMappingURL=min-greptile-confidence.js.map
@@ -4,7 +4,7 @@ import { type InlineGreptileFindings } from "./greptile-inline.js";
4
4
  import { type MergeabilitySignal } from "./mergeability.js";
5
5
  import type { SlizardGateOptions } from "./slizard-gate.js";
6
6
  import type { GateResult, RunGhFn } from "./types.js";
7
- declare function buildGateResult(prNumber: number, repo: string | null, headSha: string | null, body: string, via: string, partialData?: Record<string, unknown>, error?: string | null, inline?: InlineGreptileFindings | null): GateResult;
7
+ declare function buildGateResult(prNumber: number, repo: string | null, headSha: string | null, body: string, via: string, partialData?: Record<string, unknown>, error?: string | null, inline?: InlineGreptileFindings | null, minConfidence?: number): GateResult;
8
8
  /** Injectable GitHub-mergeability read seam (#2260) — keeps unit tests hermetic. */
9
9
  export type FetchMergeabilityFn = (prNumber: number, repo: string, runGh: RunGhFn) => MergeabilitySignal;
10
10
  export interface ComputeGateOptions extends CiGateOptions, SlizardGateOptions {
@@ -15,6 +15,16 @@ export interface ComputeGateOptions extends CiGateOptions, SlizardGateOptions {
15
15
  * off, an absent/stale review verdict blocks even on a GitHub-CLEAN PR.
16
16
  */
17
17
  readonly disableMergeabilityReconcile?: boolean;
18
+ /**
19
+ * Project root for resolving plan.policy.review.minGreptileConfidence (#3095).
20
+ * Defaults to process.cwd() when omitted.
21
+ */
22
+ readonly projectRoot?: string | null;
23
+ /**
24
+ * Override the resolved min confidence (1–5). When set, skips policy resolve.
25
+ * Tests and injectors use this; production callers leave it unset.
26
+ */
27
+ readonly minConfidence?: number;
18
28
  }
19
29
  /** Run the primary->fallback1->fallback2 cascade and return a result. */
20
30
  export declare function computeGateResult(prNumber: number, repo: string | null, runGh: RunGhFn, options?: ComputeGateOptions): GateResult;
@@ -1,3 +1,4 @@
1
+ import { resolveMinGreptileConfidence } from "../policy/min-greptile-confidence.js";
1
2
  import { buildCiSummaryLine, evaluateCiGate } from "./ci-gate.js";
2
3
  import { FALLBACK2_NOT_CLEAN_MSG, VIA_ERROR, VIA_FALLBACK1, VIA_FALLBACK2, VIA_PRIMARY, } from "./constants.js";
3
4
  import { evaluateGates, isMergeReady } from "./evaluate.js";
@@ -6,9 +7,11 @@ import { fetchUnresolvedGreptileInlineFindings, inlineFindingsToDict, } from "./
6
7
  import { fetchMergeability, isGithubMergeableClean, mergeabilityToDict, verdictBlockIsSoftOnly, verdictShaIsStale, } from "./mergeability.js";
7
8
  import { emptyVerdict, parseGreptileBody } from "./parse.js";
8
9
  import { evaluateSlizardGate, isSlizardCheck } from "./slizard-gate.js";
9
- function buildGateResult(prNumber, repo, headSha, body, via, partialData = {}, error = null, inline = null) {
10
+ function buildGateResult(prNumber, repo, headSha, body, via, partialData = {}, error = null, inline = null, minConfidence) {
10
11
  const verdict = parseGreptileBody(body);
11
- const failures = evaluateGates(prNumber, headSha, verdict, inline);
12
+ const failures = evaluateGates(prNumber, headSha, verdict, inline, {
13
+ minConfidence,
14
+ });
12
15
  return {
13
16
  prNumber,
14
17
  repo,
@@ -20,6 +23,12 @@ function buildGateResult(prNumber, repo, headSha, body, via, partialData = {}, e
20
23
  error,
21
24
  };
22
25
  }
26
+ function resolvedMinConfidence(options) {
27
+ if (options.minConfidence !== undefined) {
28
+ return options.minConfidence;
29
+ }
30
+ return resolveMinGreptileConfidence(options.projectRoot ?? process.cwd()).min;
31
+ }
23
32
  /** Run the CI + SLizard gates off a single check-runs fetch (#2169 / #2189). */
24
33
  function evaluateCiAndSlizard(checkRuns, options) {
25
34
  const slizardResult = evaluateSlizardGate(checkRuns, options);
@@ -110,7 +119,11 @@ function finalizeVerdictGate(prNumber, repo, headSha, verdict, runGh, options) {
110
119
  const resolved = resolveRepo(repo, runGh);
111
120
  const inline = loadInlineGreptileFindings(prNumber, repo, headSha, runGh);
112
121
  partialData.greptile_inline = inlineFindingsToDict(inline);
113
- const failures = evaluateGates(prNumber, headSha, verdict, inline);
122
+ const minConfidence = resolvedMinConfidence(options);
123
+ partialData.min_greptile_confidence = minConfidence;
124
+ const failures = evaluateGates(prNumber, headSha, verdict, inline, {
125
+ minConfidence,
126
+ });
114
127
  if (failures.length === 0) {
115
128
  const ci = applyCiGateForHead(resolved.repo, headSha, runGh, options);
116
129
  failures.push(...ci.failures);
@@ -123,7 +136,7 @@ function finalizeVerdictGate(prNumber, repo, headSha, verdict, runGh, options) {
123
136
  // blocking. Only reconcile a SOFT block (verdict absent / stale head SHA).
124
137
  if (options.disableMergeabilityReconcile === true ||
125
138
  resolved.repo === null ||
126
- !verdictBlockIsSoftOnly(verdict, headSha, inline)) {
139
+ !verdictBlockIsSoftOnly(verdict, headSha, inline, minConfidence)) {
127
140
  return { failures, partialData };
128
141
  }
129
142
  const ci = applyCiGateForHead(resolved.repo, headSha, runGh, options);
@@ -1,6 +1,13 @@
1
1
  import type { InlineGreptileFindings } from "./greptile-inline.js";
2
2
  import type { GreptileVerdict } from "./types.js";
3
+ export interface EvaluateGatesOptions {
4
+ /**
5
+ * Minimum Greptile confidence (1–5) that satisfies CLEAN (#3095).
6
+ * Defaults to the consumer bar (4 == legacy confidence > 3).
7
+ */
8
+ readonly minConfidence?: number;
9
+ }
3
10
  /** Return failure messages (empty list == merge-ready). */
4
- export declare function evaluateGates(_prNumber: number, headSha: string | null, verdict: GreptileVerdict, inline?: InlineGreptileFindings | null): string[];
11
+ export declare function evaluateGates(_prNumber: number, headSha: string | null, verdict: GreptileVerdict, inline?: InlineGreptileFindings | null, options?: EvaluateGatesOptions): string[];
5
12
  export declare function isMergeReady(failures: readonly string[]): boolean;
6
13
  //# sourceMappingURL=evaluate.d.ts.map
@@ -1,7 +1,9 @@
1
+ import { DEFAULT_CONSUMER_MIN_GREPTILE_CONFIDENCE, formatMinConfidenceRequirement, meetsMinGreptileConfidence, } from "../policy/min-greptile-confidence.js";
1
2
  import { INFORMAL_CLEAN_DIAGNOSTIC } from "./constants.js";
2
3
  /** Return failure messages (empty list == merge-ready). */
3
- export function evaluateGates(_prNumber, headSha, verdict, inline = null) {
4
+ export function evaluateGates(_prNumber, headSha, verdict, inline = null, options = {}) {
4
5
  const failures = [];
6
+ const minConfidence = options.minConfidence ?? DEFAULT_CONSUMER_MIN_GREPTILE_CONFIDENCE;
5
7
  if (!verdict.found) {
6
8
  failures.push("No Greptile rolling-summary comment found on the PR. " +
7
9
  "Either Greptile has not posted yet, or the bot login filter is wrong. " +
@@ -32,9 +34,10 @@ export function evaluateGates(_prNumber, headSha, verdict, inline = null) {
32
34
  "Confidence is a required exit-condition input per " +
33
35
  "skills/deft-directive-review-cycle/SKILL.md Phase 2 Step 6.");
34
36
  }
35
- else if (verdict.confidence <= 3) {
36
- failures.push(`Greptile confidence is ${verdict.confidence}/5; exit condition requires > 3. ` +
37
- "Address remaining findings or push clarifying changes.");
37
+ else if (!meetsMinGreptileConfidence(verdict.confidence, minConfidence)) {
38
+ failures.push(`Greptile confidence is ${verdict.confidence}/5; exit condition requires ${formatMinConfidenceRequirement(minConfidence)}. ` +
39
+ "Address remaining findings or push clarifying changes. " +
40
+ "Inspect the floor via `task policy:show --field=minGreptileConfidence` (#3095).");
38
41
  }
39
42
  if (verdict.p0Count > 0 || verdict.p1Count > 0) {
40
43
  failures.push(`Greptile reports ${verdict.p0Count} P0 and ${verdict.p1Count} P1 findings ` +
@@ -42,5 +42,11 @@ export declare function verdictShaIsStale(verdict: GreptileVerdict, headSha: str
42
42
  * regardless of GitHub mergeability (guardrail: do not merge a PR with a real
43
43
  * P0/P1 review finding).
44
44
  */
45
- export declare function verdictBlockIsSoftOnly(verdict: GreptileVerdict, headSha: string | null, inline?: InlineGreptileFindings | null): boolean;
45
+ export declare function verdictBlockIsSoftOnly(verdict: GreptileVerdict, headSha: string | null, inline?: InlineGreptileFindings | null,
46
+ /**
47
+ * Resolved min Greptile confidence (1–5). Scores below this are HARD blockers
48
+ * and must never be reconciled away via GitHub CLEAN (#3095). Defaults to the
49
+ * consumer floor (4).
50
+ */
51
+ minConfidence?: number): boolean;
46
52
  //# sourceMappingURL=mergeability.d.ts.map
@@ -1,3 +1,4 @@
1
+ import { meetsMinGreptileConfidence } from "../policy/min-greptile-confidence.js";
1
2
  /** REST `mergeable_state` value that mirrors GraphQL `mergeStateStatus: CLEAN`. */
2
3
  export const MERGE_STATE_CLEAN = "clean";
3
4
  /**
@@ -75,7 +76,13 @@ export function verdictShaIsStale(verdict, headSha) {
75
76
  * regardless of GitHub mergeability (guardrail: do not merge a PR with a real
76
77
  * P0/P1 review finding).
77
78
  */
78
- export function verdictBlockIsSoftOnly(verdict, headSha, inline = null) {
79
+ export function verdictBlockIsSoftOnly(verdict, headSha, inline = null,
80
+ /**
81
+ * Resolved min Greptile confidence (1–5). Scores below this are HARD blockers
82
+ * and must never be reconciled away via GitHub CLEAN (#3095). Defaults to the
83
+ * consumer floor (4).
84
+ */
85
+ minConfidence = 4) {
79
86
  if (inline !== null && inline.error !== null) {
80
87
  return false;
81
88
  }
@@ -99,7 +106,12 @@ export function verdictBlockIsSoftOnly(verdict, headSha, inline = null) {
99
106
  if (verdict.errored) {
100
107
  return false;
101
108
  }
102
- if (verdict.confidence !== null && verdict.confidence <= 3) {
109
+ // Confidence below the resolved floor is a hard blocker (#2260 / #3095).
110
+ // Dogfood/policy may set min=5 so a 4/5 score stays hard even when GitHub
111
+ // reports CLEAN + MERGEABLE. Use the shared predicate so the export is on
112
+ // the production call path (SLizard #3095).
113
+ if (verdict.confidence !== null &&
114
+ !meetsMinGreptileConfidence(verdict.confidence, minConfidence)) {
103
115
  return false;
104
116
  }
105
117
  if (verdict.p0Count > 0 || verdict.p1Count > 0) {
@@ -5,6 +5,8 @@ export interface ParsedMonitorArgs {
5
5
  readonly repo: string | null;
6
6
  readonly capMinutes: number;
7
7
  readonly emitJson: boolean;
8
+ /** Project root for minGreptileConfidence (#3095 / #3102). Null = default cwd at run. */
9
+ readonly projectRoot: string | null;
8
10
  readonly error?: string;
9
11
  }
10
12
  export declare function parseMonitorArgs(argv: readonly string[]): ParsedMonitorArgs;