@felspar/sdk 0.2.0 → 0.2.1

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.
@@ -2,8 +2,8 @@ import {
2
2
  denialText,
3
3
  entityIdOf,
4
4
  jobOf
5
- } from "./chunks/chunk-IY6A2423.js";
6
- import "./chunks/chunk-HACK7D24.js";
5
+ } from "./chunks/chunk-Y6KRRIQI.js";
6
+ import "./chunks/chunk-XLKRU5RA.js";
7
7
 
8
8
  // src/draft-action-gate-claude.ts
9
9
  function felsparPreToolUse(gate) {
@@ -31,9 +31,9 @@ function felsparPostToolUse(gate) {
31
31
  if (job !== void 0 && input.hook_event_name === "PostToolUse" && gate.isOutputCheckTool(input.tool_name ?? "")) {
32
32
  gate.decisions.recordOutputCheck(input.session_id, job, input.tool_response);
33
33
  }
34
- const entity = entityIdOf(input.tool_input);
35
- if (entity !== void 0 && input.hook_event_name === "PostToolUse" && gate.isDecisionTool(input.tool_name ?? "")) {
36
- gate.decisions.record(input.session_id, entity, input.tool_response);
34
+ if (input.hook_event_name === "PostToolUse" && gate.isDecisionTool(input.tool_name ?? "")) {
35
+ const entity = entityIdOf(input.tool_input);
36
+ gate.decisions.record(input.session_id, { entity, job }, input.tool_response);
37
37
  }
38
38
  return {};
39
39
  };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  felsparDecisionEvents,
3
3
  felsparGate
4
- } from "./chunks/chunk-247XZ6IY.js";
5
- import "./chunks/chunk-IY6A2423.js";
6
- import "./chunks/chunk-HACK7D24.js";
4
+ } from "./chunks/chunk-B4BWUYQY.js";
5
+ import "./chunks/chunk-Y6KRRIQI.js";
6
+ import "./chunks/chunk-XLKRU5RA.js";
7
7
  export {
8
8
  felsparDecisionEvents,
9
9
  felsparGate
@@ -2,8 +2,8 @@ import {
2
2
  denialText,
3
3
  entityIdOf,
4
4
  jobOf
5
- } from "./chunks/chunk-IY6A2423.js";
6
- import "./chunks/chunk-HACK7D24.js";
5
+ } from "./chunks/chunk-Y6KRRIQI.js";
6
+ import "./chunks/chunk-XLKRU5RA.js";
7
7
 
8
8
  // src/draft-action-gate-openai.ts
9
9
  function argumentsOf(text) {
@@ -47,9 +47,9 @@ function felsparDecisionOutputGuardrail(gate, options) {
47
47
  if (job !== void 0 && gate.isOutputCheckTool(data.toolCall.name)) {
48
48
  gate.decisions.recordOutputCheck(options.sessionOf(data.context), job, data.output);
49
49
  }
50
- const entity = entityIdOf(input);
51
- if (entity !== void 0 && gate.isDecisionTool(data.toolCall.name)) {
52
- gate.decisions.record(options.sessionOf(data.context), entity, data.output);
50
+ if (gate.isDecisionTool(data.toolCall.name)) {
51
+ const session = options.sessionOf(data.context);
52
+ gate.decisions.record(session, { entity: entityIdOf(input), job }, data.output);
53
53
  }
54
54
  return { behavior: { type: "allow" } };
55
55
  }
@@ -16,8 +16,8 @@ import {
16
16
  outputCheckFromResult,
17
17
  outputTextDigest,
18
18
  sharedDomains
19
- } from "./chunks/chunk-IY6A2423.js";
20
- import "./chunks/chunk-HACK7D24.js";
19
+ } from "./chunks/chunk-Y6KRRIQI.js";
20
+ import "./chunks/chunk-XLKRU5RA.js";
21
21
  export {
22
22
  checkAction,
23
23
  createActionGate,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  FelsparRequestError,
3
3
  createHostedFelsparClient
4
- } from "./chunks/chunk-HACK7D24.js";
4
+ } from "./chunks/chunk-XLKRU5RA.js";
5
5
  export {
6
6
  FelsparRequestError,
7
7
  createHostedFelsparClient
package/dist/eve.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  felsparDecisionEvents,
3
3
  felsparGate
4
- } from "./chunks/chunk-247XZ6IY.js";
5
- import "./chunks/chunk-IY6A2423.js";
6
- import "./chunks/chunk-HACK7D24.js";
4
+ } from "./chunks/chunk-B4BWUYQY.js";
5
+ import "./chunks/chunk-Y6KRRIQI.js";
6
+ import "./chunks/chunk-XLKRU5RA.js";
7
7
 
8
8
  // src/eve.ts
9
9
  var felsparMcpUrl = "https://mcp.felspar.ai/mcp";
@@ -26,5 +26,6 @@ export interface Found {
26
26
  export declare const foldCase: (text: string) => string;
27
27
  export declare const caseKeyOf: (rule: CaseRule) => (text: string) => string;
28
28
  export declare const sameField: (names: readonly string[]) => (field: string) => boolean;
29
+ export declare function testListProblem(scope: Pick<CaseScope, "rules" | "rule">, input: Input): string | null;
29
30
  export declare function caseFor(scope: CaseScope, input: Input): Found;
30
31
  export {};
@@ -1,6 +1,23 @@
1
1
  import type { FelsparOutputCheck } from "./draft-action-gate-outputs.js";
2
+ declare const identityModes: readonly ["provided", "fields", "content", "issued"];
3
+ export type IdentityMode = (typeof identityModes)[number];
4
+ declare const escalationTriggers: readonly ["outcome", "unresolved", "attempt_limit"];
5
+ export type EscalationTrigger = (typeof escalationTriggers)[number];
6
+ export interface FelsparCase {
7
+ id: string;
8
+ mode: IdentityMode;
9
+ }
10
+ export interface FelsparEscalation {
11
+ id: string;
12
+ trigger: EscalationTrigger;
13
+ why: string;
14
+ }
2
15
  export interface FelsparDecision {
3
16
  entity: string;
17
+ case?: FelsparCase | undefined;
18
+ job?: string | undefined;
19
+ releaseId?: string | undefined;
20
+ escalation?: FelsparEscalation | undefined;
4
21
  outcome: string;
5
22
  executionObjectId: string;
6
23
  receipt: {
@@ -14,16 +31,28 @@ export interface VerifiedDecision {
14
31
  entityId: string;
15
32
  releaseId?: string;
16
33
  outcome: string | null;
34
+ case?: {
35
+ id: string;
36
+ mode: string;
37
+ } | undefined;
38
+ escalation?: {
39
+ id: string;
40
+ trigger: string;
41
+ } | undefined;
17
42
  }
18
43
  export type ReceiptVerifier = (decision: FelsparDecision) => Promise<VerifiedDecision | null>;
19
44
  export declare function jobOf(input: unknown): string | undefined;
20
45
  export declare function entityIdOf(input: unknown): string | undefined;
21
- export declare function decisionFromResult(entity: string, output: unknown): FelsparDecision | null;
46
+ export type DecisionRequest = string | {
47
+ entity?: string | undefined;
48
+ job?: string | undefined;
49
+ };
50
+ export declare function decisionFromResult(request: DecisionRequest, output: unknown): FelsparDecision | null;
22
51
  export interface DecisionRecorder {
23
52
  recordOutputCheck: (sessionId: string, jobId: string, output: unknown) => FelsparOutputCheck | null;
24
53
  outputChecksIn: (sessionId: string) => readonly FelsparOutputCheck[];
25
- record: (sessionId: string, entity: string, output: unknown) => FelsparDecision | null;
26
- noteRequest: (callId: string, entity: string) => void;
54
+ record: (sessionId: string, request: DecisionRequest, output: unknown) => FelsparDecision | null;
55
+ noteRequest: (callId: string, request: DecisionRequest) => void;
27
56
  noteResult: (sessionId: string, callId: string, output: unknown) => FelsparDecision | null;
28
57
  decisionsIn: (sessionId: string) => readonly FelsparDecision[];
29
58
  forget: (sessionId: string) => void;
@@ -34,3 +63,4 @@ export interface DecisionRecorderLimits {
34
63
  pendingRequests?: number;
35
64
  }
36
65
  export declare function createDecisionRecorder(limits?: DecisionRecorderLimits): DecisionRecorder;
66
+ export {};
@@ -1,3 +1,4 @@
1
+ import type { EscalationTrigger, IdentityMode } from "./draft-action-gate-decisions.js";
1
2
  interface Quoted {
2
3
  text: string;
3
4
  }
@@ -6,13 +7,28 @@ export interface GateJobDescription {
6
7
  release: {
7
8
  releaseId: string;
8
9
  };
10
+ subject?: {
11
+ type: string;
12
+ match: "exact" | "case-insensitive";
13
+ } | undefined;
14
+ identity?: {
15
+ mode: IdentityMode;
16
+ } | undefined;
9
17
  outcomes: readonly {
10
18
  id: string;
11
19
  nextStep?: Quoted | null | undefined;
12
20
  outputs?: readonly {
13
21
  id: string;
14
22
  }[] | undefined;
23
+ escalate?: string | undefined;
15
24
  }[];
25
+ escalations?: {
26
+ routes: readonly {
27
+ id: string;
28
+ quote: Quoted;
29
+ }[];
30
+ unresolved: string | null;
31
+ } | undefined;
16
32
  whenUnresolved?: Quoted | null | undefined;
17
33
  }
18
34
  export type JobDescriber = (releaseId: string, jobId: string) => Promise<GateJobDescription>;
@@ -28,6 +44,16 @@ export declare function writesProblem(describe: JobDescriber | undefined, decide
28
44
  outcome: string;
29
45
  output: string;
30
46
  }): Promise<string | null>;
47
+ export declare function subjectOf(describe: JobDescriber, releaseId: string, jobId: string): Promise<{
48
+ type: string;
49
+ match: "exact" | "case-insensitive";
50
+ mode: "provided" | "fields" | "content" | "issued";
51
+ } | null>;
52
+ export interface GateEscalation {
53
+ id: string;
54
+ trigger: EscalationTrigger;
55
+ why: string | null;
56
+ }
31
57
  export type EscalationStep = {
32
58
  kind: "unresolved";
33
59
  releaseId: string | undefined;
@@ -35,9 +61,21 @@ export type EscalationStep = {
35
61
  kind: "outcome";
36
62
  releaseId: string | undefined;
37
63
  outcome: string;
64
+ replayed?: {
65
+ id: string;
66
+ trigger: string;
67
+ } | undefined;
68
+ recorded?: {
69
+ id: string;
70
+ why: string;
71
+ } | undefined;
38
72
  } | {
39
73
  kind: "output-check";
40
74
  };
41
75
  export declare const fixOutputCheck = "Fix what check_output flagged, check it again, then retry.";
42
- export declare function escalationFor(step: EscalationStep | undefined, describe: JobDescriber | undefined, jobId: string): Promise<string | null>;
76
+ export interface Escalated {
77
+ escalate?: string;
78
+ escalation?: GateEscalation;
79
+ }
80
+ export declare function escalationFor(step: EscalationStep | undefined, describe: JobDescriber | undefined, jobId: string): Promise<Escalated>;
43
81
  export {};
@@ -0,0 +1,33 @@
1
+ import type { CaseRule, CaseRules } from "./draft-action-gate-cases.js";
2
+ import type { FelsparCase, FelsparDecision } from "./draft-action-gate-decisions.js";
3
+ import type { JobDescriber } from "./draft-action-gate-describe.js";
4
+ export interface GateSubject {
5
+ type: string;
6
+ match: "exact" | "case-insensitive";
7
+ mode: FelsparCase["mode"];
8
+ }
9
+ export interface CaseKeying {
10
+ key: (id: string) => string;
11
+ decisionKey: (decision: FelsparDecision) => string;
12
+ }
13
+ export type Selected = {
14
+ company: string;
15
+ decision: FelsparDecision;
16
+ keying: CaseKeying;
17
+ } | {
18
+ company?: undefined;
19
+ reason: string;
20
+ missing?: true;
21
+ };
22
+ interface SelectScope {
23
+ rules: CaseRules & {
24
+ job: string;
25
+ sharedDomains?: readonly string[];
26
+ };
27
+ rule: CaseRule;
28
+ decisions: readonly FelsparDecision[];
29
+ describe?: JobDescriber | undefined;
30
+ }
31
+ type Input = Record<string, unknown>;
32
+ export declare function selectCase(scope: SelectScope, input: Input): Promise<Selected>;
33
+ export {};
@@ -1,12 +1,12 @@
1
- import type { JobDescriber } from "./draft-action-gate-describe.js";
1
+ import type { GateEscalation, JobDescriber } from "./draft-action-gate-describe.js";
2
2
  import type { FelsparOutputCheck, OutputCheckVerifier } from "./draft-action-gate-outputs.js";
3
3
  import type { ActionRule } from "./draft-action-gate-rules.js";
4
4
  import type { DecisionRecorder, FelsparDecision, ReceiptVerifier } from "./draft-action-gate-decisions.js";
5
5
  export { emailRecipientFields, emailSubjectFields } from "./draft-action-gate-cases.js";
6
6
  export { createDecisionRecorder, decisionFromResult, entityIdOf, jobOf, } from "./draft-action-gate-decisions.js";
7
- export type { DecisionRecorder, DecisionRecorderLimits, FelsparDecision, ReceiptVerifier, VerifiedDecision, } from "./draft-action-gate-decisions.js";
7
+ export type { DecisionRecorder, DecisionRecorderLimits, DecisionRequest, EscalationTrigger, FelsparCase, FelsparDecision, FelsparEscalation, IdentityMode, ReceiptVerifier, VerifiedDecision, } from "./draft-action-gate-decisions.js";
8
8
  export { felsparJobDescriber } from "./draft-action-gate-describe.js";
9
- export type { GateJobDescription, JobDescriber } from "./draft-action-gate-describe.js";
9
+ export type { GateEscalation, GateJobDescription, JobDescriber, } from "./draft-action-gate-describe.js";
10
10
  export { isCompanyDomain, sharedDomains } from "./draft-action-gate-domains.js";
11
11
  export type { ActionRule } from "./draft-action-gate-rules.js";
12
12
  export { felsparVerifier } from "./draft-action-gate-verifier.js";
@@ -30,10 +30,12 @@ export type ActionVerdict = {
30
30
  allow: false;
31
31
  reason: string;
32
32
  escalate?: string;
33
+ escalation?: GateEscalation;
33
34
  };
34
35
  export declare function denialText(verdict: {
35
36
  reason: string;
36
37
  escalate?: string;
38
+ escalation?: GateEscalation;
37
39
  }): string;
38
40
  export declare function gatedRule(rules: ActionGateRules, toolName: string): ActionRule | undefined;
39
41
  export interface CheckActionRequest {
@@ -1,9 +1,143 @@
1
1
  import { z } from "zod";
2
+ declare const FelsparCaseSchema: z.ZodObject<{
3
+ id: z.ZodString;
4
+ mode: z.ZodEnum<{
5
+ provided: "provided";
6
+ fields: "fields";
7
+ content: "content";
8
+ issued: "issued";
9
+ }>;
10
+ }, z.core.$strip>;
11
+ declare const FelsparRelatedSchema: z.ZodObject<{
12
+ relationship: z.ZodString;
13
+ subject: z.ZodString;
14
+ id: z.ZodString;
15
+ questions: z.ZodArray<z.ZodString>;
16
+ }, z.core.$strip>;
17
+ declare const FelsparResultSubjectSchema: z.ZodObject<{
18
+ type: z.ZodString;
19
+ id: z.ZodString;
20
+ related: z.ZodArray<z.ZodObject<{
21
+ relationship: z.ZodString;
22
+ subject: z.ZodString;
23
+ id: z.ZodString;
24
+ questions: z.ZodArray<z.ZodString>;
25
+ }, z.core.$strip>>;
26
+ }, z.core.$strip>;
27
+ declare const FelsparEscalationSchema: z.ZodObject<{
28
+ id: z.ZodString;
29
+ trigger: z.ZodEnum<{
30
+ outcome: "outcome";
31
+ unresolved: "unresolved";
32
+ attempt_limit: "attempt_limit";
33
+ }>;
34
+ why: z.ZodObject<{
35
+ text: z.ZodString;
36
+ }, z.core.$loose>;
37
+ }, z.core.$strip>;
38
+ declare const FelsparJobResultSchema: z.ZodObject<{
39
+ status: z.ZodString;
40
+ reason: z.ZodNullable<z.ZodString>;
41
+ result: z.ZodNullable<z.ZodObject<{
42
+ executionId: z.ZodString;
43
+ releaseId: z.ZodString;
44
+ releaseDigest: z.ZodString;
45
+ outcome: z.ZodNullable<z.ZodString>;
46
+ scoring: z.ZodUnknown;
47
+ context: z.ZodUnknown;
48
+ receipt: z.ZodUnknown;
49
+ case: z.ZodOptional<z.ZodObject<{
50
+ id: z.ZodString;
51
+ mode: z.ZodEnum<{
52
+ provided: "provided";
53
+ fields: "fields";
54
+ content: "content";
55
+ issued: "issued";
56
+ }>;
57
+ }, z.core.$strip>>;
58
+ subject: z.ZodOptional<z.ZodObject<{
59
+ type: z.ZodString;
60
+ id: z.ZodString;
61
+ related: z.ZodArray<z.ZodObject<{
62
+ relationship: z.ZodString;
63
+ subject: z.ZodString;
64
+ id: z.ZodString;
65
+ questions: z.ZodArray<z.ZodString>;
66
+ }, z.core.$strip>>;
67
+ }, z.core.$strip>>;
68
+ escalation: z.ZodOptional<z.ZodObject<{
69
+ id: z.ZodString;
70
+ trigger: z.ZodEnum<{
71
+ outcome: "outcome";
72
+ unresolved: "unresolved";
73
+ attempt_limit: "attempt_limit";
74
+ }>;
75
+ why: z.ZodObject<{
76
+ text: z.ZodString;
77
+ }, z.core.$loose>;
78
+ }, z.core.$strip>>;
79
+ missing: z.ZodOptional<z.ZodArray<z.ZodString>>;
80
+ }, z.core.$loose>>;
81
+ }, z.core.$strip>;
82
+ export type FelsparJobResult = z.infer<typeof FelsparJobResultSchema>;
83
+ export type FelsparJobCase = z.infer<typeof FelsparCaseSchema>;
84
+ export type FelsparRelatedRecord = z.infer<typeof FelsparRelatedSchema>;
85
+ export type FelsparResultSubject = z.infer<typeof FelsparResultSubjectSchema>;
86
+ export type FelsparJobEscalation = z.infer<typeof FelsparEscalationSchema>;
87
+ interface QuotedWords {
88
+ text: string;
89
+ }
90
+ export interface FelsparJobSubject {
91
+ type: string;
92
+ definition: QuotedWords;
93
+ identifier?: string | undefined;
94
+ example?: string | undefined;
95
+ match: "exact" | "case-insensitive";
96
+ related: readonly {
97
+ relationship: string;
98
+ meaning: QuotedWords;
99
+ cardinality: "one" | "many";
100
+ required: boolean;
101
+ subject: string;
102
+ definition: QuotedWords;
103
+ identifier: string;
104
+ example: string;
105
+ match: "exact" | "case-insensitive";
106
+ }[];
107
+ send: string;
108
+ }
109
+ export interface FelsparJobIdentity {
110
+ mode: FelsparJobCase["mode"];
111
+ send: string;
112
+ fields?: readonly {
113
+ name: string;
114
+ identifier: string;
115
+ example: string;
116
+ match: string;
117
+ }[];
118
+ question?: string | undefined;
119
+ }
120
+ export interface FelsparFactsRequest {
121
+ jobId: string;
122
+ executionId: string;
123
+ expectedReleaseDigest?: string;
124
+ entityId?: string;
125
+ identity?: Record<string, string>;
126
+ related?: Record<string, string | string[]>;
127
+ facts: Record<string, unknown>;
128
+ }
129
+ declare const FelsparJobListSchema: z.ZodObject<{
130
+ jobs: z.ZodArray<z.ZodObject<{
131
+ id: z.ZodString;
132
+ }, z.core.$strip>>;
133
+ }, z.core.$strip>;
134
+ export type FelsparJobList = z.infer<typeof FelsparJobListSchema>;
2
135
  declare const refusalSchema: z.ZodPipe<z.ZodObject<{
3
136
  error: z.ZodString;
4
137
  path: z.ZodOptional<z.ZodArray<z.ZodString>>;
5
138
  currentReleaseDigest: z.ZodOptional<z.ZodString>;
6
139
  retryAfterSeconds: z.ZodOptional<z.ZodNumber>;
140
+ escalation: z.ZodOptional<z.ZodUnknown>;
7
141
  issues: z.ZodOptional<z.ZodArray<z.ZodObject<{
8
142
  code: z.ZodString;
9
143
  path: z.ZodArray<z.ZodString>;
@@ -14,6 +148,13 @@ declare const refusalSchema: z.ZodPipe<z.ZodObject<{
14
148
  path: string[];
15
149
  }[] | undefined;
16
150
  fix?: string;
151
+ escalation?: {
152
+ id: string;
153
+ trigger: "outcome" | "unresolved" | "attempt_limit";
154
+ why: {
155
+ text: string;
156
+ };
157
+ };
17
158
  error: string;
18
159
  path?: string[] | undefined;
19
160
  currentReleaseDigest?: string | undefined;
@@ -23,6 +164,7 @@ declare const refusalSchema: z.ZodPipe<z.ZodObject<{
23
164
  path?: string[] | undefined;
24
165
  currentReleaseDigest?: string | undefined;
25
166
  retryAfterSeconds?: number | undefined;
167
+ escalation?: unknown;
26
168
  issues?: {
27
169
  code: string;
28
170
  path: string[];
@@ -43,35 +185,14 @@ export declare function createHostedFelsparClient(configuration: {
43
185
  agentKey?: string;
44
186
  fetcher?: typeof fetch;
45
187
  }): {
46
- executeJob: (id: string, value: unknown) => Promise<{
47
- status: string;
48
- reason: string | null;
49
- result: {
50
- [x: string]: unknown;
51
- executionId: string;
52
- releaseId: string;
53
- releaseDigest: string;
54
- outcome: string | null;
55
- scoring: unknown;
56
- context: unknown;
57
- receipt: unknown;
58
- } | null;
59
- }>;
60
- resolveFacts: (id: string, value: Record<string, unknown>) => Promise<{
61
- status: string;
62
- reason: string | null;
63
- result: {
64
- [x: string]: unknown;
65
- executionId: string;
66
- releaseId: string;
67
- releaseDigest: string;
68
- outcome: string | null;
69
- scoring: unknown;
70
- context: unknown;
71
- receipt: unknown;
72
- } | null;
188
+ resolveFacts: (id: string, value: FelsparFactsRequest | Record<string, unknown>) => Promise<FelsparJobResult>;
189
+ listJobs: () => Promise<{
190
+ jobs: {
191
+ id: string;
192
+ }[];
73
193
  }>;
74
- resolveJob: (id: string, value: unknown) => Promise<{
194
+ resolveJob: (id: string, value: unknown) => Promise<FelsparJobResult>;
195
+ executeJob: (id: string, value: unknown) => Promise<{
75
196
  status: string;
76
197
  reason: string | null;
77
198
  result: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@felspar/sdk",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Client and action gate for Felspar, the shared decision system for enterprise agents.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://docs.felspar.ai",
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: felspar
3
- description: Use this skill when a task involves a Felspar job or a company decision about a case, such as evaluating, classifying or qualifying a company, routing or answering a support ticket, or deciding any other record by the company's approved rules. Load it when choosing which Felspar job fits a task; before gathering evidence or calling list_jobs, get_job_requirements, get_job_decision or check_output; before writing a reply or any other text for a decided case; before an action that follows a decision, such as a draft or a record update; and whenever a Felspar result comes back held, undecided, refused or with an escalation, or Felspar's action gate denies a call.
3
+ description: Use this skill when a task involves a Felspar job or a company decision about a case, such as evaluating, classifying or qualifying a company, routing or answering a support ticket, or deciding any other record by the company's approved rules. Load it when choosing which Felspar job fits a task; before gathering evidence or calling list_jobs, get_job_requirements, get_job_decision or check_output; before writing a reply or any other text for a decided case; before an action that follows a decision, such as a draft or a record update; and whenever a Felspar result comes back held, undecided, refused or with an escalation or a case ID to reuse, or Felspar's action gate denies a call or names an escalation.
4
4
  metadata:
5
- version: "0.2.0"
5
+ version: "0.2.1"
6
6
  ---
7
7
 
8
8
  # Working with Felspar
@@ -94,9 +94,10 @@ Show each output above the answer block: the final text, then one line with its
94
94
  Actions that follow a decision (an email draft, a ticket reply, a CRM update) may pass Felspar's action gate before they run. The gate checks, in code, that Felspar decided on the case the action is about, that the decided outcome allows the action (or lists the output it writes), that the receipt still verifies and, where required, that Felspar passed exactly the text being sent. So:
95
95
 
96
96
  - Act only on a decided outcome, and only as its next step says. A held or undecided case gets no action.
97
- - Name the case the way the tool expects. An email about a company goes to people at the company Felspar decided on, one company per email. An action on a record carries the record's ID exactly as you sent it as `entity_id`.
97
+ - Name the case the way the tool expects. An email about a company goes to people at the company Felspar decided on, one company per email. An action on a record carries the case's ID: `result.case.id` exactly when the result names a case (always for an issued, fields or content job), otherwise the record's ID exactly as you sent it as `entity_id`. Never put another case's ID on an action.
98
+ - Work one case at a time: when the tool has no field for the case ID, the gate binds the action to the one case you decided in this conversation.
98
99
  - Send exactly the text `check_output` passed, and set only the fields the tool needs; the gate denies anything else.
99
- - If the gate denies an action, don't retry or rephrase it to get around the gate. Report the reason. When the denial gives a `Next step:` (the company's own, quoted from the policy), do that instead; when it asks you to fix what `check_output` flagged, fix the text, check it again and only then retry; otherwise escalate.
100
+ - If the gate denies an action, don't retry or rephrase it to get around the gate. Report the reason. When the denial gives a `Next step:` (the company's own, quoted from the policy), do that instead; when it names an `Escalation <id>`, report that id exactly with its why and hand the case off; when it asks you to fix what `check_output` flagged, fix the text, check it again and only then retry; otherwise escalate.
100
101
 
101
102
  ## 5. Answer
102
103