@pikku/core 0.12.80 → 0.12.83
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.
- package/CHANGELOG.md +345 -0
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/function/function-runner.js +2 -5
- package/dist/function/index.d.ts +1 -1
- package/dist/index.d.ts +11 -11
- package/dist/index.js +3 -3
- package/dist/pikku-state.js +4 -0
- package/dist/services/ai-agent-runner-service.d.ts +7 -0
- package/dist/services/ai-run-state-service.d.ts +10 -0
- package/dist/services/in-memory-ai-run-state-service.d.ts +5 -1
- package/dist/services/in-memory-ai-run-state-service.js +9 -0
- package/dist/services/index.d.ts +15 -16
- package/dist/services/index.js +5 -5
- package/dist/services/meta-service.d.ts +2 -1
- package/dist/services/scoped-credential-service.d.ts +21 -0
- package/dist/services/scoped-credential-service.js +53 -0
- package/dist/testing/service-tests/ai-storage-service-tests.js +76 -0
- package/dist/types/core.types.d.ts +2 -3
- package/dist/types/state.types.d.ts +19 -1
- package/dist/wirings/actor-flow/index.d.ts +1 -1
- package/dist/wirings/ai-agent/ai-agent-finalize.d.ts +58 -0
- package/dist/wirings/ai-agent/ai-agent-finalize.js +138 -0
- package/dist/wirings/ai-agent/ai-agent-interrupt.js +1 -0
- package/dist/wirings/ai-agent/ai-agent-memory.d.ts +2 -8
- package/dist/wirings/ai-agent/ai-agent-memory.js +34 -17
- package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +7 -0
- package/dist/wirings/ai-agent/ai-agent-model-config.js +44 -1
- package/dist/wirings/ai-agent/ai-agent-prepare.js +4 -0
- package/dist/wirings/ai-agent/ai-agent-runner.js +61 -40
- package/dist/wirings/ai-agent/ai-agent-stream.js +89 -36
- package/dist/wirings/ai-agent/ai-agent-turn.d.ts +1 -0
- package/dist/wirings/ai-agent/ai-agent-turn.js +1 -0
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +46 -1
- package/dist/wirings/ai-agent/index.d.ts +8 -7
- package/dist/wirings/ai-agent/index.js +5 -4
- package/dist/wirings/ai-scorer/ai-scorer-grade.d.ts +26 -0
- package/dist/wirings/ai-scorer/ai-scorer-grade.js +33 -0
- package/dist/wirings/ai-scorer/ai-scorer-judge.d.ts +17 -0
- package/dist/wirings/ai-scorer/ai-scorer-judge.js +92 -0
- package/dist/wirings/ai-scorer/ai-scorer-live.d.ts +15 -0
- package/dist/wirings/ai-scorer/ai-scorer-live.js +38 -0
- package/dist/wirings/ai-scorer/ai-scorer-registry.d.ts +18 -0
- package/dist/wirings/ai-scorer/ai-scorer-registry.js +46 -0
- package/dist/wirings/ai-scorer/ai-scorer-sampling.d.ts +8 -0
- package/dist/wirings/ai-scorer/ai-scorer-sampling.js +31 -0
- package/dist/wirings/ai-scorer/ai-scorer-snapshots.d.ts +10 -0
- package/dist/wirings/ai-scorer/ai-scorer-snapshots.js +40 -0
- package/dist/wirings/ai-scorer/ai-scorer-worker.d.ts +15 -0
- package/dist/wirings/ai-scorer/ai-scorer-worker.js +58 -0
- package/dist/wirings/ai-scorer/ai-scorer.d.ts +39 -0
- package/dist/wirings/ai-scorer/ai-scorer.js +40 -0
- package/dist/wirings/ai-scorer/ai-scorer.types.d.ts +90 -0
- package/dist/wirings/ai-scorer/ai-scorer.types.js +4 -0
- package/dist/wirings/ai-scorer/index.d.ts +6 -0
- package/dist/wirings/ai-scorer/index.js +5 -0
- package/dist/wirings/channel/index.d.ts +5 -6
- package/dist/wirings/channel/index.js +3 -4
- package/dist/wirings/channel/local/local-channel-runner.js +8 -1
- package/dist/wirings/cli/channel/cli-raw-channel-runner.js +9 -1
- package/dist/wirings/cli/channel/index.d.ts +1 -2
- package/dist/wirings/cli/channel/index.js +0 -1
- package/dist/wirings/cli/cli-runner.js +13 -1
- package/dist/wirings/credential/index.d.ts +1 -1
- package/dist/wirings/gateway/index.d.ts +1 -1
- package/dist/wirings/http/http-runner.js +8 -2
- package/dist/wirings/http/index.d.ts +1 -2
- package/dist/wirings/mcp/index.d.ts +1 -1
- package/dist/wirings/mcp/mcp-runner.d.ts +15 -0
- package/dist/wirings/mcp/mcp-runner.js +18 -5
- package/dist/wirings/persona/index.d.ts +3 -4
- package/dist/wirings/persona/index.js +2 -3
- package/dist/wirings/queue/index.d.ts +1 -3
- package/dist/wirings/queue/index.js +1 -3
- package/dist/wirings/rpc/addon-runner.d.ts +8 -0
- package/dist/wirings/rpc/addon-runner.js +31 -3
- package/dist/wirings/rpc/rpc-runner.js +4 -0
- package/dist/wirings/rpc/rpc-types.d.ts +8 -0
- package/dist/wirings/rpc/wire-addon.d.ts +25 -0
- package/dist/wirings/rpc/wire-addon.js +8 -0
- package/dist/wirings/scheduler/index.d.ts +1 -1
- package/dist/wirings/trigger/index.d.ts +1 -1
- package/dist/wirings/virtual-user/index.d.ts +5 -6
- package/dist/wirings/virtual-user/index.js +2 -4
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +85 -15
- package/dist/wirings/workflow/feature.d.ts +2 -1
- package/dist/wirings/workflow/index.d.ts +5 -16
- package/dist/wirings/workflow/index.js +1 -9
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +17 -7
- package/dist/wirings/workflow/pikku-scenario-service.js +48 -13
- package/dist/wirings/workflow/pikku-workflow-service.js +17 -3
- package/dist/wirings/workflow/scenario-step.types.d.ts +8 -0
- package/dist/wirings/workflow/scenario.types.d.ts +37 -0
- package/dist/wirings/workflow/workflow-approval-audit.d.ts +16 -0
- package/dist/wirings/workflow/workflow-approval-audit.js +40 -0
- package/dist/wirings/workflow/workflow-approval-policy.d.ts +20 -0
- package/dist/wirings/workflow/workflow-approval-policy.js +48 -0
- package/dist/wirings/workflow/workflow-approval.d.ts +29 -1
- package/dist/wirings/workflow/workflow-approval.js +65 -2
- package/dist/wirings/workflow/workflow-run-ownership.d.ts +2 -1
- package/dist/wirings/workflow/workflow-run-ownership.js +2 -1
- package/dist/wirings/workflow/workflow.types.d.ts +2 -37
- package/knowledge/decisions/internals/addon-pikku-meta-ships-at-the-package-root-or-under-dist.md +32 -0
- package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +39 -0
- package/knowledge/decisions/internals/index.md +30 -3
- package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +115 -0
- package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +37 -0
- package/knowledge/decisions/security/a-workflow-run-is-read-and-approved-by-its-owner.md +30 -14
- package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +59 -0
- package/knowledge/decisions/security/index.md +3 -1
- package/knowledge/questions/index.md +1 -1
- package/package.json +3 -2
- package/scripts/generate-api-report.mts +143 -18
- package/src/api-report.test.ts +2 -2
- package/src/errors/index.ts +1 -1
- package/src/function/function-runner.test.ts +52 -0
- package/src/function/function-runner.ts +5 -9
- package/src/function/index.ts +0 -2
- package/src/index.ts +0 -35
- package/src/pikku-state.ts +5 -0
- package/src/public-surface.json +81 -118
- package/src/services/ai-agent-runner-service.ts +12 -1
- package/src/services/ai-run-state-service.ts +11 -0
- package/src/services/in-memory-ai-run-state-service.ts +13 -0
- package/src/services/index.ts +7 -58
- package/src/services/meta-service.ts +2 -4
- package/src/services/scoped-credential-service.test.ts +86 -0
- package/src/services/scoped-credential-service.ts +63 -0
- package/src/testing/service-tests/ai-storage-service-tests.ts +93 -0
- package/src/types/core.types.ts +4 -7
- package/src/types/state.types.ts +21 -1
- package/src/wirings/actor-flow/index.ts +0 -3
- package/src/wirings/ai-agent/ai-agent-finalize.test.ts +186 -0
- package/src/wirings/ai-agent/ai-agent-finalize.ts +197 -0
- package/src/wirings/ai-agent/ai-agent-interrupt.ts +1 -0
- package/src/wirings/ai-agent/ai-agent-memory.ts +54 -38
- package/src/wirings/ai-agent/ai-agent-model-config.test.ts +72 -3
- package/src/wirings/ai-agent/ai-agent-model-config.ts +49 -1
- package/src/wirings/ai-agent/ai-agent-prepare.ts +4 -0
- package/src/wirings/ai-agent/ai-agent-runner.ts +71 -40
- package/src/wirings/ai-agent/ai-agent-stream-output-hooks.test.ts +353 -0
- package/src/wirings/ai-agent/ai-agent-stream.ts +116 -54
- package/src/wirings/ai-agent/ai-agent-turn.test.ts +67 -0
- package/src/wirings/ai-agent/ai-agent-turn.ts +1 -0
- package/src/wirings/ai-agent/ai-agent.types.ts +64 -4
- package/src/wirings/ai-agent/index.ts +2 -16
- package/src/wirings/ai-scorer/ai-scorer-grade.test.ts +106 -0
- package/src/wirings/ai-scorer/ai-scorer-grade.ts +55 -0
- package/src/wirings/ai-scorer/ai-scorer-judge.test.ts +143 -0
- package/src/wirings/ai-scorer/ai-scorer-judge.ts +120 -0
- package/src/wirings/ai-scorer/ai-scorer-live.test.ts +174 -0
- package/src/wirings/ai-scorer/ai-scorer-live.ts +56 -0
- package/src/wirings/ai-scorer/ai-scorer-registry.ts +63 -0
- package/src/wirings/ai-scorer/ai-scorer-sampling.test.ts +34 -0
- package/src/wirings/ai-scorer/ai-scorer-sampling.ts +36 -0
- package/src/wirings/ai-scorer/ai-scorer-snapshots.test.ts +49 -0
- package/src/wirings/ai-scorer/ai-scorer-snapshots.ts +46 -0
- package/src/wirings/ai-scorer/ai-scorer-worker.test.ts +122 -0
- package/src/wirings/ai-scorer/ai-scorer-worker.ts +69 -0
- package/src/wirings/ai-scorer/ai-scorer.ts +76 -0
- package/src/wirings/ai-scorer/ai-scorer.types.ts +107 -0
- package/src/wirings/ai-scorer/index.ts +24 -0
- package/src/wirings/channel/index.ts +1 -20
- package/src/wirings/channel/local/local-channel-runner.test.ts +68 -0
- package/src/wirings/channel/local/local-channel-runner.ts +8 -1
- package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +23 -0
- package/src/wirings/cli/channel/cli-raw-channel-runner.ts +12 -1
- package/src/wirings/cli/channel/index.ts +0 -7
- package/src/wirings/cli/cli-runner.test.ts +68 -0
- package/src/wirings/cli/cli-runner.ts +18 -1
- package/src/wirings/credential/index.ts +0 -1
- package/src/wirings/gateway/index.ts +0 -3
- package/src/wirings/http/http-runner.test.ts +66 -0
- package/src/wirings/http/http-runner.ts +10 -2
- package/src/wirings/http/index.ts +1 -1
- package/src/wirings/mcp/index.ts +0 -1
- package/src/wirings/mcp/mcp-runner.test.ts +181 -0
- package/src/wirings/mcp/mcp-runner.ts +35 -5
- package/src/wirings/persona/index.ts +0 -8
- package/src/wirings/queue/index.ts +0 -14
- package/src/wirings/rpc/addon-runner.ts +62 -3
- package/src/wirings/rpc/addon-secrets.test.ts +391 -0
- package/src/wirings/rpc/rpc-runner.test.ts +2 -0
- package/src/wirings/rpc/rpc-runner.ts +4 -0
- package/src/wirings/rpc/rpc-types.ts +8 -0
- package/src/wirings/rpc/wire-addon.ts +33 -0
- package/src/wirings/scheduler/index.ts +0 -1
- package/src/wirings/trigger/index.ts +0 -1
- package/src/wirings/virtual-user/index.ts +0 -16
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +96 -16
- package/src/wirings/workflow/feature.ts +2 -5
- package/src/wirings/workflow/graph/graph-runner.test.ts +72 -0
- package/src/wirings/workflow/index.ts +2 -68
- package/src/wirings/workflow/pikku-scenario-service.ts +81 -16
- package/src/wirings/workflow/pikku-workflow-service.test.ts +13 -12
- package/src/wirings/workflow/pikku-workflow-service.ts +28 -4
- package/src/wirings/workflow/scenario-expectations.test.ts +75 -0
- package/src/wirings/workflow/scenario-hooks.test.ts +3 -2
- package/src/wirings/workflow/scenario-step.types.ts +8 -0
- package/src/wirings/workflow/scenario.types.ts +63 -0
- package/src/wirings/workflow/workflow-approval-audit.ts +47 -0
- package/src/wirings/workflow/workflow-approval-policy.test.ts +524 -0
- package/src/wirings/workflow/workflow-approval-policy.ts +68 -0
- package/src/wirings/workflow/workflow-approval.ts +113 -9
- package/src/wirings/workflow/workflow-run-authority.test.ts +12 -15
- package/src/wirings/workflow/workflow-run-ownership.ts +2 -1
- package/src/wirings/workflow/workflow.types.ts +1 -63
- package/src/wirings-stay-decoupled.test.ts +6 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/internal.d.ts +0 -3
- package/dist/internal.js +0 -2
- package/dist/middleware/timeout.d.ts +0 -9
- package/dist/middleware/timeout.js +0 -15
- package/dist/pikku-response.d.ts +0 -6
- package/dist/pikku-response.js +0 -6
- package/dist/services/gopass-secrets.d.ts +0 -15
- package/dist/services/gopass-secrets.js +0 -76
- package/dist/services/http-scenario-actors.d.ts +0 -75
- package/dist/services/http-scenario-actors.js +0 -195
- package/dist/services/http-user-flow-actors.d.ts +0 -67
- package/dist/services/http-user-flow-actors.js +0 -193
- package/dist/services/scenario-actors-service.d.ts +0 -127
- package/dist/services/scenario-actors-service.js +0 -40
- package/dist/services/user-flow-actors-service.d.ts +0 -39
- package/dist/wirings/credential/wire-credential.d.ts +0 -48
- package/dist/wirings/credential/wire-credential.js +0 -47
- package/dist/wirings/oauth2/oauth2-client.d.ts +0 -47
- package/dist/wirings/oauth2/oauth2-client.js +0 -263
- package/dist/wirings/oauth2/oauth2-routes.d.ts +0 -35
- package/dist/wirings/oauth2/oauth2-routes.js +0 -146
- package/dist/wirings/scope/wire-scope.d.ts +0 -33
- package/dist/wirings/scope/wire-scope.js +0 -32
- package/dist/wirings/workflow/dsl/index.d.ts +0 -5
- package/dist/wirings/workflow/dsl/index.js +0 -4
- package/dist/wirings/workflow/graph/index.d.ts +0 -5
- package/dist/wirings/workflow/graph/index.js +0 -4
- /package/dist/{services/user-flow-actors-service.js → wirings/workflow/scenario.types.js} +0 -0
|
@@ -146,3 +146,78 @@ describe('workflow.expectService', () => {
|
|
|
146
146
|
)
|
|
147
147
|
})
|
|
148
148
|
})
|
|
149
|
+
|
|
150
|
+
describe('workflow.expectScore', () => {
|
|
151
|
+
beforeEach(() => resetPikkuState())
|
|
152
|
+
|
|
153
|
+
const grades = (grade: { score: number; reason?: string }) => ({
|
|
154
|
+
rpcWithWire: async (rpcName: string, data: any) => {
|
|
155
|
+
assert.equal(rpcName, 'pikkuScenarioGradeRun')
|
|
156
|
+
assert.equal(data.runId, 'run-1')
|
|
157
|
+
return grade
|
|
158
|
+
},
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('returns the grade when the score clears the bound', async () => {
|
|
162
|
+
const { wire } = await scenarioWire(grades({ score: 0.9 }))
|
|
163
|
+
|
|
164
|
+
const grade = await wire.expectScore('was brief', 'run-1', 'brevity', {
|
|
165
|
+
atLeast: 0.8,
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
assert.equal(grade.score, 0.9)
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
test('a scorer that graded zero fails without a bound being stated', async () => {
|
|
172
|
+
const { wire } = await scenarioWire(grades({ score: 0 }))
|
|
173
|
+
|
|
174
|
+
await assert.rejects(
|
|
175
|
+
wire.expectScore('was brief', 'run-1', 'brevity', { retries: 0 }),
|
|
176
|
+
/expected 'brevity' to grade run run-1 at least 0\.5, got 0/
|
|
177
|
+
)
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
test('the failure carries the reason the judge gave', async () => {
|
|
181
|
+
const { wire } = await scenarioWire(
|
|
182
|
+
grades({ score: 0.2, reason: 'It rambled for four paragraphs' })
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
await assert.rejects(
|
|
186
|
+
wire.expectScore('was brief', 'run-1', 'brevity', {
|
|
187
|
+
atLeast: 0.8,
|
|
188
|
+
retries: 0,
|
|
189
|
+
}),
|
|
190
|
+
/It rambled for four paragraphs/
|
|
191
|
+
)
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
test('atMost fails a score that is too high', async () => {
|
|
195
|
+
const { wire } = await scenarioWire(grades({ score: 0.95 }))
|
|
196
|
+
|
|
197
|
+
await assert.rejects(
|
|
198
|
+
wire.expectScore('was not sycophantic', 'run-1', 'sycophancy', {
|
|
199
|
+
atLeast: 0,
|
|
200
|
+
atMost: 0.3,
|
|
201
|
+
retries: 0,
|
|
202
|
+
}),
|
|
203
|
+
/between 0 and 0\.3, got 0\.95/
|
|
204
|
+
)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
test('a reference answer reaches the grader', async () => {
|
|
208
|
+
let seen: any
|
|
209
|
+
const { wire } = await scenarioWire({
|
|
210
|
+
rpcWithWire: async (_rpcName: string, data: any) => {
|
|
211
|
+
seen = data
|
|
212
|
+
return { score: 1 }
|
|
213
|
+
},
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
await wire.expectScore('matched the answer key', 'run-1', 'correctness', {
|
|
217
|
+
reference: 'Paris',
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
assert.equal(seen.reference, 'Paris')
|
|
221
|
+
assert.equal(seen.scorer, 'correctness')
|
|
222
|
+
})
|
|
223
|
+
})
|
|
@@ -185,8 +185,9 @@ describe('scenario before/after hooks', () => {
|
|
|
185
185
|
})
|
|
186
186
|
|
|
187
187
|
test('after reads what the body wrote to the scenario context', async () => {
|
|
188
|
-
// The reason the context exists:
|
|
189
|
-
//
|
|
188
|
+
// The reason the context exists: a hook's `data` is only ever the run's
|
|
189
|
+
// *input*, never what the body produced. The context is the channel the
|
|
190
|
+
// body writes that through, and it reaches the hook on the shared wire.
|
|
190
191
|
let seen: any
|
|
191
192
|
await runScenario('contextHandover', {
|
|
192
193
|
after: async (_services, _data, wire) => {
|
|
@@ -229,6 +229,14 @@ export interface ScenarioBrowserProvider {
|
|
|
229
229
|
* scenario cannot leave the next signed in as somebody else.
|
|
230
230
|
*/
|
|
231
231
|
reset?(): Promise<void>
|
|
232
|
+
/**
|
|
233
|
+
* Name the scenario about to run, so anything it captures is filed under it.
|
|
234
|
+
*
|
|
235
|
+
* Called before each scenario. A provider that is never told has to fall
|
|
236
|
+
* back to one shared label, which puts every run's artifacts in a single
|
|
237
|
+
* folder — findable only by timestamp.
|
|
238
|
+
*/
|
|
239
|
+
beginScenario?(scenario: string): void
|
|
232
240
|
/**
|
|
233
241
|
* Snapshot every open window for a failed scenario. `label` identifies the
|
|
234
242
|
* scenario in artifact filenames. Never throws: a failure to capture must
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CorePikkuFunctionConfig,
|
|
3
|
+
CorePikkuFunctionHook,
|
|
4
|
+
} from '../../function/functions.types.js'
|
|
5
|
+
|
|
6
|
+
export type {
|
|
7
|
+
ScenarioStepInvocation,
|
|
8
|
+
ScenarioStepMeta,
|
|
9
|
+
PikkuScenarioWire,
|
|
10
|
+
} from './dsl/workflow-dsl.types.js'
|
|
11
|
+
|
|
12
|
+
export type {
|
|
13
|
+
ScenarioStepPhase,
|
|
14
|
+
ScenarioStepKind,
|
|
15
|
+
ScenarioStepOptions,
|
|
16
|
+
PikkuScenarioStepWire,
|
|
17
|
+
ScenarioEnvironment,
|
|
18
|
+
ScenarioSurface,
|
|
19
|
+
ScenarioSurfaceResolution,
|
|
20
|
+
PikkuBrowserWire,
|
|
21
|
+
TestIdSelector,
|
|
22
|
+
ScenarioBrowserProvider,
|
|
23
|
+
ScenarioBrowserFailure,
|
|
24
|
+
} from './scenario-step.types.js'
|
|
25
|
+
|
|
26
|
+
export type CoreFeatureScenario =
|
|
27
|
+
| CorePikkuFunctionConfig<any, any, any>
|
|
28
|
+
| { scenario: CorePikkuFunctionConfig<any, any, any>; data: unknown }
|
|
29
|
+
|
|
30
|
+
export type CoreFeature = {
|
|
31
|
+
name: string
|
|
32
|
+
description?: string
|
|
33
|
+
tags?: string[]
|
|
34
|
+
scenarios: readonly CoreFeatureScenario[]
|
|
35
|
+
before?: CorePikkuFunctionHook
|
|
36
|
+
after?: CorePikkuFunctionHook
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type FeatureMetaEntry = {
|
|
40
|
+
scenario: string
|
|
41
|
+
data?: unknown
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type FeatureMeta = {
|
|
45
|
+
id: string
|
|
46
|
+
name: string
|
|
47
|
+
description?: string
|
|
48
|
+
tags: string[]
|
|
49
|
+
entries: FeatureMetaEntry[]
|
|
50
|
+
unresolvedEntries: number
|
|
51
|
+
hasBefore: boolean
|
|
52
|
+
hasAfter: boolean
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type FeaturesMeta = Record<string, FeatureMeta>
|
|
56
|
+
|
|
57
|
+
export type FeaturePlanEntry = {
|
|
58
|
+
featureId: string
|
|
59
|
+
featureName: string
|
|
60
|
+
scenarioName: string
|
|
61
|
+
data?: unknown
|
|
62
|
+
tags: string[]
|
|
63
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getSingletonServices } from '../../pikku-state.js'
|
|
2
|
+
import type { ApprovalAuditEvent } from './workflow-approval.js'
|
|
3
|
+
|
|
4
|
+
/** The audit type an answer to an approval gate is recorded under. */
|
|
5
|
+
export const APPROVAL_AUDIT_TYPE = 'workflow.approval.decided'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Record an answer to an approval gate where it outlives the run.
|
|
9
|
+
*
|
|
10
|
+
* The step result carries the settled decision, but it is deleted with the run
|
|
11
|
+
* — `deleteRun` cascades to steps and to history — and a refused attempt never
|
|
12
|
+
* reaches a step at all. An approval is asked for precisely so it can be
|
|
13
|
+
* answered for afterwards, so the answer also goes to the audit sink, which
|
|
14
|
+
* holds no foreign key to the run.
|
|
15
|
+
*
|
|
16
|
+
* A project with no sink wired records nothing, and a sink that fails is logged
|
|
17
|
+
* rather than thrown: the trail must not be the reason a decision is lost.
|
|
18
|
+
*/
|
|
19
|
+
export const auditApprovalDecision = async (
|
|
20
|
+
event: ApprovalAuditEvent
|
|
21
|
+
): Promise<void> => {
|
|
22
|
+
const services = getSingletonServices()
|
|
23
|
+
if (!services?.audit) {
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
await services.audit.audit({
|
|
28
|
+
type: APPROVAL_AUDIT_TYPE,
|
|
29
|
+
source: 'explicit',
|
|
30
|
+
outcome: event.outcome,
|
|
31
|
+
occurredAt: new Date().toISOString(),
|
|
32
|
+
wireType: 'workflow',
|
|
33
|
+
userIdentity: { pikkuUserId: event.decidedBy?.userId },
|
|
34
|
+
metadata: {
|
|
35
|
+
runId: event.runId,
|
|
36
|
+
reason: event.reason,
|
|
37
|
+
scopes: event.decidedBy?.scopes,
|
|
38
|
+
refusal: event.refusal,
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
} catch (error) {
|
|
42
|
+
services.logger?.warn(
|
|
43
|
+
`Failed to audit the decision on approval '${event.reason}' for run ${event.runId}`,
|
|
44
|
+
error
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
}
|