@oscharko-dev/keiko-contracts 0.2.7 → 0.2.9

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 (108) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/bff-wire.d.ts +86 -19
  3. package/dist/bff-wire.d.ts.map +1 -1
  4. package/dist/command-runner.d.ts +81 -0
  5. package/dist/command-runner.d.ts.map +1 -0
  6. package/dist/command-runner.js +209 -0
  7. package/dist/container-runtime.d.ts +125 -0
  8. package/dist/container-runtime.d.ts.map +1 -0
  9. package/dist/container-runtime.js +287 -0
  10. package/dist/context-engineering.js +2 -2
  11. package/dist/discussion-intelligence.d.ts +70 -0
  12. package/dist/discussion-intelligence.d.ts.map +1 -0
  13. package/dist/discussion-intelligence.js +440 -0
  14. package/dist/editor-agent-governance.d.ts +65 -0
  15. package/dist/editor-agent-governance.d.ts.map +1 -0
  16. package/dist/editor-agent-governance.js +180 -0
  17. package/dist/editor-agent.d.ts +29 -1
  18. package/dist/editor-agent.d.ts.map +1 -1
  19. package/dist/editor-agent.js +183 -6
  20. package/dist/editor-builtin-capabilities.d.ts +13 -0
  21. package/dist/editor-builtin-capabilities.d.ts.map +1 -0
  22. package/dist/editor-builtin-capabilities.js +135 -0
  23. package/dist/editor-language-mode-map.d.ts +11 -0
  24. package/dist/editor-language-mode-map.d.ts.map +1 -0
  25. package/dist/editor-language-mode-map.js +89 -0
  26. package/dist/editor-layout.d.ts +37 -0
  27. package/dist/editor-layout.d.ts.map +1 -1
  28. package/dist/editor-layout.js +125 -8
  29. package/dist/editor-workspace-path.d.ts +20 -0
  30. package/dist/editor-workspace-path.d.ts.map +1 -0
  31. package/dist/editor-workspace-path.js +133 -0
  32. package/dist/evidence.d.ts +3 -1
  33. package/dist/evidence.d.ts.map +1 -1
  34. package/dist/gateway.d.ts +72 -3
  35. package/dist/gateway.d.ts.map +1 -1
  36. package/dist/gateway.js +73 -3
  37. package/dist/git-commit-intent.d.ts +28 -0
  38. package/dist/git-commit-intent.d.ts.map +1 -0
  39. package/dist/git-commit-intent.js +155 -0
  40. package/dist/git-commit-policy.d.ts +29 -0
  41. package/dist/git-commit-policy.d.ts.map +1 -0
  42. package/dist/git-commit-policy.js +173 -0
  43. package/dist/git-delivery-action-sheet.d.ts +157 -0
  44. package/dist/git-delivery-action-sheet.d.ts.map +1 -0
  45. package/dist/git-delivery-action-sheet.js +430 -0
  46. package/dist/git-delivery-evidence.d.ts +92 -0
  47. package/dist/git-delivery-evidence.d.ts.map +1 -0
  48. package/dist/git-delivery-evidence.js +272 -0
  49. package/dist/git-delivery-policy.d.ts +40 -0
  50. package/dist/git-delivery-policy.d.ts.map +1 -0
  51. package/dist/git-delivery-policy.js +183 -0
  52. package/dist/git-delivery-provider.d.ts +53 -0
  53. package/dist/git-delivery-provider.d.ts.map +1 -0
  54. package/dist/git-delivery-provider.js +96 -0
  55. package/dist/git-delivery.d.ts +202 -0
  56. package/dist/git-delivery.d.ts.map +1 -0
  57. package/dist/git-delivery.js +410 -0
  58. package/dist/git-history.d.ts +27 -0
  59. package/dist/git-history.d.ts.map +1 -0
  60. package/dist/git-history.js +73 -0
  61. package/dist/git-merge.d.ts +67 -0
  62. package/dist/git-merge.d.ts.map +1 -0
  63. package/dist/git-merge.js +323 -0
  64. package/dist/git-pull-request.d.ts +112 -0
  65. package/dist/git-pull-request.d.ts.map +1 -0
  66. package/dist/git-pull-request.js +351 -0
  67. package/dist/git-repository-agent.d.ts +46 -0
  68. package/dist/git-repository-agent.d.ts.map +1 -0
  69. package/dist/git-repository-agent.js +198 -0
  70. package/dist/git-repository-summary.d.ts +54 -0
  71. package/dist/git-repository-summary.d.ts.map +1 -0
  72. package/dist/git-repository-summary.js +105 -0
  73. package/dist/git-repository.d.ts +60 -0
  74. package/dist/git-repository.d.ts.map +1 -0
  75. package/dist/git-repository.js +106 -0
  76. package/dist/git-sync.d.ts +49 -0
  77. package/dist/git-sync.d.ts.map +1 -0
  78. package/dist/git-sync.js +110 -0
  79. package/dist/index.d.ts +63 -9
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +33 -6
  82. package/dist/lsp-process.d.ts +38 -0
  83. package/dist/lsp-process.d.ts.map +1 -0
  84. package/dist/lsp-process.js +103 -0
  85. package/dist/prompt-enhancer-analyzer.d.ts.map +1 -1
  86. package/dist/prompt-enhancer-analyzer.js +198 -22
  87. package/dist/runtime-capabilities.d.ts +44 -0
  88. package/dist/runtime-capabilities.d.ts.map +1 -0
  89. package/dist/runtime-capabilities.js +141 -0
  90. package/dist/task-workspace.d.ts +302 -0
  91. package/dist/task-workspace.d.ts.map +1 -0
  92. package/dist/task-workspace.js +1236 -0
  93. package/dist/voice-action-intent.d.ts +86 -0
  94. package/dist/voice-action-intent.d.ts.map +1 -0
  95. package/dist/voice-action-intent.js +387 -0
  96. package/dist/voice-playback.d.ts +50 -0
  97. package/dist/voice-playback.d.ts.map +1 -0
  98. package/dist/voice-playback.js +240 -0
  99. package/dist/voice-protocol.d.ts +165 -0
  100. package/dist/voice-protocol.d.ts.map +1 -0
  101. package/dist/voice-protocol.js +312 -0
  102. package/dist/voice-transcript.d.ts +57 -0
  103. package/dist/voice-transcript.d.ts.map +1 -0
  104. package/dist/voice-transcript.js +221 -0
  105. package/package.json +5 -1
  106. package/dist/conversation-budget.d.ts +0 -37
  107. package/dist/conversation-budget.d.ts.map +0 -1
  108. package/dist/conversation-budget.js +0 -97
@@ -0,0 +1,86 @@
1
+ import type { VoiceProfile } from "./gateway.js";
2
+ import type { CommittedVoiceTranscriptProjection, VoiceTranscriptSource } from "./voice-transcript.js";
3
+ export declare const VOICE_ACTION_INTENT_SCHEMA_VERSION: "1";
4
+ export declare function isVoiceActionIntentSchemaVersionSupported(version: unknown): boolean;
5
+ export type SpokenActionEffectClass = "read-only" | "mutating" | "destructive" | "external-effect" | "unknown";
6
+ export declare const SPOKEN_ACTION_EFFECT_CLASSES: readonly SpokenActionEffectClass[];
7
+ export declare function isSpokenActionEffectClass(value: unknown): value is SpokenActionEffectClass;
8
+ export declare function assertNeverSpokenActionEffectClass(value: never): never;
9
+ export declare const SPOKEN_ACTION_EFFECT_REQUIRES_CONFIRMATION: Readonly<Record<SpokenActionEffectClass, boolean>>;
10
+ export declare function spokenActionRequiresConfirmation(effectClass: SpokenActionEffectClass): boolean;
11
+ export interface SpokenActionEffectMarkers {
12
+ readonly destructive: readonly string[];
13
+ readonly externalEffect: readonly string[];
14
+ readonly mutating: readonly string[];
15
+ readonly readOnly: readonly string[];
16
+ }
17
+ export declare const SPOKEN_ACTION_EFFECT_MARKERS: SpokenActionEffectMarkers;
18
+ export declare function classifySpokenActionEffect(committedText: string): SpokenActionEffectClass;
19
+ export type SpokenActionState = "proposed" | "awaiting-confirmation" | "confirmed" | "routed" | "completed" | "cancelled" | "superseded" | "interrupted" | "expired";
20
+ export declare const SPOKEN_ACTION_STATES: readonly SpokenActionState[];
21
+ export declare const SPOKEN_ACTION_TERMINAL_STATES: readonly SpokenActionState[];
22
+ export declare const SPOKEN_ACTION_STATE_TRANSITIONS: Readonly<Record<SpokenActionState, readonly SpokenActionState[]>>;
23
+ export declare function isSpokenActionState(value: unknown): value is SpokenActionState;
24
+ export declare function canTransitionSpokenAction(from: SpokenActionState, to: SpokenActionState): boolean;
25
+ export declare function isTerminalSpokenActionState(state: SpokenActionState): boolean;
26
+ export declare function assertNeverSpokenActionState(value: never): never;
27
+ export declare function voiceCanProposeAction(profile: VoiceProfile): boolean;
28
+ export type SpokenActionOutcome = "routed" | "denied" | "cancelled" | "superseded" | "not-applicable";
29
+ export declare const SPOKEN_ACTION_OUTCOMES: readonly SpokenActionOutcome[];
30
+ export declare function isSpokenActionOutcome(value: unknown): value is SpokenActionOutcome;
31
+ export interface SpokenActionConfirmationInput {
32
+ readonly schemaVersion: typeof VOICE_ACTION_INTENT_SCHEMA_VERSION;
33
+ readonly committedText: string;
34
+ readonly turnIndex: number;
35
+ readonly effectClass: SpokenActionEffectClass;
36
+ readonly source: VoiceTranscriptSource;
37
+ readonly committedSegmentCount: number;
38
+ }
39
+ export declare function canonicalizeSpokenActionConfirmation(input: SpokenActionConfirmationInput): string;
40
+ export interface SpokenActionProposal {
41
+ readonly schemaVersion: typeof VOICE_ACTION_INTENT_SCHEMA_VERSION;
42
+ readonly effectClass: SpokenActionEffectClass;
43
+ readonly requiresConfirmation: boolean;
44
+ readonly state: SpokenActionState;
45
+ readonly source: VoiceTranscriptSource;
46
+ readonly turnIndex: number;
47
+ readonly committedSegmentCount: number;
48
+ readonly committedChars: number;
49
+ readonly confirmationInput: SpokenActionConfirmationInput;
50
+ }
51
+ export declare function normalizeSpokenActionProposal(projection: CommittedVoiceTranscriptProjection, profile: VoiceProfile, turnIndex: number, source: VoiceTranscriptSource): SpokenActionProposal | undefined;
52
+ export interface SpokenActionAuditRecord {
53
+ readonly schemaVersion: typeof VOICE_ACTION_INTENT_SCHEMA_VERSION;
54
+ readonly effectClass: SpokenActionEffectClass;
55
+ readonly state: SpokenActionState;
56
+ readonly confirmationRequired: boolean;
57
+ readonly confirmed: boolean;
58
+ readonly outcome: SpokenActionOutcome;
59
+ readonly source: VoiceTranscriptSource;
60
+ readonly turnIndex: number;
61
+ readonly committedSegmentCount: number;
62
+ readonly committedChars: number;
63
+ readonly bindingDigest: string;
64
+ }
65
+ export interface SpokenActionAuditInput {
66
+ readonly effectClass: SpokenActionEffectClass;
67
+ readonly state: SpokenActionState;
68
+ readonly confirmationRequired: boolean;
69
+ readonly confirmed: boolean;
70
+ readonly outcome: SpokenActionOutcome;
71
+ readonly source: VoiceTranscriptSource;
72
+ readonly turnIndex: number;
73
+ readonly committedSegmentCount: number;
74
+ readonly committedChars: number;
75
+ readonly bindingDigest: string;
76
+ }
77
+ export declare function buildSpokenActionAuditRecord(input: SpokenActionAuditInput): SpokenActionAuditRecord;
78
+ export type SpokenActionValidationResult = {
79
+ readonly ok: true;
80
+ } | {
81
+ readonly ok: false;
82
+ readonly reasons: readonly string[];
83
+ };
84
+ export declare function validateSpokenActionProposal(value: unknown): SpokenActionValidationResult;
85
+ export declare function validateSpokenActionAuditRecord(value: unknown): SpokenActionValidationResult;
86
+ //# sourceMappingURL=voice-action-intent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-action-intent.d.ts","sourceRoot":"","sources":["../src/voice-action-intent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,387 @@
1
+ // Spoken Action Intent governance contract (Epic #491, Issue #503, ADR-0066). Voice is an UNTRUSTED
2
+ // input source: a committed spoken transcript may PROPOSE an action but can never EXECUTE one or bypass
3
+ // any existing gate. This leaf module DEFINES the deterministic, fail-closed normalization +
4
+ // confirmation layer that sits IN FRONT OF the existing governance (the workflow-handoff request, its
5
+ // user approval gate, `validateWorkflowHandoffRequest`, and `checkPatchAgainstScope`). It ADDS
6
+ // preconditions; it removes none.
7
+ //
8
+ // It is pure data + pure functions only — nothing performs IO, crypto, clock reads, randomness, or audio
9
+ // processing. The audit record (`SpokenActionAuditRecord`) has NO raw text and NO audio field: it carries
10
+ // only closed enums, bools, ints, and a content-free one-way digest computed downstream. The proposal
11
+ // (`SpokenActionProposal`) carries `committedText` ONLY transiently inside `confirmationInput` for the
12
+ // downstream digest derivation (Artifact 2); that seed is never persisted into evidence.
13
+ //
14
+ // Classification is a GUARDRAIL, not a semantic engine. `classifySpokenActionEffect` is deterministic,
15
+ // local (no NLU, no model call), and fail-closed: text it does not recognize as read-only-only resolves
16
+ // to `unknown`, which requires confirmation. Its accuracy is NOT load-bearing for safety, because (a) the
17
+ // default is fail-closed and (b) a proposal never authorizes anything — the existing approval gate and
18
+ // handoff gates still independently apply downstream. Keeping classification on-host and content-free is
19
+ // the strongest posture for the banking / insurer audience.
20
+ //
21
+ // `VOICE_ACTION_INTENT_SCHEMA_VERSION` follows the sibling evolution rule (ADR-0010 D2): a breaking
22
+ // change introduces a NEW literal rather than mutating "1", and it is INDEPENDENT of every other schema
23
+ // version. Leaf-package rule (ADR-0019 direction 1): no cross-package workspace import may appear here;
24
+ // siblings are reached by relative path only.
25
+ import { isVoiceTranscriptSource, voiceTranscriptCaptureAllowed } from "./voice-transcript.js";
26
+ // ─── Schema version ───────────────────────────────────────────────────────────
27
+ export const VOICE_ACTION_INTENT_SCHEMA_VERSION = "1";
28
+ export function isVoiceActionIntentSchemaVersionSupported(version) {
29
+ return version === VOICE_ACTION_INTENT_SCHEMA_VERSION;
30
+ }
31
+ export const SPOKEN_ACTION_EFFECT_CLASSES = [
32
+ "read-only",
33
+ "mutating",
34
+ "destructive",
35
+ "external-effect",
36
+ "unknown",
37
+ ];
38
+ export function isSpokenActionEffectClass(value) {
39
+ return (typeof value === "string" && SPOKEN_ACTION_EFFECT_CLASSES.includes(value));
40
+ }
41
+ export function assertNeverSpokenActionEffectClass(value) {
42
+ throw new TypeError(`Unhandled SpokenActionEffectClass: ${JSON.stringify(value)}`);
43
+ }
44
+ // Fail-closed confirmation table: every class except `read-only` requires explicit confirmation. Keyed
45
+ // by class for totality (a new class without an entry is a compile error).
46
+ export const SPOKEN_ACTION_EFFECT_REQUIRES_CONFIRMATION = {
47
+ "read-only": false,
48
+ mutating: true,
49
+ destructive: true,
50
+ "external-effect": true,
51
+ unknown: true,
52
+ };
53
+ export function spokenActionRequiresConfirmation(effectClass) {
54
+ return SPOKEN_ACTION_EFFECT_REQUIRES_CONFIRMATION[effectClass];
55
+ }
56
+ export const SPOKEN_ACTION_EFFECT_MARKERS = {
57
+ destructive: ["delete", "remove", "drop", "purge", "erase", "destroy", "wipe", "truncate"],
58
+ externalEffect: [
59
+ "send",
60
+ "deploy",
61
+ "publish",
62
+ "email",
63
+ "pay",
64
+ "transfer",
65
+ "call",
66
+ "post",
67
+ "merge",
68
+ ],
69
+ mutating: [
70
+ "create",
71
+ "add",
72
+ "update",
73
+ "edit",
74
+ "rename",
75
+ "move",
76
+ "write",
77
+ "set",
78
+ "change",
79
+ "modify",
80
+ ],
81
+ readOnly: [
82
+ "show",
83
+ "list",
84
+ "read",
85
+ "view",
86
+ "display",
87
+ "find",
88
+ "search",
89
+ "open",
90
+ "get",
91
+ "describe",
92
+ ],
93
+ };
94
+ // Strip characters that could smuggle an invisible or compatibility-form verb past the ASCII
95
+ // lexicon: C0/C1 controls (\u0000-\u0008, \u000E-\u001F, \u007F-\u009F),
96
+ // zero-width chars (\u200B-\u200D, \uFEFF), and bidi-override controls
97
+ // (\u202A-\u202E, \u2066-\u2069). The standard whitespace controls (\u0009-\u000D:
98
+ // tab/LF/VT/FF/CR) are deliberately EXCLUDED so the later \s+ collapse turns them into a single
99
+ // space and word boundaries survive; stripping them would join adjacent words and silently lose the
100
+ // marker. Without this strip, a destructive verb interrupted by a zero-width char would dodge the
101
+ // marker, misclassify as read-only, and skip confirmation.
102
+ /* eslint-disable no-control-regex -- C0/C1 control ranges are intentional here */
103
+ const UNSAFE_FORMAT_CHARS = /[\u0000-\u0008\u000E-\u001F\u007F-\u009F\u200B-\u200D\uFEFF\u202A-\u202E\u2066-\u2069]/g;
104
+ /* eslint-enable no-control-regex */
105
+ // Inline minimal normalization — leaf cannot import keiko-security. Apply Unicode NFKC FIRST so
106
+ // compatibility forms fold to ASCII (a fullwidth destructive verb folds to its ASCII spelling);
107
+ // otherwise such forms evade the ASCII marker lexicon and a destructive request would misclassify
108
+ // as read-only and skip confirmation. Then strip zero-width / bidi / control chars, lowercase, trim,
109
+ // and collapse internal whitespace runs to single spaces so word-boundary matching is stable. On
110
+ // plain ASCII input NFKC and the strip are the identity, so existing ASCII classification is unchanged.
111
+ function normalizeForClassification(text) {
112
+ return text
113
+ .normalize("NFKC")
114
+ .replace(UNSAFE_FORMAT_CHARS, "")
115
+ .trim()
116
+ .toLowerCase()
117
+ .replace(/\s+/g, " ");
118
+ }
119
+ // Whole-word membership test: wraps both sides in spaces so `set` does not match inside `settlement`.
120
+ function containsMarker(paddedText, markers) {
121
+ return markers.some((marker) => paddedText.includes(` ${marker} `));
122
+ }
123
+ // Conservative, ordered precedence: destructive > external-effect > mutating > read-only. Empty /
124
+ // whitespace-only text → `unknown`. Text that matches no recognized marker → `unknown` (fail-closed).
125
+ export function classifySpokenActionEffect(committedText) {
126
+ const normalized = normalizeForClassification(committedText);
127
+ if (normalized.length === 0) {
128
+ return "unknown";
129
+ }
130
+ const padded = ` ${normalized} `;
131
+ if (containsMarker(padded, SPOKEN_ACTION_EFFECT_MARKERS.destructive)) {
132
+ return "destructive";
133
+ }
134
+ if (containsMarker(padded, SPOKEN_ACTION_EFFECT_MARKERS.externalEffect)) {
135
+ return "external-effect";
136
+ }
137
+ if (containsMarker(padded, SPOKEN_ACTION_EFFECT_MARKERS.mutating)) {
138
+ return "mutating";
139
+ }
140
+ if (containsMarker(padded, SPOKEN_ACTION_EFFECT_MARKERS.readOnly)) {
141
+ return "read-only";
142
+ }
143
+ return "unknown";
144
+ }
145
+ export const SPOKEN_ACTION_STATES = [
146
+ "proposed",
147
+ "awaiting-confirmation",
148
+ "confirmed",
149
+ "routed",
150
+ "completed",
151
+ "cancelled",
152
+ "superseded",
153
+ "interrupted",
154
+ "expired",
155
+ ];
156
+ export const SPOKEN_ACTION_TERMINAL_STATES = [
157
+ "completed",
158
+ "cancelled",
159
+ "superseded",
160
+ "interrupted",
161
+ "expired",
162
+ ];
163
+ // The non-terminal invalidation targets every non-terminal state can reach (cancel / supersede /
164
+ // interrupt / expire). Shared so the transition table stays consistent.
165
+ const SPOKEN_ACTION_INVALIDATION_STATES = [
166
+ "cancelled",
167
+ "superseded",
168
+ "interrupted",
169
+ "expired",
170
+ ];
171
+ // Legal state-changing transitions, keyed by state for totality.
172
+ // read-only path: proposed → routed → completed
173
+ // confirm path: proposed → awaiting-confirmation → confirmed → routed → completed
174
+ // any non-terminal: → cancelled | superseded | interrupted | expired
175
+ export const SPOKEN_ACTION_STATE_TRANSITIONS = {
176
+ proposed: ["awaiting-confirmation", "routed", ...SPOKEN_ACTION_INVALIDATION_STATES],
177
+ "awaiting-confirmation": ["confirmed", ...SPOKEN_ACTION_INVALIDATION_STATES],
178
+ confirmed: ["routed", ...SPOKEN_ACTION_INVALIDATION_STATES],
179
+ routed: ["completed", ...SPOKEN_ACTION_INVALIDATION_STATES],
180
+ completed: [],
181
+ cancelled: [],
182
+ superseded: [],
183
+ interrupted: [],
184
+ expired: [],
185
+ };
186
+ export function isSpokenActionState(value) {
187
+ return typeof value === "string" && SPOKEN_ACTION_STATES.includes(value);
188
+ }
189
+ export function canTransitionSpokenAction(from, to) {
190
+ return SPOKEN_ACTION_STATE_TRANSITIONS[from].includes(to);
191
+ }
192
+ export function isTerminalSpokenActionState(state) {
193
+ return SPOKEN_ACTION_TERMINAL_STATES.includes(state);
194
+ }
195
+ export function assertNeverSpokenActionState(value) {
196
+ throw new TypeError(`Unhandled SpokenActionState: ${JSON.stringify(value)}`);
197
+ }
198
+ // ─── Capability gating (AC1 / AC2) ───────────────────────────────────────────────
199
+ // Derived from the voice transcript capability so it cannot drift: a spoken action can be proposed only
200
+ // where committed transcript capture is allowed (`speech-to-text` / `full-realtime`). `none` and
201
+ // `speech-output` (playback-only) make the whole layer dormant (AC1). The text path never calls this.
202
+ export function voiceCanProposeAction(profile) {
203
+ return voiceTranscriptCaptureAllowed(profile);
204
+ }
205
+ export const SPOKEN_ACTION_OUTCOMES = [
206
+ "routed",
207
+ "denied",
208
+ "cancelled",
209
+ "superseded",
210
+ "not-applicable",
211
+ ];
212
+ export function isSpokenActionOutcome(value) {
213
+ return typeof value === "string" && SPOKEN_ACTION_OUTCOMES.includes(value);
214
+ }
215
+ // Deterministic, stable field ordering with length-prefixed segments so no field's content can be
216
+ // confused with another's (a classic canonicalization ambiguity). Pure string; no crypto here.
217
+ export function canonicalizeSpokenActionConfirmation(input) {
218
+ const fields = [
219
+ `v=${input.schemaVersion}`,
220
+ `turn=${String(input.turnIndex)}`,
221
+ `effect=${input.effectClass}`,
222
+ `source=${input.source}`,
223
+ `segments=${String(input.committedSegmentCount)}`,
224
+ `textlen=${String(input.committedText.length)}`,
225
+ `text=${input.committedText}`,
226
+ ];
227
+ return fields.join("\n");
228
+ }
229
+ // AC1/AC2 entry gate: returns `undefined` when the profile cannot propose actions (AC1) or the committed
230
+ // projection carries no text (AC2). Partial / stable / discarded / redacted / superseded segments can
231
+ // never appear in `projection.text` by construction (`selectCommittedVoiceTranscript`), so a non-empty
232
+ // projection text already means committed content only.
233
+ export function normalizeSpokenActionProposal(projection, profile, turnIndex, source) {
234
+ if (!voiceCanProposeAction(profile)) {
235
+ return undefined;
236
+ }
237
+ const committedText = projection.text;
238
+ if (committedText.trim().length === 0) {
239
+ return undefined;
240
+ }
241
+ const effectClass = classifySpokenActionEffect(committedText);
242
+ const requiresConfirmation = spokenActionRequiresConfirmation(effectClass);
243
+ const confirmationInput = {
244
+ schemaVersion: VOICE_ACTION_INTENT_SCHEMA_VERSION,
245
+ committedText,
246
+ turnIndex,
247
+ effectClass,
248
+ source,
249
+ committedSegmentCount: projection.segmentCount,
250
+ };
251
+ return {
252
+ schemaVersion: VOICE_ACTION_INTENT_SCHEMA_VERSION,
253
+ effectClass,
254
+ requiresConfirmation,
255
+ state: requiresConfirmation ? "awaiting-confirmation" : "proposed",
256
+ source,
257
+ turnIndex,
258
+ committedSegmentCount: projection.segmentCount,
259
+ committedChars: committedText.length,
260
+ confirmationInput,
261
+ };
262
+ }
263
+ // Pure builder. Copies only the content-free fields; structurally cannot carry committed text because no
264
+ // text field exists on either the input or the record.
265
+ export function buildSpokenActionAuditRecord(input) {
266
+ return {
267
+ schemaVersion: VOICE_ACTION_INTENT_SCHEMA_VERSION,
268
+ effectClass: input.effectClass,
269
+ state: input.state,
270
+ confirmationRequired: input.confirmationRequired,
271
+ confirmed: input.confirmed,
272
+ outcome: input.outcome,
273
+ source: input.source,
274
+ turnIndex: input.turnIndex,
275
+ committedSegmentCount: input.committedSegmentCount,
276
+ committedChars: input.committedChars,
277
+ bindingDigest: input.bindingDigest,
278
+ };
279
+ }
280
+ function buildSpokenActionResult(reasons) {
281
+ return reasons.length === 0 ? { ok: true } : { ok: false, reasons };
282
+ }
283
+ function isRecord(value) {
284
+ return typeof value === "object" && value !== null;
285
+ }
286
+ function isNonNegativeInteger(value) {
287
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
288
+ }
289
+ // A binding digest is either the empty string (no confirmation bound) or a 64-char lowercase sha256 hex.
290
+ const BINDING_DIGEST_PATTERN = /^[0-9a-f]{64}$/;
291
+ function isValidBindingDigest(value) {
292
+ return value === "" || (typeof value === "string" && BINDING_DIGEST_PATTERN.test(value));
293
+ }
294
+ // Shared count-field check used by both record validators: turnIndex / committedSegmentCount /
295
+ // committedChars must each be non-negative integers. Extracting it keeps both validators under the
296
+ // complexity cap and keeps the reason strings identical across record shapes.
297
+ function validateCommittedCounts(value, reasons) {
298
+ if (!isNonNegativeInteger(value.turnIndex)) {
299
+ reasons.push("turnIndex: must be a non-negative integer");
300
+ }
301
+ if (!isNonNegativeInteger(value.committedSegmentCount)) {
302
+ reasons.push("committedSegmentCount: must be a non-negative integer");
303
+ }
304
+ if (!isNonNegativeInteger(value.committedChars)) {
305
+ reasons.push("committedChars: must be a non-negative integer");
306
+ }
307
+ }
308
+ function validateConfirmationInput(value, reasons) {
309
+ if (!isRecord(value)) {
310
+ reasons.push("confirmationInput: must be an object");
311
+ return;
312
+ }
313
+ if (!isVoiceActionIntentSchemaVersionSupported(value.schemaVersion)) {
314
+ reasons.push("confirmationInput.schemaVersion: unsupported");
315
+ }
316
+ if (typeof value.committedText !== "string") {
317
+ reasons.push("confirmationInput.committedText: must be a string");
318
+ }
319
+ if (!isNonNegativeInteger(value.turnIndex)) {
320
+ reasons.push("confirmationInput.turnIndex: must be a non-negative integer");
321
+ }
322
+ if (!isSpokenActionEffectClass(value.effectClass)) {
323
+ reasons.push("confirmationInput.effectClass: unknown effect class");
324
+ }
325
+ if (!isVoiceTranscriptSource(value.source)) {
326
+ reasons.push("confirmationInput.source: unknown transcript source");
327
+ }
328
+ if (!isNonNegativeInteger(value.committedSegmentCount)) {
329
+ reasons.push("confirmationInput.committedSegmentCount: must be a non-negative integer");
330
+ }
331
+ }
332
+ export function validateSpokenActionProposal(value) {
333
+ if (!isRecord(value)) {
334
+ return { ok: false, reasons: ["proposal: must be an object"] };
335
+ }
336
+ const reasons = [];
337
+ if (!isVoiceActionIntentSchemaVersionSupported(value.schemaVersion)) {
338
+ reasons.push("schemaVersion: unsupported");
339
+ }
340
+ if (!isSpokenActionEffectClass(value.effectClass)) {
341
+ reasons.push("effectClass: unknown effect class");
342
+ }
343
+ if (typeof value.requiresConfirmation !== "boolean") {
344
+ reasons.push("requiresConfirmation: must be a boolean");
345
+ }
346
+ if (!isSpokenActionState(value.state)) {
347
+ reasons.push("state: unknown spoken action state");
348
+ }
349
+ if (!isVoiceTranscriptSource(value.source)) {
350
+ reasons.push("source: unknown transcript source");
351
+ }
352
+ validateCommittedCounts(value, reasons);
353
+ validateConfirmationInput(value.confirmationInput, reasons);
354
+ return buildSpokenActionResult(reasons);
355
+ }
356
+ export function validateSpokenActionAuditRecord(value) {
357
+ if (!isRecord(value)) {
358
+ return { ok: false, reasons: ["audit: must be an object"] };
359
+ }
360
+ const reasons = [];
361
+ if (!isVoiceActionIntentSchemaVersionSupported(value.schemaVersion)) {
362
+ reasons.push("schemaVersion: unsupported");
363
+ }
364
+ if (!isSpokenActionEffectClass(value.effectClass)) {
365
+ reasons.push("effectClass: unknown effect class");
366
+ }
367
+ if (!isSpokenActionState(value.state)) {
368
+ reasons.push("state: unknown spoken action state");
369
+ }
370
+ if (typeof value.confirmationRequired !== "boolean") {
371
+ reasons.push("confirmationRequired: must be a boolean");
372
+ }
373
+ if (typeof value.confirmed !== "boolean") {
374
+ reasons.push("confirmed: must be a boolean");
375
+ }
376
+ if (!isSpokenActionOutcome(value.outcome)) {
377
+ reasons.push("outcome: unknown outcome");
378
+ }
379
+ if (!isVoiceTranscriptSource(value.source)) {
380
+ reasons.push("source: unknown transcript source");
381
+ }
382
+ validateCommittedCounts(value, reasons);
383
+ if (!isValidBindingDigest(value.bindingDigest)) {
384
+ reasons.push("bindingDigest: must be empty or a 64-char lowercase sha256 hex");
385
+ }
386
+ return buildSpokenActionResult(reasons);
387
+ }
@@ -0,0 +1,50 @@
1
+ import type { VoiceProfile } from "./gateway.js";
2
+ import type { VoicePlaybackState, VoiceReplayClass, VoiceRedactionClass } from "./voice-protocol.js";
3
+ export declare const VOICE_PLAYBACK_SCHEMA_VERSION: "1";
4
+ export declare function isVoicePlaybackSchemaVersionSupported(version: unknown): boolean;
5
+ export type VoicePlaybackPhase = "unavailable" | "preparing" | "speaking" | "paused" | "interrupted" | "canceled" | "failed" | "complete";
6
+ export declare const VOICE_PLAYBACK_PHASES: readonly VoicePlaybackPhase[];
7
+ export declare const VOICE_PLAYBACK_ACTIVE_PHASES: readonly VoicePlaybackPhase[];
8
+ export declare const VOICE_PLAYBACK_SETTLED_PHASES: readonly VoicePlaybackPhase[];
9
+ export type VoicePlaybackFailureKind = "rate-limited" | "timeout" | "provider-error" | "unavailable" | "internal";
10
+ export declare const VOICE_PLAYBACK_FAILURE_KINDS: readonly VoicePlaybackFailureKind[];
11
+ export declare const VOICE_PLAYBACK_PHASE_REPLAY: Record<VoicePlaybackPhase, VoiceReplayClass>;
12
+ export declare const VOICE_PLAYBACK_PHASE_REDACTION: Record<VoicePlaybackPhase, VoiceRedactionClass>;
13
+ export declare const VOICE_PLAYBACK_AUDIO_PLANE: import("./voice-protocol.js").VoiceMediaPlaneDescriptor;
14
+ export declare const VOICE_PLAYBACK_TRANSITIONS: Record<VoicePlaybackPhase, readonly VoicePlaybackPhase[]>;
15
+ export declare function isVoicePlaybackPhase(value: unknown): value is VoicePlaybackPhase;
16
+ export declare function isVoicePlaybackFailureKind(value: unknown): value is VoicePlaybackFailureKind;
17
+ export declare function voicePlaybackPhaseReplayClass(phase: VoicePlaybackPhase): VoiceReplayClass;
18
+ export declare function voicePlaybackPhaseRedactionClass(phase: VoicePlaybackPhase): VoiceRedactionClass;
19
+ export declare function isActiveVoicePlaybackPhase(phase: VoicePlaybackPhase): boolean;
20
+ export declare function isSettledVoicePlaybackPhase(phase: VoicePlaybackPhase): boolean;
21
+ export declare function canTransitionVoicePlayback(from: VoicePlaybackPhase, to: VoicePlaybackPhase): boolean;
22
+ export declare function assertNeverVoicePlaybackPhase(phase: never): never;
23
+ export declare function mapVoicePlaybackPhaseToWireState(phase: VoicePlaybackPhase): VoicePlaybackState | undefined;
24
+ export type VoicePlaybackEffect = "request-synthesis" | "start-output" | "pause-output" | "resume-output" | "stop-output" | "mute-output" | "unmute-output" | "notify-turn-speech-start" | "notify-turn-speech-completed" | "notify-turn-speech-stopped" | "notify-turn-interrupt";
25
+ export declare const VOICE_PLAYBACK_EFFECTS: readonly VoicePlaybackEffect[];
26
+ export declare function isVoicePlaybackEffect(value: unknown): value is VoicePlaybackEffect;
27
+ export declare function voicePlaybackAllowedForProfile(profile: VoiceProfile): boolean;
28
+ export declare function voicePlaybackInterruptAllowedForProfile(profile: VoiceProfile): boolean;
29
+ export declare function initialVoicePlaybackPhase(_profile: VoiceProfile): VoicePlaybackPhase;
30
+ export interface VoicePlaybackTurnSummary {
31
+ readonly schemaVersion: typeof VOICE_PLAYBACK_SCHEMA_VERSION;
32
+ readonly phase: VoicePlaybackPhase;
33
+ readonly available: boolean;
34
+ readonly spoke: boolean;
35
+ readonly completed: boolean;
36
+ readonly interrupted: boolean;
37
+ readonly failed: boolean;
38
+ readonly interruptions: number;
39
+ readonly replays: number;
40
+ readonly failureKind?: VoicePlaybackFailureKind | undefined;
41
+ }
42
+ export declare function summarizeVoicePlaybackTurn(input: {
43
+ readonly phase: VoicePlaybackPhase;
44
+ readonly available: boolean;
45
+ readonly spoke: boolean;
46
+ readonly interruptions: number;
47
+ readonly replays: number;
48
+ readonly failureKind?: VoicePlaybackFailureKind | undefined;
49
+ }): VoicePlaybackTurnSummary;
50
+ //# sourceMappingURL=voice-playback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-playback.d.ts","sourceRoot":"","sources":["../src/voice-playback.ts"],"names":[],"mappings":"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"}