@deftai/directive-core 0.96.0 → 0.97.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 (73) hide show
  1. package/dist/cache/archive.js +10 -4
  2. package/dist/check/gate-lists.js +8 -0
  3. package/dist/consumer-check-contract/evaluate.d.ts +124 -0
  4. package/dist/consumer-check-contract/evaluate.js +699 -0
  5. package/dist/consumer-check-contract/index.d.ts +5 -0
  6. package/dist/consumer-check-contract/index.js +5 -0
  7. package/dist/delivery-attempt/disk-begin.d.ts +51 -0
  8. package/dist/delivery-attempt/disk-begin.js +68 -0
  9. package/dist/delivery-attempt/evaluate.d.ts +26 -0
  10. package/dist/delivery-attempt/evaluate.js +443 -0
  11. package/dist/delivery-attempt/fingerprint.d.ts +32 -0
  12. package/dist/delivery-attempt/fingerprint.js +100 -0
  13. package/dist/delivery-attempt/handoff.d.ts +25 -0
  14. package/dist/delivery-attempt/handoff.js +102 -0
  15. package/dist/delivery-attempt/index.d.ts +17 -0
  16. package/dist/delivery-attempt/index.js +17 -0
  17. package/dist/delivery-attempt/ledger.d.ts +169 -0
  18. package/dist/delivery-attempt/ledger.js +758 -0
  19. package/dist/delivery-attempt/material-delta.d.ts +38 -0
  20. package/dist/delivery-attempt/material-delta.js +126 -0
  21. package/dist/delivery-attempt/types.d.ts +210 -0
  22. package/dist/delivery-attempt/types.js +77 -0
  23. package/dist/doctor/index.d.ts +1 -0
  24. package/dist/doctor/index.js +1 -0
  25. package/dist/doctor/main.js +12 -0
  26. package/dist/doctor/openclaw-soft-rebind.d.ts +26 -0
  27. package/dist/doctor/openclaw-soft-rebind.js +164 -0
  28. package/dist/hooks/dispatcher.d.ts +2 -1
  29. package/dist/hooks/dispatcher.js +63 -9
  30. package/dist/index.d.ts +4 -0
  31. package/dist/index.js +4 -0
  32. package/dist/init-deposit/gitignore.js +7 -0
  33. package/dist/init-deposit/init-deposit.js +5 -0
  34. package/dist/init-deposit/refresh.js +3 -0
  35. package/dist/pr-merge-readiness/ci-gate.d.ts +29 -1
  36. package/dist/pr-merge-readiness/ci-gate.js +191 -24
  37. package/dist/pr-merge-readiness/compute.js +10 -1
  38. package/dist/pr-merge-readiness/index.d.ts +2 -1
  39. package/dist/pr-merge-readiness/index.js +2 -1
  40. package/dist/pr-merge-readiness/output.js +14 -0
  41. package/dist/pr-merge-readiness/platform-status.d.ts +29 -0
  42. package/dist/pr-merge-readiness/platform-status.js +49 -0
  43. package/dist/pr-watch/constants.d.ts +10 -0
  44. package/dist/pr-watch/constants.js +12 -1
  45. package/dist/pr-watch/main.js +16 -1
  46. package/dist/pr-watch/probe.js +13 -1
  47. package/dist/pr-watch/types.d.ts +3 -2
  48. package/dist/pr-watch/watch.js +14 -7
  49. package/dist/scope-provenance/digest.d.ts +67 -0
  50. package/dist/scope-provenance/digest.js +188 -0
  51. package/dist/scope-provenance/evaluate.d.ts +82 -0
  52. package/dist/scope-provenance/evaluate.js +528 -0
  53. package/dist/scope-provenance/index.d.ts +6 -0
  54. package/dist/scope-provenance/index.js +6 -0
  55. package/dist/session/compact-ritual.d.ts +96 -0
  56. package/dist/session/compact-ritual.js +237 -0
  57. package/dist/session/compact-ritual.spec.d.ts +2 -0
  58. package/dist/session/compact-ritual.spec.js +21 -0
  59. package/dist/session/index.d.ts +2 -0
  60. package/dist/session/index.js +2 -0
  61. package/dist/session/openclaw-soft-rebind-deposit.d.ts +46 -0
  62. package/dist/session/openclaw-soft-rebind-deposit.js +165 -0
  63. package/dist/test-boundary/evaluate.d.ts +54 -0
  64. package/dist/test-boundary/evaluate.js +368 -0
  65. package/dist/test-boundary/index.d.ts +6 -0
  66. package/dist/test-boundary/index.js +6 -0
  67. package/dist/test-boundary/policy.d.ts +52 -0
  68. package/dist/test-boundary/policy.js +182 -0
  69. package/dist/triage/bootstrap/gitignore.d.ts +1 -1
  70. package/dist/triage/bootstrap/gitignore.js +15 -1
  71. package/dist/vbrief-activate/activate.js +22 -6
  72. package/dist/xbrief/styles.js +33 -17
  73. package/package.json +7 -3
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Material-progress evaluation for delivery-attempt circuit breaker (#3143).
3
+ *
4
+ * Material progress = verifiable state change that can resolve or advance
5
+ * beyond the current failure. New revision ids, worker swaps, compaction,
6
+ * and analysis restatement alone are not material progress.
7
+ */
8
+ import type { FailureInfo, MaterialDeltaClaim, MaterialDeltaKind } from "./types.js";
9
+ export interface MaterialProgressResult {
10
+ readonly isMaterial: boolean;
11
+ readonly classification: MaterialDeltaKind | "none";
12
+ readonly relevantClaims: readonly MaterialDeltaClaim[];
13
+ readonly reason: string;
14
+ }
15
+ /**
16
+ * Whether claimed deltas address the current failure (or advance stage).
17
+ *
18
+ * Source-bound evidence: claims whose sourceRevision does not match the
19
+ * evaluated revision are ignored (cannot treat intermediate evidence as
20
+ * valid for a later revision).
21
+ */
22
+ export declare function evaluateMaterialProgress(options: {
23
+ readonly claims: readonly MaterialDeltaClaim[] | null | undefined;
24
+ readonly failure: FailureInfo | null | undefined;
25
+ readonly evaluatedRevision: string;
26
+ /**
27
+ * When true (default), evidence/external claims must match evaluatedRevision.
28
+ * Code/config/stage claims may apply if addresses match even when revision
29
+ * changed (the new revision *is* the delta carrier).
30
+ */
31
+ readonly enforceSourceBoundEvidence?: boolean;
32
+ }): MaterialProgressResult;
33
+ /**
34
+ * Whether a new revision alone constitutes material progress.
35
+ * Issue contract: creating a new revision identifier is NOT material progress.
36
+ */
37
+ export declare function isRevisionChangeMaterial(_previousRevision: string | null, _nextRevision: string): boolean;
38
+ //# sourceMappingURL=material-delta.d.ts.map
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Material-progress evaluation for delivery-attempt circuit breaker (#3143).
3
+ *
4
+ * Material progress = verifiable state change that can resolve or advance
5
+ * beyond the current failure. New revision ids, worker swaps, compaction,
6
+ * and analysis restatement alone are not material progress.
7
+ */
8
+ /** Kinds that can count as progress when they address the failing invariant. */
9
+ const PROGRESS_KINDS = new Set([
10
+ "code",
11
+ "configuration",
12
+ "evidence",
13
+ "external-state",
14
+ "stage",
15
+ ]);
16
+ /**
17
+ * Whether claimed deltas address the current failure (or advance stage).
18
+ *
19
+ * Source-bound evidence: claims whose sourceRevision does not match the
20
+ * evaluated revision are ignored (cannot treat intermediate evidence as
21
+ * valid for a later revision).
22
+ */
23
+ export function evaluateMaterialProgress(options) {
24
+ const claims = options.claims ?? [];
25
+ const enforceBound = options.enforceSourceBoundEvidence !== false;
26
+ const failure = options.failure ?? null;
27
+ const rev = options.evaluatedRevision;
28
+ if (claims.length === 0) {
29
+ return {
30
+ isMaterial: false,
31
+ classification: "none",
32
+ relevantClaims: [],
33
+ reason: "no material delta claims",
34
+ };
35
+ }
36
+ const relevant = [];
37
+ for (const claim of claims) {
38
+ if (claim.kind === "none" || claim.kind === "unrelated") {
39
+ continue;
40
+ }
41
+ if (!PROGRESS_KINDS.has(claim.kind)) {
42
+ continue;
43
+ }
44
+ // Source-bound evidence: intermediate revision evidence is invalid for later rev.
45
+ if (enforceBound &&
46
+ (claim.kind === "evidence" || claim.kind === "external-state") &&
47
+ claim.sourceRevision !== rev) {
48
+ continue;
49
+ }
50
+ if (claimAddressesFailure(claim, failure)) {
51
+ relevant.push(claim);
52
+ }
53
+ }
54
+ if (relevant.length === 0) {
55
+ const onlyUnrelated = claims.every((c) => c.kind === "unrelated" || c.kind === "none");
56
+ return {
57
+ isMaterial: false,
58
+ classification: onlyUnrelated ? "unrelated" : "none",
59
+ relevantClaims: [],
60
+ reason: onlyUnrelated
61
+ ? "revision churn / unrelated delta does not address failing invariant"
62
+ : "claimed deltas do not address the failing invariant or are source-bound mismatched",
63
+ };
64
+ }
65
+ // Prefer strongest classification for observability.
66
+ const order = [
67
+ "stage",
68
+ "code",
69
+ "configuration",
70
+ "evidence",
71
+ "external-state",
72
+ ];
73
+ const first = relevant[0];
74
+ let classification = first !== undefined ? first.kind : "none";
75
+ for (const k of order) {
76
+ if (relevant.some((c) => c.kind === k)) {
77
+ classification = k;
78
+ break;
79
+ }
80
+ }
81
+ return {
82
+ isMaterial: true,
83
+ classification,
84
+ relevantClaims: relevant,
85
+ reason: `relevant ${classification} delta addressing failure invariant`,
86
+ };
87
+ }
88
+ function claimAddressesFailure(claim, failure) {
89
+ // Stage advancement is always material progress when claimed.
90
+ if (claim.kind === "stage") {
91
+ return true;
92
+ }
93
+ // No prior failure → any progress-kind claim is material (first recovery path).
94
+ if (failure === null) {
95
+ return claim.addresses.length > 0 || PROGRESS_KINDS.has(claim.kind);
96
+ }
97
+ if (claim.addresses.length === 0) {
98
+ // Empty addresses: only treat stage as auto-relevant (handled above).
99
+ // Code/config without addresses is not trusted as material for a known failure.
100
+ return false;
101
+ }
102
+ const targets = new Set([failure.resourceClass ?? "", failure.stage, failure.code ?? "", failure.fingerprint]
103
+ .map((s) => s.trim().toLowerCase())
104
+ .filter((s) => s.length > 0));
105
+ for (const a of claim.addresses) {
106
+ const key = a.trim().toLowerCase();
107
+ if (key.length === 0)
108
+ continue;
109
+ if (targets.has(key))
110
+ return true;
111
+ // Prefix / substring match for component classes (e.g. "auth" matches "auth.permission").
112
+ for (const t of targets) {
113
+ if (t.includes(key) || key.includes(t))
114
+ return true;
115
+ }
116
+ }
117
+ return false;
118
+ }
119
+ /**
120
+ * Whether a new revision alone constitutes material progress.
121
+ * Issue contract: creating a new revision identifier is NOT material progress.
122
+ */
123
+ export function isRevisionChangeMaterial(_previousRevision, _nextRevision) {
124
+ return false;
125
+ }
126
+ //# sourceMappingURL=material-delta.js.map
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Delivery-attempt ledger and pre-dispatch circuit breaker (#3143).
3
+ *
4
+ * Durable attempt state for autonomous delivery / operational-acceptance
5
+ * loops. Enforcement is mechanical — not prompt-only dual-stop defaults (#2442).
6
+ */
7
+ /** Schema version for on-disk unit ledgers. */
8
+ export declare const DELIVERY_ATTEMPT_SCHEMA_VERSION: 1;
9
+ /** Default ledger directory under project root. */
10
+ export declare const DELIVERY_ATTEMPT_DIR = ".deft/delivery-attempts";
11
+ export declare const ATTEMPT_STATUSES: readonly ["queued", "running", "succeeded", "failed", "cancelled", "blocked"];
12
+ export type AttemptStatus = (typeof ATTEMPT_STATUSES)[number];
13
+ export declare const ATTEMPT_TRIGGERS: readonly ["automatic", "manual", "retry", "resume", "override"];
14
+ export type AttemptTrigger = (typeof ATTEMPT_TRIGGERS)[number];
15
+ export declare const RETRYABILITY: readonly ["transient", "deterministic", "unknown"];
16
+ export type Retryability = (typeof RETRYABILITY)[number];
17
+ export declare const MATERIAL_DELTA_KINDS: readonly ["code", "configuration", "evidence", "external-state", "stage", "none", "unrelated"];
18
+ export type MaterialDeltaKind = (typeof MATERIAL_DELTA_KINDS)[number];
19
+ /** Pre-dispatch decision codes from issue #3143 expected behavior. */
20
+ export declare const PRE_DISPATCH_DECISIONS: readonly ["ALLOW_FIRST_ATTEMPT", "ALLOW_TRANSIENT_RETRY", "ALLOW_MATERIAL_PROGRESS", "ALLOW_OVERRIDE", "ALLOW_RESUME", "DENY_DUPLICATE_ACTIVE", "BLOCK_NON_RETRYABLE", "BLOCK_NO_MATERIAL_PROGRESS", "BLOCK_REPEATED_UNKNOWN", "BLOCK_ATTEMPT_BUDGET", "BLOCK_ELAPSED_BUDGET", "BLOCK_TOOL_OR_TOKEN_BUDGET"];
21
+ export type PreDispatchDecision = (typeof PRE_DISPATCH_DECISIONS)[number];
22
+ export declare function isAllowDecision(decision: PreDispatchDecision): boolean;
23
+ export declare function isBlockDecision(decision: PreDispatchDecision): boolean;
24
+ export declare function isDenyDecision(decision: PreDispatchDecision): boolean;
25
+ /** Normalized failure identity (no secrets / raw logs). */
26
+ export interface FailureInfo {
27
+ readonly stage: string;
28
+ readonly code: string | null;
29
+ /** Stable redacted digest of stage + code + normalized message class. */
30
+ readonly fingerprint: string;
31
+ readonly retryability: Retryability;
32
+ /** Optional invariant / resource class implicated by the failure. */
33
+ readonly resourceClass?: string | null;
34
+ }
35
+ /** One material-delta claim attached to an attempt or revision. */
36
+ export interface MaterialDeltaClaim {
37
+ readonly kind: MaterialDeltaKind;
38
+ /**
39
+ * Resource / component classes the delta addresses (matched against
40
+ * failure.resourceClass or fingerprint stages for relevance).
41
+ */
42
+ readonly addresses: readonly string[];
43
+ /** Source revision the delta was observed for (source-bound evidence). */
44
+ readonly sourceRevision: string;
45
+ readonly note?: string | null;
46
+ }
47
+ /** Single attempt row in a unit ledger. */
48
+ export interface DeliveryAttemptRecord {
49
+ readonly attemptId: string;
50
+ readonly sourceRevision: string;
51
+ readonly trigger: AttemptTrigger;
52
+ readonly status: AttemptStatus;
53
+ readonly failure: FailureInfo | null;
54
+ readonly materialDelta: readonly MaterialDeltaClaim[];
55
+ readonly startedAt: string;
56
+ readonly endedAt: string | null;
57
+ readonly elapsedSeconds: number;
58
+ readonly toolCallCount: number;
59
+ /** Host token usage when exposed; null when telemetry unavailable. */
60
+ readonly hostTokenCount: number | null;
61
+ readonly workerId: string | null;
62
+ /** External run id for interrupted-run reconciliation. */
63
+ readonly externalRunId: string | null;
64
+ }
65
+ /** Audited operator override — does not erase history. */
66
+ export interface OperatorOverride {
67
+ readonly overrideId: string;
68
+ readonly actor: string;
69
+ readonly rationale: string;
70
+ readonly recordedAt: string;
71
+ /** Bounded: permits this many additional automatic attempts. */
72
+ readonly allowedAttempts: number;
73
+ readonly expiresAt: string | null;
74
+ readonly remainingAttempts: number;
75
+ }
76
+ /** Resume condition that re-enables automatic dispatch. */
77
+ export interface ResumeCondition {
78
+ readonly kind: "material-delta" | "external-state" | "operator-override" | "monitor-wake";
79
+ readonly description: string;
80
+ readonly satisfied: boolean;
81
+ }
82
+ /**
83
+ * Durable unit ledger keyed by scopeId + targetId + workflowId.
84
+ * Survives worker replacement, session restart, compaction, and new revisions.
85
+ */
86
+ export interface DeliveryUnitLedger {
87
+ readonly schemaVersion: typeof DELIVERY_ATTEMPT_SCHEMA_VERSION;
88
+ readonly scopeId: string;
89
+ readonly targetId: string;
90
+ readonly workflowId: string;
91
+ readonly phaseId: string;
92
+ readonly attempts: readonly DeliveryAttemptRecord[];
93
+ /** Aggregate failed dispatch count in this delivery/acceptance phase. */
94
+ readonly failedAttemptCount: number;
95
+ /** Per-fingerprint identical-failure counts (carry across revisions). */
96
+ readonly sameFailureCounts: Readonly<Record<string, number>>;
97
+ /** Cumulative elapsed seconds across attempts in this phase. */
98
+ readonly totalElapsedSeconds: number;
99
+ readonly totalToolCallCount: number;
100
+ readonly totalHostTokenCount: number | null;
101
+ readonly lastFailure: FailureInfo | null;
102
+ readonly lastMaterialDelta: readonly MaterialDeltaClaim[];
103
+ readonly lastSourceRevision: string | null;
104
+ readonly blockedDecision: PreDispatchDecision | null;
105
+ readonly resumeCondition: ResumeCondition | null;
106
+ readonly override: OperatorOverride | null;
107
+ readonly updatedAt: string;
108
+ }
109
+ /** Conservative autonomous-delivery defaults from issue #3143. */
110
+ export interface DeliveryBudgetPolicy {
111
+ /** Max queued+running attempts per unit (default 1). */
112
+ readonly maxActiveAttempts: number;
113
+ /** Max automatic retries after a transient failure (default 1). */
114
+ readonly maxTransientRetries: number;
115
+ /**
116
+ * Identical unknown failures without material progress that block
117
+ * (default 2 → second identical unknown blocks).
118
+ */
119
+ readonly maxUnknownWithoutProgress: number;
120
+ /** Failed dispatches in one phase before BLOCK_ATTEMPT_BUDGET (default 3). */
121
+ readonly maxFailedAttempts: number;
122
+ /** Hard wall-clock budget in seconds (default 3600). */
123
+ readonly maxElapsedSeconds: number;
124
+ /** Hard tool-call budget (default 500). */
125
+ readonly maxToolCalls: number;
126
+ /**
127
+ * Host token budget when telemetry is available; null = do not enforce
128
+ * token budget (elapsed/tool-call still apply).
129
+ */
130
+ readonly maxHostTokens: number | null;
131
+ /**
132
+ * When true, deterministic failures never get automatic retry without
133
+ * relevant material delta (default true).
134
+ */
135
+ readonly blockDeterministicWithoutDelta: boolean;
136
+ }
137
+ export declare const DEFAULT_DELIVERY_BUDGET_POLICY: DeliveryBudgetPolicy;
138
+ /** Input for a pre-dispatch evaluation. */
139
+ export interface PreDispatchInput {
140
+ readonly scopeId: string;
141
+ readonly targetId: string;
142
+ readonly workflowId: string;
143
+ readonly phaseId?: string;
144
+ readonly sourceRevision: string;
145
+ readonly trigger: AttemptTrigger;
146
+ /** Optional predicted / prior failure class for same-fingerprint checks. */
147
+ readonly anticipatedFailure?: FailureInfo | null;
148
+ /** Material delta claimed for this dispatch relative to last failure. */
149
+ readonly materialDelta?: readonly MaterialDeltaClaim[];
150
+ /** Current cumulative usage when re-entering after a partial run. */
151
+ readonly usage?: {
152
+ readonly elapsedSeconds?: number;
153
+ readonly toolCallCount?: number;
154
+ readonly hostTokenCount?: number | null;
155
+ };
156
+ readonly policy?: Partial<DeliveryBudgetPolicy>;
157
+ /** ISO now override for tests. */
158
+ readonly now?: string;
159
+ }
160
+ /** Structured decision event for observability (#3143 Observability). */
161
+ export interface PreDispatchDecisionEvent {
162
+ readonly decision: "allow" | "deny" | "block" | "escalate";
163
+ readonly reasonCode: PreDispatchDecision;
164
+ readonly retryability: Retryability | null;
165
+ readonly failureFingerprint: string | null;
166
+ readonly attemptCount: number;
167
+ readonly failedAttemptCount: number;
168
+ readonly sameFailureCount: number;
169
+ readonly materialDeltaClassification: MaterialDeltaKind | "none";
170
+ readonly resumeCondition: ResumeCondition | null;
171
+ readonly overrideId: string | null;
172
+ readonly scopeId: string;
173
+ readonly targetId: string;
174
+ readonly workflowId: string;
175
+ readonly sourceRevision: string;
176
+ }
177
+ export interface PreDispatchResult {
178
+ readonly decision: PreDispatchDecision;
179
+ readonly allowed: boolean;
180
+ readonly reason: string;
181
+ readonly event: PreDispatchDecisionEvent;
182
+ readonly handoff: TerminalHandoff | null;
183
+ /** Suggested next attempt id when allowed (caller may override). */
184
+ readonly nextAttemptId: string | null;
185
+ }
186
+ /** Terminal handoff contract when the circuit breaker blocks. */
187
+ export interface TerminalHandoff {
188
+ readonly schemaVersion: 1;
189
+ readonly scopeId: string;
190
+ readonly targetId: string;
191
+ readonly workflowId: string;
192
+ readonly lastSourceRevision: string | null;
193
+ readonly failure: FailureInfo | null;
194
+ readonly totalAttempts: number;
195
+ readonly failedAttemptCount: number;
196
+ readonly sameFailureCount: number;
197
+ readonly elapsedSeconds: number;
198
+ readonly toolCallCount: number;
199
+ readonly hostTokenCount: number | null;
200
+ readonly lastMaterialDelta: readonly MaterialDeltaClaim[];
201
+ readonly denyReason: PreDispatchDecision;
202
+ readonly nextSafeAction: string;
203
+ readonly resumeCondition: ResumeCondition;
204
+ readonly overridePermitted: boolean;
205
+ readonly recordedAt: string;
206
+ }
207
+ export declare function deliveryUnitKey(scopeId: string, targetId: string, workflowId: string): string;
208
+ export declare function utcIso(now?: Date | string): string;
209
+ export declare function mergePolicy(partial?: Partial<DeliveryBudgetPolicy>): DeliveryBudgetPolicy;
210
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Delivery-attempt ledger and pre-dispatch circuit breaker (#3143).
3
+ *
4
+ * Durable attempt state for autonomous delivery / operational-acceptance
5
+ * loops. Enforcement is mechanical — not prompt-only dual-stop defaults (#2442).
6
+ */
7
+ /** Schema version for on-disk unit ledgers. */
8
+ export const DELIVERY_ATTEMPT_SCHEMA_VERSION = 1;
9
+ /** Default ledger directory under project root. */
10
+ export const DELIVERY_ATTEMPT_DIR = ".deft/delivery-attempts";
11
+ export const ATTEMPT_STATUSES = [
12
+ "queued",
13
+ "running",
14
+ "succeeded",
15
+ "failed",
16
+ "cancelled",
17
+ "blocked",
18
+ ];
19
+ export const ATTEMPT_TRIGGERS = ["automatic", "manual", "retry", "resume", "override"];
20
+ export const RETRYABILITY = ["transient", "deterministic", "unknown"];
21
+ export const MATERIAL_DELTA_KINDS = [
22
+ "code",
23
+ "configuration",
24
+ "evidence",
25
+ "external-state",
26
+ "stage",
27
+ "none",
28
+ "unrelated",
29
+ ];
30
+ /** Pre-dispatch decision codes from issue #3143 expected behavior. */
31
+ export const PRE_DISPATCH_DECISIONS = [
32
+ "ALLOW_FIRST_ATTEMPT",
33
+ "ALLOW_TRANSIENT_RETRY",
34
+ "ALLOW_MATERIAL_PROGRESS",
35
+ "ALLOW_OVERRIDE",
36
+ "ALLOW_RESUME",
37
+ "DENY_DUPLICATE_ACTIVE",
38
+ "BLOCK_NON_RETRYABLE",
39
+ "BLOCK_NO_MATERIAL_PROGRESS",
40
+ "BLOCK_REPEATED_UNKNOWN",
41
+ "BLOCK_ATTEMPT_BUDGET",
42
+ "BLOCK_ELAPSED_BUDGET",
43
+ "BLOCK_TOOL_OR_TOKEN_BUDGET",
44
+ ];
45
+ export function isAllowDecision(decision) {
46
+ return decision.startsWith("ALLOW_");
47
+ }
48
+ export function isBlockDecision(decision) {
49
+ return decision.startsWith("BLOCK_");
50
+ }
51
+ export function isDenyDecision(decision) {
52
+ return decision.startsWith("DENY_");
53
+ }
54
+ export const DEFAULT_DELIVERY_BUDGET_POLICY = {
55
+ maxActiveAttempts: 1,
56
+ maxTransientRetries: 1,
57
+ maxUnknownWithoutProgress: 2,
58
+ maxFailedAttempts: 3,
59
+ maxElapsedSeconds: 3600,
60
+ maxToolCalls: 500,
61
+ maxHostTokens: null,
62
+ blockDeterministicWithoutDelta: true,
63
+ };
64
+ export function deliveryUnitKey(scopeId, targetId, workflowId) {
65
+ return `${scopeId}\u001f${targetId}\u001f${workflowId}`;
66
+ }
67
+ export function utcIso(now) {
68
+ if (typeof now === "string" && now.length > 0) {
69
+ return now.endsWith("Z") ? now.replace(/\.\d{3}Z$/, "Z") : now;
70
+ }
71
+ const dt = now instanceof Date ? now : new Date();
72
+ return dt.toISOString().replace(/\.\d{3}Z$/, "Z");
73
+ }
74
+ export function mergePolicy(partial) {
75
+ return { ...DEFAULT_DELIVERY_BUDGET_POLICY, ...partial };
76
+ }
77
+ //# sourceMappingURL=types.js.map
@@ -9,6 +9,7 @@ export * from "./manifest.js";
9
9
  export * from "./npm-registry.js";
10
10
  export * from "./openclaw-l2-adapter.js";
11
11
  export * from "./openclaw-skills.js";
12
+ export * from "./openclaw-soft-rebind.js";
12
13
  export * from "./paths.js";
13
14
  export * from "./payload-staleness.js";
14
15
  export * from "./release-availability.js";
@@ -9,6 +9,7 @@ export * from "./manifest.js";
9
9
  export * from "./npm-registry.js";
10
10
  export * from "./openclaw-l2-adapter.js";
11
11
  export * from "./openclaw-skills.js";
12
+ export * from "./openclaw-soft-rebind.js";
12
13
  export * from "./paths.js";
13
14
  export * from "./payload-staleness.js";
14
15
  export * from "./release-availability.js";
@@ -25,6 +25,7 @@ import { parseInstallRootFromAgentsMd } from "./manifest.js";
25
25
  import { runNpmRegistryMirrorCheck } from "./npm-registry.js";
26
26
  import { runOpenClawL2AdapterCheck } from "./openclaw-l2-adapter.js";
27
27
  import { runOpenClawSkillPinsCheck } from "./openclaw-skills.js";
28
+ import { runOpenClawSoftRebindCheck } from "./openclaw-soft-rebind.js";
28
29
  import { createPlainSink } from "./output.js";
29
30
  import { readTextSafe, resolveFrameworkRootForProject, resolvePath, resolveVersion, runningInsideDeftRepo, } from "./paths.js";
30
31
  import { runPayloadStalenessCheck } from "./payload-staleness.js";
@@ -416,6 +417,17 @@ export function cmdDoctor(args, seams = {}) {
416
417
  if (!jsonMode) {
417
418
  sink.blank();
418
419
  }
420
+ sink.info("Checking OpenClaw soft AGENTS re-bind skill...");
421
+ runOpenClawSoftRebindCheck(sink, addFinding, {
422
+ projectRoot,
423
+ fixMode,
424
+ jsonMode,
425
+ allAgents: flags.openclawAllAgents,
426
+ seams,
427
+ });
428
+ if (!jsonMode) {
429
+ sink.blank();
430
+ }
419
431
  sink.info("Checking OpenClaw L2 product-command skills...");
420
432
  runOpenClawL2AdapterCheck(sink, addFinding, {
421
433
  projectRoot,
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Doctor check + --fix wire for OpenClaw soft AGENTS re-bind skill (#3171).
3
+ *
4
+ * Complements always-pins (#3001/#3008) and L2 product commands (#3064). This
5
+ * skill is the required durable soft post-amnesia surface for OpenClaw — not
6
+ * claimed via file-host PreCompact hooks alone.
7
+ */
8
+ import { assessOpenClawSoftRebindSkill, depositOpenClawSoftRebindSkill, type OpenClawSoftRebindDepositResult } from "../session/openclaw-soft-rebind-deposit.js";
9
+ import type { OutputSink } from "./output.js";
10
+ import type { DoctorSeams, Finding } from "./types.js";
11
+ /** Stable doctor check id for JSON findings. */
12
+ export declare const OPENCLAW_SOFT_REBIND_CHECK = "openclaw-soft-agents-rebind";
13
+ export interface RunOpenClawSoftRebindOptions {
14
+ readonly projectRoot: string;
15
+ readonly fixMode: boolean;
16
+ readonly jsonMode: boolean;
17
+ readonly allAgents: boolean;
18
+ readonly seams?: DoctorSeams;
19
+ }
20
+ /**
21
+ * Doctor check: OpenClaw soft AGENTS re-bind skill present and current.
22
+ * No-ops when OpenClaw is not detected. Fix mode deposits managed skill.
23
+ */
24
+ export declare function runOpenClawSoftRebindCheck(sink: OutputSink, addFinding: (finding: Finding) => void, options: RunOpenClawSoftRebindOptions): OpenClawSoftRebindDepositResult | null;
25
+ export { assessOpenClawSoftRebindSkill, depositOpenClawSoftRebindSkill };
26
+ //# sourceMappingURL=openclaw-soft-rebind.d.ts.map