@eddacraft/anvil-kindling-integration 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +14 -0
- package/README.md +542 -0
- package/dist/adapter.d.ts +49 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +100 -0
- package/dist/config.d.ts +89 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +173 -0
- package/dist/emitters/action-emitter.d.ts +40 -0
- package/dist/emitters/action-emitter.d.ts.map +1 -0
- package/dist/emitters/action-emitter.js +52 -0
- package/dist/emitters/constraint-emitter.d.ts +32 -0
- package/dist/emitters/constraint-emitter.d.ts.map +1 -0
- package/dist/emitters/constraint-emitter.js +41 -0
- package/dist/emitters/error-emitter.d.ts +33 -0
- package/dist/emitters/error-emitter.d.ts.map +1 -0
- package/dist/emitters/error-emitter.js +50 -0
- package/dist/emitters/gate-emitter.d.ts +37 -0
- package/dist/emitters/gate-emitter.d.ts.map +1 -0
- package/dist/emitters/gate-emitter.js +53 -0
- package/dist/emitters/human-input-emitter.d.ts +30 -0
- package/dist/emitters/human-input-emitter.d.ts.map +1 -0
- package/dist/emitters/human-input-emitter.js +38 -0
- package/dist/emitters/index.d.ts +13 -0
- package/dist/emitters/index.d.ts.map +1 -0
- package/dist/emitters/index.js +19 -0
- package/dist/emitters/plan-emitter.d.ts +75 -0
- package/dist/emitters/plan-emitter.d.ts.map +1 -0
- package/dist/emitters/plan-emitter.js +116 -0
- package/dist/emitters/session-emitter.d.ts +57 -0
- package/dist/emitters/session-emitter.d.ts.map +1 -0
- package/dist/emitters/session-emitter.js +80 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +111 -0
- package/dist/kindling-service.d.ts +122 -0
- package/dist/kindling-service.d.ts.map +1 -0
- package/dist/kindling-service.js +203 -0
- package/dist/observation-contract.d.ts +561 -0
- package/dist/observation-contract.d.ts.map +1 -0
- package/dist/observation-contract.js +391 -0
- package/dist/query-contract.d.ts +463 -0
- package/dist/query-contract.d.ts.map +1 -0
- package/dist/query-contract.js +314 -0
- package/dist/query-limits.d.ts +40 -0
- package/dist/query-limits.d.ts.map +1 -0
- package/dist/query-limits.js +79 -0
- package/dist/query-service.d.ts +109 -0
- package/dist/query-service.d.ts.map +1 -0
- package/dist/query-service.js +140 -0
- package/dist/retention.d.ts +79 -0
- package/dist/retention.d.ts.map +1 -0
- package/dist/retention.js +81 -0
- package/dist/sensitive-data-validator.d.ts +47 -0
- package/dist/sensitive-data-validator.d.ts.map +1 -0
- package/dist/sensitive-data-validator.js +135 -0
- package/dist/status.d.ts +104 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +136 -0
- package/dist/utils/debug.d.ts +9 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +55 -0
- package/package.json +114 -0
- package/src/adapter.ts +117 -0
- package/src/config.ts +202 -0
- package/src/emitters/action-emitter.ts +90 -0
- package/src/emitters/constraint-emitter.ts +73 -0
- package/src/emitters/error-emitter.ts +86 -0
- package/src/emitters/gate-emitter.ts +87 -0
- package/src/emitters/human-input-emitter.ts +71 -0
- package/src/emitters/index.ts +40 -0
- package/src/emitters/plan-emitter.ts +183 -0
- package/src/emitters/session-emitter.ts +131 -0
- package/src/index.ts +254 -0
- package/src/kindling-service.ts +272 -0
- package/src/malicious-ai.test.ts +949 -0
- package/src/observation-contract.ts +500 -0
- package/src/query-contract.ts +389 -0
- package/src/query-limits.ts +106 -0
- package/src/query-service.ts +217 -0
- package/src/retention.ts +153 -0
- package/src/sensitive-data-validator.ts +167 -0
- package/src/status.ts +221 -0
- package/src/utils/debug.ts +65 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kindling Configuration Schema (KINDLING-002)
|
|
3
|
+
*
|
|
4
|
+
* Defines configuration for the Kindling integration layer.
|
|
5
|
+
* Configuration is read from `.anvilrc` or `anvil.config.json` in the project root.
|
|
6
|
+
*
|
|
7
|
+
* @see kindling-service.ts for how config is consumed
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
/**
|
|
11
|
+
* Capture flags: which observation kinds to record
|
|
12
|
+
*/
|
|
13
|
+
export declare const CaptureConfigSchema: z.ZodObject<{
|
|
14
|
+
sessions: z.ZodDefault<z.ZodBoolean>;
|
|
15
|
+
gates: z.ZodDefault<z.ZodBoolean>;
|
|
16
|
+
actions: z.ZodDefault<z.ZodBoolean>;
|
|
17
|
+
plans: z.ZodDefault<z.ZodBoolean>;
|
|
18
|
+
human_inputs: z.ZodDefault<z.ZodBoolean>;
|
|
19
|
+
constraints: z.ZodDefault<z.ZodBoolean>;
|
|
20
|
+
errors: z.ZodDefault<z.ZodBoolean>;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
export type CaptureConfig = z.infer<typeof CaptureConfigSchema>;
|
|
23
|
+
/**
|
|
24
|
+
* Retention policy
|
|
25
|
+
*/
|
|
26
|
+
export declare const RetentionConfigSchema: z.ZodObject<{
|
|
27
|
+
days: z.ZodDefault<z.ZodNumber>;
|
|
28
|
+
auto_prune: z.ZodDefault<z.ZodBoolean>;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
export type RetentionConfig = z.infer<typeof RetentionConfigSchema>;
|
|
31
|
+
/**
|
|
32
|
+
* Query limit defaults
|
|
33
|
+
*/
|
|
34
|
+
export declare const QueryLimitConfigSchema: z.ZodObject<{
|
|
35
|
+
max_results: z.ZodDefault<z.ZodNumber>;
|
|
36
|
+
max_payload_bytes: z.ZodDefault<z.ZodNumber>;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
export type QueryLimitConfig = z.infer<typeof QueryLimitConfigSchema>;
|
|
39
|
+
/**
|
|
40
|
+
* Full Kindling configuration
|
|
41
|
+
*/
|
|
42
|
+
export declare const KindlingConfigSchema: z.ZodObject<{
|
|
43
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
44
|
+
database_path: z.ZodDefault<z.ZodString>;
|
|
45
|
+
retention: z.ZodDefault<z.ZodObject<{
|
|
46
|
+
days: z.ZodDefault<z.ZodNumber>;
|
|
47
|
+
auto_prune: z.ZodDefault<z.ZodBoolean>;
|
|
48
|
+
}, z.core.$strip>>;
|
|
49
|
+
capture: z.ZodDefault<z.ZodObject<{
|
|
50
|
+
sessions: z.ZodDefault<z.ZodBoolean>;
|
|
51
|
+
gates: z.ZodDefault<z.ZodBoolean>;
|
|
52
|
+
actions: z.ZodDefault<z.ZodBoolean>;
|
|
53
|
+
plans: z.ZodDefault<z.ZodBoolean>;
|
|
54
|
+
human_inputs: z.ZodDefault<z.ZodBoolean>;
|
|
55
|
+
constraints: z.ZodDefault<z.ZodBoolean>;
|
|
56
|
+
errors: z.ZodDefault<z.ZodBoolean>;
|
|
57
|
+
}, z.core.$strip>>;
|
|
58
|
+
query_limits: z.ZodDefault<z.ZodObject<{
|
|
59
|
+
max_results: z.ZodDefault<z.ZodNumber>;
|
|
60
|
+
max_payload_bytes: z.ZodDefault<z.ZodNumber>;
|
|
61
|
+
}, z.core.$strip>>;
|
|
62
|
+
}, z.core.$strip>;
|
|
63
|
+
export type KindlingConfig = z.infer<typeof KindlingConfigSchema>;
|
|
64
|
+
/**
|
|
65
|
+
* Default configuration: disabled, sensible defaults for everything else
|
|
66
|
+
*/
|
|
67
|
+
export declare const DEFAULT_KINDLING_CONFIG: KindlingConfig;
|
|
68
|
+
/**
|
|
69
|
+
* Load Kindling configuration from the project root.
|
|
70
|
+
*
|
|
71
|
+
* Searches for `.anvilrc` or `anvil.config.json` in the given directory.
|
|
72
|
+
* Expects a JSON file with an optional `kindling` key containing the config.
|
|
73
|
+
*
|
|
74
|
+
* Returns the default (disabled) config if no file is found or if the
|
|
75
|
+
* `kindling` key is absent.
|
|
76
|
+
*
|
|
77
|
+
* @param projectRoot - Absolute path to the project root directory
|
|
78
|
+
* @returns Parsed and validated KindlingConfig
|
|
79
|
+
*/
|
|
80
|
+
export declare function loadKindlingConfig(projectRoot: string): KindlingConfig;
|
|
81
|
+
/**
|
|
82
|
+
* Check whether a specific observation kind should be captured based on config.
|
|
83
|
+
*
|
|
84
|
+
* @param config - Kindling configuration
|
|
85
|
+
* @param kind - Observation kind string
|
|
86
|
+
* @returns true if the observation should be captured
|
|
87
|
+
*/
|
|
88
|
+
export declare function shouldCapture(config: KindlingConfig, kind: string): boolean;
|
|
89
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;iBAQ9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;iBAGhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;iBAejC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;iBAuB/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAMlE;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,cAA+C,CAAC;AAWtF;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAwCtE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CA4B3E"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kindling Configuration Schema (KINDLING-002)
|
|
3
|
+
*
|
|
4
|
+
* Defines configuration for the Kindling integration layer.
|
|
5
|
+
* Configuration is read from `.anvilrc` or `anvil.config.json` in the project root.
|
|
6
|
+
*
|
|
7
|
+
* @see kindling-service.ts for how config is consumed
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Configuration Schema
|
|
14
|
+
// =============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Capture flags: which observation kinds to record
|
|
17
|
+
*/
|
|
18
|
+
export const CaptureConfigSchema = z.object({
|
|
19
|
+
sessions: z.boolean().default(true).describe('Record session start/end'),
|
|
20
|
+
gates: z.boolean().default(true).describe('Record gate evaluations'),
|
|
21
|
+
actions: z.boolean().default(true).describe('Record action executions'),
|
|
22
|
+
plans: z.boolean().default(true).describe('Record plan lifecycle events'),
|
|
23
|
+
human_inputs: z.boolean().default(true).describe('Record human inputs'),
|
|
24
|
+
constraints: z.boolean().default(true).describe('Record constraint applications'),
|
|
25
|
+
errors: z.boolean().default(true).describe('Record errors'),
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Retention policy
|
|
29
|
+
*/
|
|
30
|
+
export const RetentionConfigSchema = z.object({
|
|
31
|
+
days: z.number().int().positive().default(90).describe('Days to retain observations'),
|
|
32
|
+
auto_prune: z.boolean().default(false).describe('Automatically prune on session start'),
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Query limit defaults
|
|
36
|
+
*/
|
|
37
|
+
export const QueryLimitConfigSchema = z.object({
|
|
38
|
+
max_results: z
|
|
39
|
+
.number()
|
|
40
|
+
.int()
|
|
41
|
+
.positive()
|
|
42
|
+
.max(1000)
|
|
43
|
+
.default(100)
|
|
44
|
+
.describe('Default max results per query'),
|
|
45
|
+
max_payload_bytes: z
|
|
46
|
+
.number()
|
|
47
|
+
.int()
|
|
48
|
+
.positive()
|
|
49
|
+
.max(10 * 1024 * 1024)
|
|
50
|
+
.default(1024 * 1024)
|
|
51
|
+
.describe('Default max payload size in bytes'),
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* Full Kindling configuration
|
|
55
|
+
*/
|
|
56
|
+
export const KindlingConfigSchema = z.object({
|
|
57
|
+
enabled: z.boolean().default(false).describe('Whether Kindling recording is active'),
|
|
58
|
+
database_path: z
|
|
59
|
+
.string()
|
|
60
|
+
.default('.anvil/kindling.db')
|
|
61
|
+
.describe('Path to the SQLite database (relative to project root)'),
|
|
62
|
+
retention: RetentionConfigSchema.default(() => ({
|
|
63
|
+
days: 90,
|
|
64
|
+
auto_prune: false,
|
|
65
|
+
})),
|
|
66
|
+
capture: CaptureConfigSchema.default(() => ({
|
|
67
|
+
sessions: true,
|
|
68
|
+
gates: true,
|
|
69
|
+
actions: true,
|
|
70
|
+
plans: true,
|
|
71
|
+
human_inputs: true,
|
|
72
|
+
constraints: true,
|
|
73
|
+
errors: true,
|
|
74
|
+
})),
|
|
75
|
+
query_limits: QueryLimitConfigSchema.default(() => ({
|
|
76
|
+
max_results: 100,
|
|
77
|
+
max_payload_bytes: 1024 * 1024,
|
|
78
|
+
})),
|
|
79
|
+
});
|
|
80
|
+
// =============================================================================
|
|
81
|
+
// Default Configuration
|
|
82
|
+
// =============================================================================
|
|
83
|
+
/**
|
|
84
|
+
* Default configuration: disabled, sensible defaults for everything else
|
|
85
|
+
*/
|
|
86
|
+
export const DEFAULT_KINDLING_CONFIG = KindlingConfigSchema.parse({});
|
|
87
|
+
// =============================================================================
|
|
88
|
+
// Configuration Loading
|
|
89
|
+
// =============================================================================
|
|
90
|
+
/**
|
|
91
|
+
* Known configuration file names, checked in order
|
|
92
|
+
*/
|
|
93
|
+
const CONFIG_FILE_NAMES = ['.anvilrc', 'anvil.config.json'];
|
|
94
|
+
/**
|
|
95
|
+
* Load Kindling configuration from the project root.
|
|
96
|
+
*
|
|
97
|
+
* Searches for `.anvilrc` or `anvil.config.json` in the given directory.
|
|
98
|
+
* Expects a JSON file with an optional `kindling` key containing the config.
|
|
99
|
+
*
|
|
100
|
+
* Returns the default (disabled) config if no file is found or if the
|
|
101
|
+
* `kindling` key is absent.
|
|
102
|
+
*
|
|
103
|
+
* @param projectRoot - Absolute path to the project root directory
|
|
104
|
+
* @returns Parsed and validated KindlingConfig
|
|
105
|
+
*/
|
|
106
|
+
export function loadKindlingConfig(projectRoot) {
|
|
107
|
+
for (const fileName of CONFIG_FILE_NAMES) {
|
|
108
|
+
const filePath = join(projectRoot, fileName);
|
|
109
|
+
if (!existsSync(filePath)) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
const raw = readFileSync(filePath, 'utf-8');
|
|
114
|
+
const parsed = JSON.parse(raw);
|
|
115
|
+
if (parsed === null || typeof parsed !== 'object') {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const record = parsed;
|
|
119
|
+
if (!('kindling' in record) || record['kindling'] === undefined) {
|
|
120
|
+
// Config file exists but has no kindling section
|
|
121
|
+
return DEFAULT_KINDLING_CONFIG;
|
|
122
|
+
}
|
|
123
|
+
const result = KindlingConfigSchema.safeParse(record['kindling']);
|
|
124
|
+
if (result.success) {
|
|
125
|
+
return result.data;
|
|
126
|
+
}
|
|
127
|
+
// Invalid config shape -- fall back to defaults rather than crashing
|
|
128
|
+
// The caller (service layer) will operate in disabled mode
|
|
129
|
+
return DEFAULT_KINDLING_CONFIG;
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// JSON parse error or read error -- fall back to defaults
|
|
133
|
+
return DEFAULT_KINDLING_CONFIG;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// No config file found
|
|
137
|
+
return DEFAULT_KINDLING_CONFIG;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Check whether a specific observation kind should be captured based on config.
|
|
141
|
+
*
|
|
142
|
+
* @param config - Kindling configuration
|
|
143
|
+
* @param kind - Observation kind string
|
|
144
|
+
* @returns true if the observation should be captured
|
|
145
|
+
*/
|
|
146
|
+
export function shouldCapture(config, kind) {
|
|
147
|
+
if (!config.enabled) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
switch (kind) {
|
|
151
|
+
case 'session_start':
|
|
152
|
+
case 'session_end':
|
|
153
|
+
return config.capture.sessions;
|
|
154
|
+
case 'gate_evaluated':
|
|
155
|
+
return config.capture.gates;
|
|
156
|
+
case 'action_executed':
|
|
157
|
+
return config.capture.actions;
|
|
158
|
+
case 'plan_created':
|
|
159
|
+
case 'plan_edited':
|
|
160
|
+
case 'plan_approved':
|
|
161
|
+
case 'plan_rejected':
|
|
162
|
+
return config.capture.plans;
|
|
163
|
+
case 'human_input':
|
|
164
|
+
return config.capture.human_inputs;
|
|
165
|
+
case 'constraint_applied':
|
|
166
|
+
return config.capture.constraints;
|
|
167
|
+
case 'error':
|
|
168
|
+
return config.capture.errors;
|
|
169
|
+
default:
|
|
170
|
+
// Unknown kinds are captured by default when enabled
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action Emitter (KINDLING-005)
|
|
3
|
+
*
|
|
4
|
+
* Emits action_executed observations when commands, tool invocations,
|
|
5
|
+
* file operations, or diff applications occur.
|
|
6
|
+
*/
|
|
7
|
+
import type { KindlingService } from '../kindling-service.js';
|
|
8
|
+
/**
|
|
9
|
+
* Action execution details to be recorded
|
|
10
|
+
*/
|
|
11
|
+
export interface ActionDetails {
|
|
12
|
+
session_id: string;
|
|
13
|
+
action_type: 'command' | 'tool_invocation' | 'file_write' | 'file_delete' | 'diff_apply';
|
|
14
|
+
details: {
|
|
15
|
+
command?: string;
|
|
16
|
+
tool_name?: string;
|
|
17
|
+
file_paths?: string[];
|
|
18
|
+
diff_summary?: {
|
|
19
|
+
additions: number;
|
|
20
|
+
deletions: number;
|
|
21
|
+
files_changed: number;
|
|
22
|
+
};
|
|
23
|
+
working_directory: string;
|
|
24
|
+
environment_target?: string;
|
|
25
|
+
};
|
|
26
|
+
governed_by_gate_id?: string;
|
|
27
|
+
governed_by_plan_id?: string;
|
|
28
|
+
outcome: 'success' | 'failure' | 'partial';
|
|
29
|
+
exit_code?: number;
|
|
30
|
+
duration_ms: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Emit an action_executed observation.
|
|
34
|
+
*
|
|
35
|
+
* @param service - KindlingService instance
|
|
36
|
+
* @param actionDetails - Action execution details
|
|
37
|
+
* @returns The generated action_id
|
|
38
|
+
*/
|
|
39
|
+
export declare function emitActionExecuted(service: KindlingService, actionDetails: ActionDetails): string;
|
|
40
|
+
//# sourceMappingURL=action-emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-emitter.d.ts","sourceRoot":"","sources":["../../src/emitters/action-emitter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAU9D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,SAAS,GAAG,iBAAiB,GAAG,YAAY,GAAG,aAAa,GAAG,YAAY,CAAC;IACzF,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,YAAY,CAAC,EAAE;YACb,SAAS,EAAE,MAAM,CAAC;YAClB,SAAS,EAAE,MAAM,CAAC;YAClB,aAAa,EAAE,MAAM,CAAC;SACvB,CAAC;QACF,iBAAiB,EAAE,MAAM,CAAC;QAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,GAAG,MAAM,CAmCjG"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action Emitter (KINDLING-005)
|
|
3
|
+
*
|
|
4
|
+
* Emits action_executed observations when commands, tool invocations,
|
|
5
|
+
* file operations, or diff applications occur.
|
|
6
|
+
*/
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
import { createDebugger } from '../utils/debug.js';
|
|
9
|
+
const debug = createDebugger('kindling');
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Emitter
|
|
12
|
+
// =============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Emit an action_executed observation.
|
|
15
|
+
*
|
|
16
|
+
* @param service - KindlingService instance
|
|
17
|
+
* @param actionDetails - Action execution details
|
|
18
|
+
* @returns The generated action_id
|
|
19
|
+
*/
|
|
20
|
+
export function emitActionExecuted(service, actionDetails) {
|
|
21
|
+
const actionId = randomUUID();
|
|
22
|
+
debug('emitting action_executed', {
|
|
23
|
+
actionId,
|
|
24
|
+
actionType: actionDetails.action_type,
|
|
25
|
+
outcome: actionDetails.outcome,
|
|
26
|
+
});
|
|
27
|
+
const observation = {
|
|
28
|
+
kind: 'action_executed',
|
|
29
|
+
session_id: actionDetails.session_id,
|
|
30
|
+
timestamp: new Date().toISOString(),
|
|
31
|
+
action_id: actionId,
|
|
32
|
+
action_type: actionDetails.action_type,
|
|
33
|
+
details: {
|
|
34
|
+
command: actionDetails.details.command,
|
|
35
|
+
tool_name: actionDetails.details.tool_name,
|
|
36
|
+
file_paths: actionDetails.details.file_paths,
|
|
37
|
+
diff_summary: actionDetails.details.diff_summary,
|
|
38
|
+
working_directory: actionDetails.details.working_directory,
|
|
39
|
+
environment_target: actionDetails.details.environment_target,
|
|
40
|
+
},
|
|
41
|
+
governed_by_gate_id: actionDetails.governed_by_gate_id,
|
|
42
|
+
governed_by_plan_id: actionDetails.governed_by_plan_id,
|
|
43
|
+
outcome: actionDetails.outcome,
|
|
44
|
+
exit_code: actionDetails.exit_code,
|
|
45
|
+
duration_ms: actionDetails.duration_ms,
|
|
46
|
+
};
|
|
47
|
+
// Fire-and-forget
|
|
48
|
+
service.emit(observation).catch(() => {
|
|
49
|
+
// Silently swallow
|
|
50
|
+
});
|
|
51
|
+
return actionId;
|
|
52
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constraint Emitter (KINDLING-007b)
|
|
3
|
+
*
|
|
4
|
+
* Emits constraint_applied observations when Anvil prevents an action
|
|
5
|
+
* due to policy, scope, environment, or approval requirements.
|
|
6
|
+
*/
|
|
7
|
+
import type { KindlingService } from '../kindling-service.js';
|
|
8
|
+
/**
|
|
9
|
+
* Constraint application details to be recorded
|
|
10
|
+
*/
|
|
11
|
+
export interface ConstraintDetails {
|
|
12
|
+
session_id: string;
|
|
13
|
+
constraint_type: 'policy' | 'rule' | 'scope' | 'environment' | 'approval_required';
|
|
14
|
+
prevented_action: {
|
|
15
|
+
action_type: string;
|
|
16
|
+
action_target?: string;
|
|
17
|
+
};
|
|
18
|
+
reason: string;
|
|
19
|
+
scope?: string;
|
|
20
|
+
environment?: string;
|
|
21
|
+
options_available?: string[];
|
|
22
|
+
options_allowed?: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Emit a constraint_applied observation.
|
|
26
|
+
*
|
|
27
|
+
* @param service - KindlingService instance
|
|
28
|
+
* @param constraint - Constraint application details
|
|
29
|
+
* @returns The generated constraint_id
|
|
30
|
+
*/
|
|
31
|
+
export declare function emitConstraintApplied(service: KindlingService, constraint: ConstraintDetails): string;
|
|
32
|
+
//# sourceMappingURL=constraint-emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constraint-emitter.d.ts","sourceRoot":"","sources":["../../src/emitters/constraint-emitter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAO9D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,mBAAmB,CAAC;IACnF,gBAAgB,EAAE;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAMD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,eAAe,EACxB,UAAU,EAAE,iBAAiB,GAC5B,MAAM,CA0BR"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constraint Emitter (KINDLING-007b)
|
|
3
|
+
*
|
|
4
|
+
* Emits constraint_applied observations when Anvil prevents an action
|
|
5
|
+
* due to policy, scope, environment, or approval requirements.
|
|
6
|
+
*/
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// Emitter
|
|
10
|
+
// =============================================================================
|
|
11
|
+
/**
|
|
12
|
+
* Emit a constraint_applied observation.
|
|
13
|
+
*
|
|
14
|
+
* @param service - KindlingService instance
|
|
15
|
+
* @param constraint - Constraint application details
|
|
16
|
+
* @returns The generated constraint_id
|
|
17
|
+
*/
|
|
18
|
+
export function emitConstraintApplied(service, constraint) {
|
|
19
|
+
const constraintId = randomUUID();
|
|
20
|
+
const observation = {
|
|
21
|
+
kind: 'constraint_applied',
|
|
22
|
+
session_id: constraint.session_id,
|
|
23
|
+
timestamp: new Date().toISOString(),
|
|
24
|
+
constraint_id: constraintId,
|
|
25
|
+
constraint_type: constraint.constraint_type,
|
|
26
|
+
prevented_action: {
|
|
27
|
+
action_type: constraint.prevented_action.action_type,
|
|
28
|
+
action_target: constraint.prevented_action.action_target,
|
|
29
|
+
},
|
|
30
|
+
reason: constraint.reason,
|
|
31
|
+
scope: constraint.scope,
|
|
32
|
+
environment: constraint.environment,
|
|
33
|
+
options_available: constraint.options_available,
|
|
34
|
+
options_allowed: constraint.options_allowed,
|
|
35
|
+
};
|
|
36
|
+
// Fire-and-forget
|
|
37
|
+
service.emit(observation).catch(() => {
|
|
38
|
+
// Silently swallow
|
|
39
|
+
});
|
|
40
|
+
return constraintId;
|
|
41
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Emitter (KINDLING-008)
|
|
3
|
+
*
|
|
4
|
+
* Emits error observations when failures occur.
|
|
5
|
+
* "Errors are not noise, they are data."
|
|
6
|
+
*/
|
|
7
|
+
import type { KindlingService } from '../kindling-service.js';
|
|
8
|
+
/**
|
|
9
|
+
* Error details to be recorded
|
|
10
|
+
*/
|
|
11
|
+
export interface ErrorDetails {
|
|
12
|
+
session_id: string;
|
|
13
|
+
error_type: 'command_failure' | 'tool_error' | 'aborted_execution' | 'partial_state' | 'validation_failure';
|
|
14
|
+
context: {
|
|
15
|
+
component: string;
|
|
16
|
+
action_id?: string;
|
|
17
|
+
gate_id?: string;
|
|
18
|
+
};
|
|
19
|
+
error_message: string;
|
|
20
|
+
error_code?: string;
|
|
21
|
+
exit_code?: number;
|
|
22
|
+
recoverable: boolean;
|
|
23
|
+
partial_state_description?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Emit an error observation.
|
|
27
|
+
*
|
|
28
|
+
* @param service - KindlingService instance
|
|
29
|
+
* @param errorDetails - Error details
|
|
30
|
+
* @returns The generated error_id
|
|
31
|
+
*/
|
|
32
|
+
export declare function emitError(service: KindlingService, errorDetails: ErrorDetails): string;
|
|
33
|
+
//# sourceMappingURL=error-emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-emitter.d.ts","sourceRoot":"","sources":["../../src/emitters/error-emitter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAU9D;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EACN,iBAAiB,GACjB,YAAY,GACZ,mBAAmB,GACnB,eAAe,GACf,oBAAoB,CAAC;IACzB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC;AAMD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,GAAG,MAAM,CAiCtF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Emitter (KINDLING-008)
|
|
3
|
+
*
|
|
4
|
+
* Emits error observations when failures occur.
|
|
5
|
+
* "Errors are not noise, they are data."
|
|
6
|
+
*/
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
import { createDebugger } from '../utils/debug.js';
|
|
9
|
+
const debug = createDebugger('kindling');
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Emitter
|
|
12
|
+
// =============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Emit an error observation.
|
|
15
|
+
*
|
|
16
|
+
* @param service - KindlingService instance
|
|
17
|
+
* @param errorDetails - Error details
|
|
18
|
+
* @returns The generated error_id
|
|
19
|
+
*/
|
|
20
|
+
export function emitError(service, errorDetails) {
|
|
21
|
+
const errorId = randomUUID();
|
|
22
|
+
debug('emitting error observation', {
|
|
23
|
+
errorId,
|
|
24
|
+
errorType: errorDetails.error_type,
|
|
25
|
+
component: errorDetails.context.component,
|
|
26
|
+
recoverable: errorDetails.recoverable,
|
|
27
|
+
});
|
|
28
|
+
const observation = {
|
|
29
|
+
kind: 'error',
|
|
30
|
+
session_id: errorDetails.session_id,
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
error_id: errorId,
|
|
33
|
+
error_type: errorDetails.error_type,
|
|
34
|
+
context: {
|
|
35
|
+
component: errorDetails.context.component,
|
|
36
|
+
action_id: errorDetails.context.action_id,
|
|
37
|
+
gate_id: errorDetails.context.gate_id,
|
|
38
|
+
},
|
|
39
|
+
error_message: errorDetails.error_message,
|
|
40
|
+
error_code: errorDetails.error_code,
|
|
41
|
+
exit_code: errorDetails.exit_code,
|
|
42
|
+
recoverable: errorDetails.recoverable,
|
|
43
|
+
partial_state_description: errorDetails.partial_state_description,
|
|
44
|
+
};
|
|
45
|
+
// Fire-and-forget
|
|
46
|
+
service.emit(observation).catch(() => {
|
|
47
|
+
// Silently swallow
|
|
48
|
+
});
|
|
49
|
+
return errorId;
|
|
50
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate Emitter (KINDLING-004)
|
|
3
|
+
*
|
|
4
|
+
* Emits gate_evaluated observations when gates are checked.
|
|
5
|
+
* Gate evaluations form the governance record -- why things were
|
|
6
|
+
* allowed or blocked.
|
|
7
|
+
*/
|
|
8
|
+
import type { KindlingService } from '../kindling-service.js';
|
|
9
|
+
/**
|
|
10
|
+
* Gate evaluation result to be recorded
|
|
11
|
+
*/
|
|
12
|
+
export interface GateResult {
|
|
13
|
+
session_id: string;
|
|
14
|
+
gate_id: string;
|
|
15
|
+
gate_version?: string;
|
|
16
|
+
inputs: {
|
|
17
|
+
file_count?: number;
|
|
18
|
+
changed_files?: string[];
|
|
19
|
+
baseline_hash?: string;
|
|
20
|
+
};
|
|
21
|
+
outcome: 'pass' | 'fail' | 'error' | 'skipped';
|
|
22
|
+
rules_evaluated: string[];
|
|
23
|
+
rules_violated?: string[];
|
|
24
|
+
enforcement: 'blocking' | 'warning' | 'informational';
|
|
25
|
+
duration_ms: number;
|
|
26
|
+
violation_count?: number;
|
|
27
|
+
warning_count?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Emit a gate_evaluated observation.
|
|
31
|
+
*
|
|
32
|
+
* @param service - KindlingService instance
|
|
33
|
+
* @param gateResult - Gate evaluation result
|
|
34
|
+
* @returns The generated gate_eval_id
|
|
35
|
+
*/
|
|
36
|
+
export declare function emitGateEvaluated(service: KindlingService, gateResult: GateResult): string;
|
|
37
|
+
//# sourceMappingURL=gate-emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-emitter.d.ts","sourceRoot":"","sources":["../../src/emitters/gate-emitter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAU9D;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE;QACN,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC/C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,WAAW,EAAE,UAAU,GAAG,SAAS,GAAG,eAAe,CAAC;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,CAmC1F"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate Emitter (KINDLING-004)
|
|
3
|
+
*
|
|
4
|
+
* Emits gate_evaluated observations when gates are checked.
|
|
5
|
+
* Gate evaluations form the governance record -- why things were
|
|
6
|
+
* allowed or blocked.
|
|
7
|
+
*/
|
|
8
|
+
import { randomUUID } from 'node:crypto';
|
|
9
|
+
import { createDebugger } from '../utils/debug.js';
|
|
10
|
+
const debug = createDebugger('kindling');
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Emitter
|
|
13
|
+
// =============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Emit a gate_evaluated observation.
|
|
16
|
+
*
|
|
17
|
+
* @param service - KindlingService instance
|
|
18
|
+
* @param gateResult - Gate evaluation result
|
|
19
|
+
* @returns The generated gate_eval_id
|
|
20
|
+
*/
|
|
21
|
+
export function emitGateEvaluated(service, gateResult) {
|
|
22
|
+
const gateEvalId = randomUUID();
|
|
23
|
+
debug('emitting gate_evaluated', {
|
|
24
|
+
gateId: gateResult.gate_id,
|
|
25
|
+
outcome: gateResult.outcome,
|
|
26
|
+
gateEvalId,
|
|
27
|
+
});
|
|
28
|
+
const observation = {
|
|
29
|
+
kind: 'gate_evaluated',
|
|
30
|
+
session_id: gateResult.session_id,
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
gate_eval_id: gateEvalId,
|
|
33
|
+
gate_id: gateResult.gate_id,
|
|
34
|
+
gate_version: gateResult.gate_version,
|
|
35
|
+
inputs: {
|
|
36
|
+
file_count: gateResult.inputs.file_count,
|
|
37
|
+
changed_files: gateResult.inputs.changed_files,
|
|
38
|
+
baseline_hash: gateResult.inputs.baseline_hash,
|
|
39
|
+
},
|
|
40
|
+
outcome: gateResult.outcome,
|
|
41
|
+
rules_evaluated: gateResult.rules_evaluated,
|
|
42
|
+
rules_violated: gateResult.rules_violated,
|
|
43
|
+
enforcement: gateResult.enforcement,
|
|
44
|
+
duration_ms: gateResult.duration_ms,
|
|
45
|
+
violation_count: gateResult.violation_count,
|
|
46
|
+
warning_count: gateResult.warning_count,
|
|
47
|
+
};
|
|
48
|
+
// Fire-and-forget
|
|
49
|
+
service.emit(observation).catch(() => {
|
|
50
|
+
// Silently swallow
|
|
51
|
+
});
|
|
52
|
+
return gateEvalId;
|
|
53
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human Input Emitter (KINDLING-007a)
|
|
3
|
+
*
|
|
4
|
+
* Emits human_input observations when a user makes a decision
|
|
5
|
+
* (approval, override, rejection, manual edit, confirmation, cancellation).
|
|
6
|
+
*/
|
|
7
|
+
import type { KindlingService } from '../kindling-service.js';
|
|
8
|
+
/**
|
|
9
|
+
* Human input details to be recorded
|
|
10
|
+
*/
|
|
11
|
+
export interface HumanInputDetails {
|
|
12
|
+
session_id: string;
|
|
13
|
+
input_type: 'approval' | 'override' | 'rejection' | 'manual_edit' | 'confirmation' | 'cancellation';
|
|
14
|
+
context: {
|
|
15
|
+
prompt?: string;
|
|
16
|
+
target?: string;
|
|
17
|
+
};
|
|
18
|
+
decision: string;
|
|
19
|
+
reason?: string;
|
|
20
|
+
user_identifier: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Emit a human_input observation.
|
|
24
|
+
*
|
|
25
|
+
* @param service - KindlingService instance
|
|
26
|
+
* @param input - Human input details
|
|
27
|
+
* @returns A generated ID for linking purposes
|
|
28
|
+
*/
|
|
29
|
+
export declare function emitHumanInput(service: KindlingService, input: HumanInputDetails): string;
|
|
30
|
+
//# sourceMappingURL=human-input-emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"human-input-emitter.d.ts","sourceRoot":"","sources":["../../src/emitters/human-input-emitter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAO9D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EACN,UAAU,GACV,UAAU,GACV,WAAW,GACX,aAAa,GACb,cAAc,GACd,cAAc,CAAC;IACnB,OAAO,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;CACzB;AAMD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAuBzF"}
|