@dsh-enhanced/assistant-work-items 0.0.0-stage → 0.1.67

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 (152) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +685 -2
  3. package/cordis.patch.yml +11 -0
  4. package/lib/acceptance-binding.d.ts +86 -0
  5. package/lib/acceptance-binding.d.ts.map +1 -0
  6. package/lib/acceptance-binding.js +250 -0
  7. package/lib/acceptance-binding.js.map +1 -0
  8. package/lib/admission.d.ts +95 -0
  9. package/lib/admission.d.ts.map +1 -0
  10. package/lib/admission.js +642 -0
  11. package/lib/admission.js.map +1 -0
  12. package/lib/authority.d.ts +99 -0
  13. package/lib/authority.d.ts.map +1 -0
  14. package/lib/authority.js +233 -0
  15. package/lib/authority.js.map +1 -0
  16. package/lib/config.d.ts +365 -0
  17. package/lib/config.d.ts.map +1 -0
  18. package/lib/config.js +672 -0
  19. package/lib/config.js.map +1 -0
  20. package/lib/continuation-contract.d.ts +126 -0
  21. package/lib/continuation-contract.d.ts.map +1 -0
  22. package/lib/continuation-contract.js +109 -0
  23. package/lib/continuation-contract.js.map +1 -0
  24. package/lib/continuation-record.d.ts +32 -0
  25. package/lib/continuation-record.d.ts.map +1 -0
  26. package/lib/continuation-record.js +57 -0
  27. package/lib/continuation-record.js.map +1 -0
  28. package/lib/continuation.d.ts +89 -0
  29. package/lib/continuation.d.ts.map +1 -0
  30. package/lib/continuation.js +607 -0
  31. package/lib/continuation.js.map +1 -0
  32. package/lib/diagnosis-contract.d.ts +95 -0
  33. package/lib/diagnosis-contract.d.ts.map +1 -0
  34. package/lib/diagnosis-contract.js +167 -0
  35. package/lib/diagnosis-contract.js.map +1 -0
  36. package/lib/diagnosis.d.ts +70 -0
  37. package/lib/diagnosis.d.ts.map +1 -0
  38. package/lib/diagnosis.js +466 -0
  39. package/lib/diagnosis.js.map +1 -0
  40. package/lib/dispatch.d.ts +100 -0
  41. package/lib/dispatch.d.ts.map +1 -0
  42. package/lib/dispatch.js +317 -0
  43. package/lib/dispatch.js.map +1 -0
  44. package/lib/engineering-context.d.ts +86 -0
  45. package/lib/engineering-context.d.ts.map +1 -0
  46. package/lib/engineering-context.js +263 -0
  47. package/lib/engineering-context.js.map +1 -0
  48. package/lib/evaluation.d.ts +125 -0
  49. package/lib/evaluation.d.ts.map +1 -0
  50. package/lib/evaluation.js +295 -0
  51. package/lib/evaluation.js.map +1 -0
  52. package/lib/event-follow.d.ts +93 -0
  53. package/lib/event-follow.d.ts.map +1 -0
  54. package/lib/event-follow.js +150 -0
  55. package/lib/event-follow.js.map +1 -0
  56. package/lib/feedback-targets.d.ts +91 -0
  57. package/lib/feedback-targets.d.ts.map +1 -0
  58. package/lib/feedback-targets.js +362 -0
  59. package/lib/feedback-targets.js.map +1 -0
  60. package/lib/index.d.ts +27 -0
  61. package/lib/index.d.ts.map +1 -0
  62. package/lib/index.js +25 -0
  63. package/lib/index.js.map +1 -0
  64. package/lib/intake-admission.d.ts +49 -0
  65. package/lib/intake-admission.d.ts.map +1 -0
  66. package/lib/intake-admission.js +100 -0
  67. package/lib/intake-admission.js.map +1 -0
  68. package/lib/intake-evaluation-runtime.d.ts +74 -0
  69. package/lib/intake-evaluation-runtime.d.ts.map +1 -0
  70. package/lib/intake-evaluation-runtime.js +343 -0
  71. package/lib/intake-evaluation-runtime.js.map +1 -0
  72. package/lib/intake-evaluation.d.ts +180 -0
  73. package/lib/intake-evaluation.d.ts.map +1 -0
  74. package/lib/intake-evaluation.js +440 -0
  75. package/lib/intake-evaluation.js.map +1 -0
  76. package/lib/intake.d.ts +118 -0
  77. package/lib/intake.d.ts.map +1 -0
  78. package/lib/intake.js +137 -0
  79. package/lib/intake.js.map +1 -0
  80. package/lib/ledger.d.ts +86 -0
  81. package/lib/ledger.d.ts.map +1 -0
  82. package/lib/ledger.js +145 -0
  83. package/lib/ledger.js.map +1 -0
  84. package/lib/mandate.d.ts +45 -0
  85. package/lib/mandate.d.ts.map +1 -0
  86. package/lib/mandate.js +168 -0
  87. package/lib/mandate.js.map +1 -0
  88. package/lib/outcome.d.ts +137 -0
  89. package/lib/outcome.d.ts.map +1 -0
  90. package/lib/outcome.js +303 -0
  91. package/lib/outcome.js.map +1 -0
  92. package/lib/owner-access.d.ts +35 -0
  93. package/lib/owner-access.d.ts.map +1 -0
  94. package/lib/owner-access.js +152 -0
  95. package/lib/owner-access.js.map +1 -0
  96. package/lib/owner-continuation.d.ts +27 -0
  97. package/lib/owner-continuation.d.ts.map +1 -0
  98. package/lib/owner-continuation.js +131 -0
  99. package/lib/owner-continuation.js.map +1 -0
  100. package/lib/owner-recall.d.ts +85 -0
  101. package/lib/owner-recall.d.ts.map +1 -0
  102. package/lib/owner-recall.js +134 -0
  103. package/lib/owner-recall.js.map +1 -0
  104. package/lib/owner-replies.d.ts +44 -0
  105. package/lib/owner-replies.d.ts.map +1 -0
  106. package/lib/owner-replies.js +268 -0
  107. package/lib/owner-replies.js.map +1 -0
  108. package/lib/peers.d.ts +624 -0
  109. package/lib/peers.d.ts.map +1 -0
  110. package/lib/peers.js +10 -0
  111. package/lib/peers.js.map +1 -0
  112. package/lib/policy-notice.d.ts +31 -0
  113. package/lib/policy-notice.d.ts.map +1 -0
  114. package/lib/policy-notice.js +137 -0
  115. package/lib/policy-notice.js.map +1 -0
  116. package/lib/reply-contract.d.ts +67 -0
  117. package/lib/reply-contract.d.ts.map +1 -0
  118. package/lib/reply-contract.js +58 -0
  119. package/lib/reply-contract.js.map +1 -0
  120. package/lib/service.d.ts +632 -0
  121. package/lib/service.d.ts.map +1 -0
  122. package/lib/service.js +2447 -0
  123. package/lib/service.js.map +1 -0
  124. package/lib/settlement.d.ts +74 -0
  125. package/lib/settlement.d.ts.map +1 -0
  126. package/lib/settlement.js +233 -0
  127. package/lib/settlement.js.map +1 -0
  128. package/lib/signals.d.ts +176 -0
  129. package/lib/signals.d.ts.map +1 -0
  130. package/lib/signals.js +497 -0
  131. package/lib/signals.js.map +1 -0
  132. package/lib/store.d.ts +791 -0
  133. package/lib/store.d.ts.map +1 -0
  134. package/lib/store.js +3266 -0
  135. package/lib/store.js.map +1 -0
  136. package/lib/tools.d.ts +7 -0
  137. package/lib/tools.d.ts.map +1 -0
  138. package/lib/tools.js +443 -0
  139. package/lib/tools.js.map +1 -0
  140. package/lib/types.d.ts +831 -0
  141. package/lib/types.d.ts.map +1 -0
  142. package/lib/types.js +29 -0
  143. package/lib/types.js.map +1 -0
  144. package/lib/version.d.ts +2 -0
  145. package/lib/version.d.ts.map +1 -0
  146. package/lib/version.js +2 -0
  147. package/lib/version.js.map +1 -0
  148. package/lib/workspace.d.ts +43 -0
  149. package/lib/workspace.d.ts.map +1 -0
  150. package/lib/workspace.js +137 -0
  151. package/lib/workspace.js.map +1 -0
  152. package/package.json +101 -3
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Deterministic intake ledger (WP20 slice 1).
3
+ *
4
+ * One durable row per `(source, sourceEventId)` records what the Host decided
5
+ * about an inbound item, from normalized metadata only. Nothing here reads a
6
+ * message body, calls a model, admits a work item or dispatches anything: the
7
+ * row is audit evidence that a later, evaluated slice can build on.
8
+ */
9
+ export type WorkItemIntakeKind = 'message' | 'event';
10
+ export type WorkItemIntakeDecision = 'stored' | 'duplicate' | 'filtered';
11
+ export type WorkItemIntakeStrength = 'explicit' | 'inferred' | 'ignore';
12
+ export type WorkItemIntakeStrengthReason = 'allowlisted-addressed' | 'thread-follow-up' | 'allowlisted-unaddressed' | 'bot-capped' | 'not-allowlisted' | 'follow-up-not-allowlisted';
13
+ export type WorkItemIntakeReason = 'strength-explicit' | 'strength-inferred' | 'strength-ignore' | 'duplicate-content' | 'unaddressed-group-disabled' | 'unsubscribed-event-disabled';
14
+ /**
15
+ * Host-normalized metadata for one inbound item.
16
+ *
17
+ * The field list is closed: any other key (for example `text` or `body`) is
18
+ * rejected, so a caller cannot hand message content to the ledger by mistake.
19
+ * `contentDigest` is an optional SHA-256 hex digest the Host computed over the
20
+ * content it already holds; it is the only content-derived value accepted.
21
+ */
22
+ export interface WorkItemIntakeInput {
23
+ /** Host-registered inbound source, e.g. `lark-channel`. */
24
+ readonly source: string;
25
+ /** Stable source-local event id; the replay key together with `source`. */
26
+ readonly sourceEventId: string;
27
+ readonly kind: WorkItemIntakeKind;
28
+ readonly senderAllowlisted: boolean;
29
+ /** The item addresses the assistant (mention, direct message, command). */
30
+ readonly addressed: boolean;
31
+ /**
32
+ * The item follows up on a thread the ledger already tracks as work. Only an
33
+ * allowlisted sender's follow-up is explicit; any other follow-up is ignored.
34
+ */
35
+ readonly threadFollowUp: boolean;
36
+ readonly senderIsBot: boolean;
37
+ /** Messages only: posted in a group conversation. Defaults to `false`. */
38
+ readonly groupMessage?: boolean;
39
+ /** Events only: the owner subscribed to this event type. Defaults to `true`. */
40
+ readonly subscribed?: boolean;
41
+ readonly contentDigest?: string;
42
+ readonly occurredAt: number;
43
+ }
44
+ /** Per-source owner opt-ins; every flag defaults to off. */
45
+ export interface WorkItemIntakeSourcePolicy {
46
+ readonly unaddressedGroupMessages: boolean;
47
+ readonly unsubscribedEvents: boolean;
48
+ }
49
+ export interface WorkItemIntakeSignals {
50
+ readonly senderAllowlisted: boolean;
51
+ readonly addressed: boolean;
52
+ readonly threadFollowUp: boolean;
53
+ readonly senderIsBot: boolean;
54
+ readonly groupMessage: boolean;
55
+ readonly subscribed: boolean;
56
+ }
57
+ /** Normalized input plus the Host-computed grade and pre-dedup decision. */
58
+ export interface WorkItemIntakeCandidate {
59
+ readonly source: string;
60
+ readonly sourceEventId: string;
61
+ readonly kind: WorkItemIntakeKind;
62
+ readonly signals: WorkItemIntakeSignals;
63
+ readonly strength: WorkItemIntakeStrength;
64
+ readonly strengthReason: WorkItemIntakeStrengthReason;
65
+ /** `stored` may still become `duplicate` inside the store transaction. */
66
+ readonly decision: 'stored' | 'filtered';
67
+ readonly reason: WorkItemIntakeReason;
68
+ readonly contentDigest: string | null;
69
+ readonly metadataDigest: string;
70
+ readonly occurredAt: number;
71
+ }
72
+ export interface WorkItemIntakeRecord {
73
+ readonly source: string;
74
+ readonly sourceEventId: string;
75
+ readonly kind: WorkItemIntakeKind;
76
+ readonly decision: WorkItemIntakeDecision;
77
+ readonly reason: WorkItemIntakeReason;
78
+ readonly strength: WorkItemIntakeStrength;
79
+ readonly strengthReason: WorkItemIntakeStrengthReason;
80
+ readonly signals: WorkItemIntakeSignals;
81
+ readonly contentDigest: string | null;
82
+ readonly metadataDigest: string;
83
+ readonly occurredAt: number;
84
+ readonly recordedAt: number;
85
+ }
86
+ export interface WorkItemIntakeResult {
87
+ readonly record: WorkItemIntakeRecord;
88
+ /** True when the `(source, sourceEventId)` row already existed. */
89
+ readonly replayed: boolean;
90
+ /** Replay only: the replayed metadata digest differs from the original. */
91
+ readonly metadataChanged?: true;
92
+ }
93
+ export declare const INTAKE_SOURCE_ID: RegExp;
94
+ /**
95
+ * Grade one item's strength from normalized metadata.
96
+ *
97
+ * The allowlist scopes both explicit paths: an allowlisted sender that
98
+ * addresses the assistant, or follows up on a tracked work thread, is
99
+ * `explicit`; allowlisted but otherwise unaddressed is `inferred`; anything
100
+ * else, including a non-allowlisted follow-up, is `ignore`. A bot sender is
101
+ * never stronger than `inferred`.
102
+ */
103
+ export declare function gradeIntakeStrength(signals: Pick<WorkItemIntakeSignals, 'senderAllowlisted' | 'addressed' | 'threadFollowUp' | 'senderIsBot'>): {
104
+ readonly strength: WorkItemIntakeStrength;
105
+ readonly reason: WorkItemIntakeStrengthReason;
106
+ };
107
+ /**
108
+ * Validate one input and compute its grade and pre-dedup decision.
109
+ *
110
+ * An `ignore` grade is `filtered`. Source opt-in filters then apply: a group
111
+ * message that is neither addressed nor an allowlisted follow-up, or an
112
+ * unsubscribed event, is `filtered` unless the owner enabled that source.
113
+ * Everything else is `stored` (metadata only).
114
+ */
115
+ export declare function classifyIntake(raw: WorkItemIntakeInput, policy?: WorkItemIntakeSourcePolicy): WorkItemIntakeCandidate;
116
+ /** Resolve the owner opt-ins for one source; unknown sources stay fully off. */
117
+ export declare function intakeSourcePolicy(sources: Readonly<Record<string, WorkItemIntakeSourcePolicy>> | undefined, source: string): WorkItemIntakeSourcePolicy;
118
+ //# sourceMappingURL=intake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intake.d.ts","sourceRoot":"","sources":["../src/intake.ts"],"names":[],"mappings":"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"}
package/lib/intake.js ADDED
@@ -0,0 +1,137 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { WorkItemError } from "./types.js";
3
+ const INPUT_KEYS = ['source', 'sourceEventId', 'kind', 'senderAllowlisted', 'addressed', 'threadFollowUp', 'senderIsBot',
4
+ 'groupMessage', 'subscribed', 'contentDigest', 'occurredAt'];
5
+ export const INTAKE_SOURCE_ID = /^[a-z][a-z0-9-]{0,63}$/u;
6
+ const SHA256_HEX = /^[0-9a-f]{64}$/u;
7
+ const MAX_EVENT_ID_BYTES = 256;
8
+ // C0/C1 controls and line/paragraph separators never belong in an id.
9
+ function hasControl(value) {
10
+ for (const char of value) {
11
+ const code = char.codePointAt(0);
12
+ if (code < 0x20 || (code >= 0x7f && code <= 0x9f) || code === 0x2028 || code === 0x2029)
13
+ return true;
14
+ }
15
+ return false;
16
+ }
17
+ const DISABLED_POLICY = Object.freeze({ unaddressedGroupMessages: false, unsubscribedEvents: false });
18
+ function fail(code, message) {
19
+ throw new WorkItemError(code, message);
20
+ }
21
+ function flag(value, field, fallback) {
22
+ if (value === undefined && fallback !== undefined)
23
+ return fallback;
24
+ if (typeof value !== 'boolean')
25
+ fail('invalid-input', `intake ${field} must be a boolean`);
26
+ return value;
27
+ }
28
+ /**
29
+ * Grade one item's strength from normalized metadata.
30
+ *
31
+ * The allowlist scopes both explicit paths: an allowlisted sender that
32
+ * addresses the assistant, or follows up on a tracked work thread, is
33
+ * `explicit`; allowlisted but otherwise unaddressed is `inferred`; anything
34
+ * else, including a non-allowlisted follow-up, is `ignore`. A bot sender is
35
+ * never stronger than `inferred`.
36
+ */
37
+ export function gradeIntakeStrength(signals) {
38
+ let strength;
39
+ let reason;
40
+ if (signals.senderAllowlisted && signals.addressed)
41
+ [strength, reason] = ['explicit', 'allowlisted-addressed'];
42
+ else if (signals.senderAllowlisted && signals.threadFollowUp)
43
+ [strength, reason] = ['explicit', 'thread-follow-up'];
44
+ else if (signals.senderAllowlisted)
45
+ [strength, reason] = ['inferred', 'allowlisted-unaddressed'];
46
+ else if (signals.threadFollowUp)
47
+ [strength, reason] = ['ignore', 'follow-up-not-allowlisted'];
48
+ else
49
+ [strength, reason] = ['ignore', 'not-allowlisted'];
50
+ if (signals.senderIsBot && strength === 'explicit')
51
+ [strength, reason] = ['inferred', 'bot-capped'];
52
+ return Object.freeze({ strength, reason });
53
+ }
54
+ /** Stable digest over the normalized metadata only; never over content. */
55
+ function metadataDigest(fields) {
56
+ const canonical = JSON.stringify(Object.keys(fields).sort().map(key => [key, fields[key]]));
57
+ return createHash('sha256').update(canonical, 'utf8').digest('hex');
58
+ }
59
+ /**
60
+ * Validate one input and compute its grade and pre-dedup decision.
61
+ *
62
+ * An `ignore` grade is `filtered`. Source opt-in filters then apply: a group
63
+ * message that is neither addressed nor an allowlisted follow-up, or an
64
+ * unsubscribed event, is `filtered` unless the owner enabled that source.
65
+ * Everything else is `stored` (metadata only).
66
+ */
67
+ export function classifyIntake(raw, policy = DISABLED_POLICY) {
68
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw))
69
+ fail('invalid-input', 'intake input must be an object');
70
+ const value = raw;
71
+ for (const key of Object.keys(value)) {
72
+ if (!INPUT_KEYS.includes(key))
73
+ fail('invalid-input', `intake input contains unknown field ${key}`);
74
+ }
75
+ const source = value['source'];
76
+ if (typeof source !== 'string' || !INTAKE_SOURCE_ID.test(source))
77
+ fail('invalid-input', 'intake source has an invalid shape');
78
+ const eventId = value['sourceEventId'];
79
+ if (typeof eventId !== 'string' || eventId.length === 0 || eventId !== eventId.trim() || hasControl(eventId)
80
+ || Buffer.byteLength(eventId, 'utf8') > MAX_EVENT_ID_BYTES) {
81
+ fail('invalid-input', `intake sourceEventId must be 1-${MAX_EVENT_ID_BYTES} bytes without control characters`);
82
+ }
83
+ const kind = value['kind'];
84
+ if (kind !== 'message' && kind !== 'event')
85
+ fail('invalid-input', "intake kind must be 'message' or 'event'");
86
+ if (kind === 'message' && value['subscribed'] !== undefined)
87
+ fail('invalid-input', 'intake subscribed applies to events only');
88
+ if (kind === 'event' && value['groupMessage'] !== undefined)
89
+ fail('invalid-input', 'intake groupMessage applies to messages only');
90
+ const signals = Object.freeze({
91
+ senderAllowlisted: flag(value['senderAllowlisted'], 'senderAllowlisted'),
92
+ addressed: flag(value['addressed'], 'addressed'),
93
+ threadFollowUp: flag(value['threadFollowUp'], 'threadFollowUp'),
94
+ senderIsBot: flag(value['senderIsBot'], 'senderIsBot'),
95
+ groupMessage: flag(value['groupMessage'], 'groupMessage', false),
96
+ subscribed: flag(value['subscribed'], 'subscribed', true),
97
+ });
98
+ const rawDigest = value['contentDigest'];
99
+ if (rawDigest !== undefined && (typeof rawDigest !== 'string' || !SHA256_HEX.test(rawDigest))) {
100
+ fail('invalid-input', 'intake contentDigest must be a lowercase SHA-256 hex digest');
101
+ }
102
+ const contentDigest = rawDigest === undefined ? null : rawDigest;
103
+ const occurredAt = value['occurredAt'];
104
+ if (typeof occurredAt !== 'number' || !Number.isSafeInteger(occurredAt) || occurredAt < 0)
105
+ fail('invalid-input', 'intake occurredAt must be a non-negative integer');
106
+ const grade = gradeIntakeStrength(signals);
107
+ let decision = grade.strength === 'ignore' ? 'filtered' : 'stored';
108
+ let reason = grade.strength === 'explicit' ? 'strength-explicit' : grade.strength === 'inferred' ? 'strength-inferred' : 'strength-ignore';
109
+ // A follow-up counts as addressed only for an allowlisted sender.
110
+ const directed = signals.addressed || (signals.threadFollowUp && signals.senderAllowlisted);
111
+ if (kind === 'message' && signals.groupMessage && !directed && !policy.unaddressedGroupMessages) {
112
+ [decision, reason] = ['filtered', 'unaddressed-group-disabled'];
113
+ }
114
+ else if (kind === 'event' && !signals.subscribed && !policy.unsubscribedEvents) {
115
+ [decision, reason] = ['filtered', 'unsubscribed-event-disabled'];
116
+ }
117
+ return Object.freeze({
118
+ source,
119
+ sourceEventId: eventId,
120
+ kind,
121
+ signals,
122
+ strength: grade.strength,
123
+ strengthReason: grade.reason,
124
+ decision,
125
+ reason,
126
+ contentDigest,
127
+ metadataDigest: metadataDigest({ source, sourceEventId: eventId, kind, ...signals, contentDigest, occurredAt }),
128
+ occurredAt,
129
+ });
130
+ }
131
+ /** Resolve the owner opt-ins for one source; unknown sources stay fully off. */
132
+ export function intakeSourcePolicy(sources, source) {
133
+ if (sources === undefined || !Object.hasOwn(sources, source))
134
+ return DISABLED_POLICY;
135
+ return sources[source];
136
+ }
137
+ //# sourceMappingURL=intake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intake.js","sourceRoot":"","sources":["../src/intake.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import type { NormalizedLimits } from './config.ts';
2
+ import type { ClaimResult, ReportResult, ReclaimResult, WorkItemStore } from './store.ts';
3
+ import type { WorkItemClaimRecord, WorkItemDispatchRecord, WorkItemDeliveryState, WorkItemEventRecord, WorkItemRecord, WorkItemReportRecord, WorkItemReportStatus, WorkItemState } from './types.ts';
4
+ import type { WorkItemWorkspace } from './workspace.ts';
5
+ /** A point-in-time view of one item and everything attached to it. */
6
+ export interface WorkItemDetail {
7
+ readonly item: WorkItemRecord;
8
+ readonly events: readonly WorkItemEventRecord[];
9
+ readonly claim: WorkItemClaimRecord | undefined;
10
+ readonly reports: readonly WorkItemReportRecord[];
11
+ readonly dispatch: WorkItemDispatchRecord | undefined;
12
+ }
13
+ export interface ClaimRequest {
14
+ readonly itemId: string;
15
+ readonly runId: string;
16
+ readonly occurrenceId: string;
17
+ }
18
+ export interface ReportRequest {
19
+ readonly itemId: string;
20
+ readonly runId: string;
21
+ readonly status: WorkItemReportStatus;
22
+ readonly summary: string;
23
+ readonly artifactPaths: readonly string[];
24
+ readonly idempotencyKey: string;
25
+ }
26
+ /** The exact summary representation persisted by report and checked on replay. */
27
+ export declare function normalizeWorkItemReportSummary(value: string, maxBytes: number): Readonly<{
28
+ summary: string;
29
+ truncated: boolean;
30
+ }>;
31
+ /**
32
+ * Lifecycle orchestration on top of the durable store.
33
+ *
34
+ * The ledger owns sequencing and limits (lease, attempt budget, report size,
35
+ * artifact containment) while the store owns atomicity. Nothing here schedules
36
+ * work: every transition is triggered by an admission, a tool call or startup
37
+ * recovery, so the plugin adds no loop or timer to the host.
38
+ */
39
+ export declare class WorkItemLedger {
40
+ #private;
41
+ constructor(options: {
42
+ store: WorkItemStore;
43
+ workspace: WorkItemWorkspace;
44
+ limits: NormalizedLimits;
45
+ diagnosis?: boolean;
46
+ now?: () => number;
47
+ });
48
+ get store(): WorkItemStore;
49
+ get workspace(): WorkItemWorkspace;
50
+ /**
51
+ * Claim one item for one occurrence run.
52
+ *
53
+ * Creates the private scratch directory before the CAS so a worker never sees
54
+ * a claimed item without a place to write. The store decides the conflict.
55
+ */
56
+ claim(request: ClaimRequest): ClaimResult;
57
+ /**
58
+ * Park an item whose admission mandate failed revalidation.
59
+ *
60
+ * The item stays open and resumable: no claim is started, no dispatch is
61
+ * retired, and the same item is claimed or woken unchanged once policy allows
62
+ * the identical mandate again.
63
+ */
64
+ parkAuthority(item: WorkItemRecord, reason: 'authority-revoked' | 'authority-unavailable', detail?: Readonly<Record<string, unknown>>): WorkItemRecord;
65
+ /** Record a successful revalidation, lifting only this gate's own wait. */
66
+ restoreAuthority(item: WorkItemRecord): WorkItemRecord;
67
+ /** Mint a fresh wake after a claim-time revalidation denial left no run. */
68
+ rearmAuthority(item: WorkItemRecord): void;
69
+ /**
70
+ * Append a report revision under the active claim.
71
+ *
72
+ * The summary is truncated to `maxReportBytes` rather than rejected, because
73
+ * a long report is still evidence; artifact paths are validated strictly.
74
+ * Idempotent by `idempotencyKey`, so a retried tool call is safe.
75
+ */
76
+ report(request: ReportRequest): ReportResult;
77
+ /** Record the outcome of one delivery attempt for a report revision. */
78
+ recordDelivery(itemId: string, revision: number, state: WorkItemDeliveryState, deliveryId: string | null): void;
79
+ /** Lazy lease recovery, invoked on startup and every admission/claim. */
80
+ recover(): ReclaimResult;
81
+ detail(itemId: string): WorkItemDetail | undefined;
82
+ list(states?: readonly WorkItemState[], limit?: number): readonly WorkItemRecord[];
83
+ claimedRun(itemId: string, runId: string): WorkItemClaimRecord | undefined;
84
+ now(): number;
85
+ }
86
+ //# sourceMappingURL=ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}
package/lib/ledger.js ADDED
@@ -0,0 +1,145 @@
1
+ import { truncateUtf8 } from "./config.js";
2
+ import { WorkItemError } from "./types.js";
3
+ function fail(code, message, detail) {
4
+ throw new WorkItemError(code, message, detail);
5
+ }
6
+ /** The exact summary representation persisted by report and checked on replay. */
7
+ export function normalizeWorkItemReportSummary(value, maxBytes) {
8
+ const summary = value.trim();
9
+ if (summary.length === 0)
10
+ fail('invalid-input', 'report summary must not be empty');
11
+ const bounded = truncateUtf8(summary, maxBytes);
12
+ return Object.freeze({ summary: bounded.value, truncated: bounded.truncated });
13
+ }
14
+ /**
15
+ * Lifecycle orchestration on top of the durable store.
16
+ *
17
+ * The ledger owns sequencing and limits (lease, attempt budget, report size,
18
+ * artifact containment) while the store owns atomicity. Nothing here schedules
19
+ * work: every transition is triggered by an admission, a tool call or startup
20
+ * recovery, so the plugin adds no loop or timer to the host.
21
+ */
22
+ export class WorkItemLedger {
23
+ #store;
24
+ #workspace;
25
+ #limits;
26
+ #now;
27
+ #diagnosis;
28
+ constructor(options) {
29
+ this.#store = options.store;
30
+ this.#workspace = options.workspace;
31
+ this.#limits = options.limits;
32
+ this.#diagnosis = options.diagnosis ?? false;
33
+ this.#now = options.now ?? (() => Date.now());
34
+ }
35
+ get store() {
36
+ return this.#store;
37
+ }
38
+ get workspace() {
39
+ return this.#workspace;
40
+ }
41
+ /**
42
+ * Claim one item for one occurrence run.
43
+ *
44
+ * Creates the private scratch directory before the CAS so a worker never sees
45
+ * a claimed item without a place to write. The store decides the conflict.
46
+ */
47
+ claim(request) {
48
+ const item = this.#store.findItemById(request.itemId);
49
+ if (item === undefined) {
50
+ const viaOccurrence = this.#store.findItemByOccurrence(request.occurrenceId);
51
+ if (viaOccurrence === undefined)
52
+ fail('not-found', 'no work item is bound to this run');
53
+ fail('identity-mismatch', 'reported item does not match the dispatched occurrence');
54
+ }
55
+ const directory = this.#workspace.ensureDirectory(item.id);
56
+ if (item.workDir !== directory) {
57
+ // The item was admitted before its directory existed; keep the stored
58
+ // path authoritative and refuse a silently relocated workspace.
59
+ if (!this.#workspace.contains(item.workDir))
60
+ fail('storage', 'stored work directory escapes workRoot');
61
+ this.#workspace.ensureDirectory(item.id);
62
+ }
63
+ return this.#store.claim({ itemId: item.id, runId: request.runId, occurrenceId: request.occurrenceId, leaseMs: this.#limits.leaseMs, ...(this.#diagnosis ? { reclaimExpired: false } : {}) });
64
+ }
65
+ /**
66
+ * Park an item whose admission mandate failed revalidation.
67
+ *
68
+ * The item stays open and resumable: no claim is started, no dispatch is
69
+ * retired, and the same item is claimed or woken unchanged once policy allows
70
+ * the identical mandate again.
71
+ */
72
+ parkAuthority(item, reason, detail = {}) {
73
+ return this.#store.parkAuthority(item.id, reason, detail, this.#now());
74
+ }
75
+ /** Record a successful revalidation, lifting only this gate's own wait. */
76
+ restoreAuthority(item) {
77
+ return this.#store.restoreAuthority(item.id, this.#now());
78
+ }
79
+ /** Mint a fresh wake after a claim-time revalidation denial left no run. */
80
+ rearmAuthority(item) {
81
+ this.#store.rearmAuthority(item.id);
82
+ }
83
+ /**
84
+ * Append a report revision under the active claim.
85
+ *
86
+ * The summary is truncated to `maxReportBytes` rather than rejected, because
87
+ * a long report is still evidence; artifact paths are validated strictly.
88
+ * Idempotent by `idempotencyKey`, so a retried tool call is safe.
89
+ */
90
+ report(request) {
91
+ const item = this.#store.findItemById(request.itemId);
92
+ if (item === undefined)
93
+ fail('not-found', 'work item does not exist');
94
+ const claim = this.#store.findClaimByRun(request.runId);
95
+ if (claim === undefined)
96
+ fail('claim-conflict', 'claim this item before reporting');
97
+ const bounded = normalizeWorkItemReportSummary(request.summary, this.#limits.maxReportBytes);
98
+ const artifacts = this.#workspace.validateArtifacts(item, request.artifactPaths);
99
+ return this.#store.report({
100
+ itemId: item.id,
101
+ runId: request.runId,
102
+ status: request.status,
103
+ summary: bounded.summary,
104
+ truncated: bounded.truncated,
105
+ artifactPaths: artifacts,
106
+ idempotencyKey: request.idempotencyKey,
107
+ maxReports: this.#limits.maxReportsPerItem,
108
+ leaseMs: this.#limits.leaseMs,
109
+ waitingResumeMs: this.#limits.waitingResumeMs,
110
+ });
111
+ }
112
+ /** Record the outcome of one delivery attempt for a report revision. */
113
+ recordDelivery(itemId, revision, state, deliveryId) {
114
+ this.#store.setReportDelivery(itemId, revision, state, deliveryId);
115
+ }
116
+ /** Lazy lease recovery, invoked on startup and every admission/claim. */
117
+ recover() {
118
+ if (this.#diagnosis)
119
+ return Object.freeze({ requeued: Object.freeze([]), blocked: Object.freeze([]) });
120
+ return this.#store.reclaimExpired();
121
+ }
122
+ detail(itemId) {
123
+ const item = this.#store.findItemById(itemId);
124
+ if (item === undefined)
125
+ return undefined;
126
+ return Object.freeze({
127
+ item,
128
+ events: this.#store.events(item.id),
129
+ claim: this.#store.activeClaim(item.id),
130
+ reports: this.#store.reports(item.id),
131
+ dispatch: this.#store.getDispatch(item.id),
132
+ });
133
+ }
134
+ list(states, limit) {
135
+ return this.#store.listItems({ ...(states === undefined ? {} : { states }), ...(limit === undefined ? {} : { limit }) });
136
+ }
137
+ claimedRun(itemId, runId) {
138
+ const claim = this.#store.findClaimByRun(runId);
139
+ return claim !== undefined && claim.itemId === itemId ? claim : undefined;
140
+ }
141
+ now() {
142
+ return this.#now();
143
+ }
144
+ }
145
+ //# sourceMappingURL=ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { WorkItemAcceptanceBinding, WorkItemAcceptanceHandle, WorkItemAdmitInput, WorkItemDecisionRefusal, WorkItemExecuteDecision, WorkItemMandateBasis } from './types.ts';
2
+ /** Normalized decision; mandate fields are re-validated by ordinary admission. */
3
+ export interface NormalizedExecuteDecision {
4
+ readonly decisionId: string;
5
+ readonly origin: WorkItemExecuteDecision['origin'];
6
+ readonly mode: WorkItemExecuteDecision['mode'];
7
+ readonly policyRuleId: string | undefined;
8
+ readonly budgetRemaining: number;
9
+ readonly input: WorkItemAdmitInput;
10
+ /** Acceptance handle, resolved against the verifier by admission. */
11
+ readonly acceptance: WorkItemAcceptanceHandle | undefined;
12
+ }
13
+ /**
14
+ * Structural validation of one execute decision. Pure and deterministic.
15
+ *
16
+ * Only the shape is checked here; kind/title/brief/binding normalization stays
17
+ * with `WorkItemAdmission` so the two admission paths cannot drift.
18
+ */
19
+ export declare function normalizeExecuteDecision(value: unknown): NormalizedExecuteDecision;
20
+ /** Stable external identity: the decision id alone decides the dedup key. */
21
+ export declare function decisionExternalId(decisionId: string): string;
22
+ /**
23
+ * The inferred-execution gate. All three conditions must hold at once; an
24
+ * explicit decision is not gated here (Policy and ordinary admission gates
25
+ * still apply to it).
26
+ */
27
+ export declare function decisionRefusal(decision: NormalizedExecuteDecision): WorkItemDecisionRefusal | undefined;
28
+ /**
29
+ * Digest over the decision identity after admission normalized the mandate.
30
+ *
31
+ * Mode and remaining budget are admission-time facts, not identity: a replay
32
+ * of the same decision after the budget moved must resolve to the same item,
33
+ * while a different scope under the same id must not.
34
+ */
35
+ export declare function mandateDigest(decision: NormalizedExecuteDecision, normalized: {
36
+ readonly kind: string;
37
+ readonly title: string;
38
+ readonly brief: string;
39
+ readonly originBindingId: string;
40
+ readonly acceptanceRef: string | null;
41
+ }): string;
42
+ export declare function buildMandateBasis(decision: NormalizedExecuteDecision, digest: string, acceptance?: WorkItemAcceptanceBinding): WorkItemMandateBasis;
43
+ /** Structural check of a stored mandate; anything else is a malformed basis. */
44
+ export declare function mandateIsUsable(value: unknown): value is WorkItemMandateBasis;
45
+ //# sourceMappingURL=mandate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mandate.d.ts","sourceRoot":"","sources":["../src/mandate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACrB,MAAM,YAAY,CAAA;AA0BnB,kFAAkF;AAClF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAA;IAClD,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAA;IAC9C,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IACzC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAA;IAClC,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,wBAAwB,GAAG,SAAS,CAAA;CAC1D;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,yBAAyB,CAgDlF;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,yBAAyB,GAAG,uBAAuB,GAAG,SAAS,CAMxG;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,yBAAyB,EAAE,UAAU,EAAE;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CACtC,GAAG,MAAM,CAeT;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,yBAAyB,EACnC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,yBAAyB,GACrC,oBAAoB,CAWtB;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAmB7E"}