@adhd/agent-core-policy 2.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/drizzle/0000_sleepy_bullseye.sql +16 -0
- package/drizzle/0001_pale_marvel_zombies.sql +11 -0
- package/drizzle/0002_category_policy_inheritance.sql +22 -0
- package/drizzle/meta/0000_snapshot.json +119 -0
- package/drizzle/meta/0001_snapshot.json +186 -0
- package/drizzle/meta/0002_snapshot.json +274 -0
- package/drizzle/meta/_journal.json +27 -0
- package/package.json +53 -0
- package/src/db/client.d.ts +7 -0
- package/src/db/client.d.ts.map +1 -0
- package/src/db/client.js +18 -0
- package/src/db/client.js.map +1 -0
- package/src/db/migrate-runner.d.ts +30 -0
- package/src/db/migrate-runner.d.ts.map +1 -0
- package/src/db/migrate-runner.js +34 -0
- package/src/db/migrate-runner.js.map +1 -0
- package/src/db/migrate.d.ts +9 -0
- package/src/db/migrate.d.ts.map +1 -0
- package/src/db/migrate.js +13 -0
- package/src/db/migrate.js.map +1 -0
- package/src/db/schema.d.ts +383 -0
- package/src/db/schema.d.ts.map +1 -0
- package/src/db/schema.js +139 -0
- package/src/db/schema.js.map +1 -0
- package/src/index.d.ts +14 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +20 -0
- package/src/index.js.map +1 -0
- package/src/plugin/index.d.ts +24 -0
- package/src/plugin/index.d.ts.map +1 -0
- package/src/plugin/index.js +140 -0
- package/src/plugin/index.js.map +1 -0
- package/src/plugin/rate-policy.d.ts +34 -0
- package/src/plugin/rate-policy.d.ts.map +1 -0
- package/src/plugin/rate-policy.js +36 -0
- package/src/plugin/rate-policy.js.map +1 -0
- package/src/seed/index.d.ts +39 -0
- package/src/seed/index.d.ts.map +1 -0
- package/src/seed/index.js +62 -0
- package/src/seed/index.js.map +1 -0
- package/src/seed/policy-templates.d.ts +45 -0
- package/src/seed/policy-templates.d.ts.map +1 -0
- package/src/seed/policy-templates.js +189 -0
- package/src/seed/policy-templates.js.map +1 -0
- package/src/seed/policy-types.d.ts +19 -0
- package/src/seed/policy-types.d.ts.map +1 -0
- package/src/seed/policy-types.js +44 -0
- package/src/seed/policy-types.js.map +1 -0
- package/src/store/agent-policy-store.d.ts +172 -0
- package/src/store/agent-policy-store.d.ts.map +1 -0
- package/src/store/agent-policy-store.js +241 -0
- package/src/store/agent-policy-store.js.map +1 -0
- package/src/store/policy-template-store.d.ts +72 -0
- package/src/store/policy-template-store.d.ts.map +1 -0
- package/src/store/policy-template-store.js +118 -0
- package/src/store/policy-template-store.js.map +1 -0
package/src/db/schema.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { index, integer, primaryKey, sqliteTable, text, } from 'drizzle-orm/sqlite-core';
|
|
2
|
+
// ──────────────────────────────────────────────
|
|
3
|
+
// policy_policy_types (lookup — never a SQL enum)
|
|
4
|
+
// ──────────────────────────────────────────────
|
|
5
|
+
// Controlled-vocab slug values are seeded as rows, not baked into the
|
|
6
|
+
// column type. New policy types are added by inserting a row, never by
|
|
7
|
+
// a migration altering the column. [inv:lookup-not-enum]
|
|
8
|
+
export const policyTypesTable = sqliteTable('policy_policy_types', {
|
|
9
|
+
slug: text('slug').primaryKey(),
|
|
10
|
+
description: text('description').notNull(),
|
|
11
|
+
});
|
|
12
|
+
// ──────────────────────────────────────────────
|
|
13
|
+
// policy_policy_templates
|
|
14
|
+
// ──────────────────────────────────────────────
|
|
15
|
+
// Reusable rule definitions. `rules` and `enforcement` are JSON columns:
|
|
16
|
+
// - rules: structured JSON object (policy-specific rule parameters)
|
|
17
|
+
// - enforcement: JSON ARRAY of one or more mechanism strings
|
|
18
|
+
// e.g. ["agent","ci"] — NEVER a single scalar column.
|
|
19
|
+
// [inv:enforcement-is-array]
|
|
20
|
+
//
|
|
21
|
+
// `type` is an in-package FK to policy_policy_types.slug (real Drizzle FK).
|
|
22
|
+
// Cross-package references (e.g. agent_slug → registry_agents) are plain
|
|
23
|
+
// text columns — no cross-prefix FK. [decisions.md Decision 0]
|
|
24
|
+
export const policyTemplatesTable = sqliteTable('policy_policy_templates', {
|
|
25
|
+
slug: text('slug').primaryKey(),
|
|
26
|
+
// In-package FK — policy_policy_types lives in the same drizzle schema.
|
|
27
|
+
type: text('type')
|
|
28
|
+
.notNull()
|
|
29
|
+
.references(() => policyTypesTable.slug),
|
|
30
|
+
description: text('description').notNull(),
|
|
31
|
+
// Structured rule parameters — deserialized to an object on read.
|
|
32
|
+
rules: text('rules', { mode: 'json' }).notNull(),
|
|
33
|
+
// One or more enforcement mechanism strings stored as a JSON array.
|
|
34
|
+
enforcement: text('enforcement', { mode: 'json' }).notNull(),
|
|
35
|
+
// Schema version; starts at 1, incremented on template update.
|
|
36
|
+
version: integer('version').notNull().default(1),
|
|
37
|
+
// SQLite boolean: 1 = system-owned template (cannot be deleted by users).
|
|
38
|
+
isSystem: integer('is_system', { mode: 'boolean' })
|
|
39
|
+
.notNull()
|
|
40
|
+
.default(false),
|
|
41
|
+
}, (table) => [
|
|
42
|
+
// Querying templates by type is the dominant read pattern.
|
|
43
|
+
index('idx_policy_templates_type').on(table.type),
|
|
44
|
+
]);
|
|
45
|
+
// ──────────────────────────────────────────────
|
|
46
|
+
// policy_category_policies (category→policy attachment)
|
|
47
|
+
// ──────────────────────────────────────────────
|
|
48
|
+
// Stores the lazy category-level policy attachments. When a policy is attached
|
|
49
|
+
// to a taxonomy category, a single row lands here — NOT fan-outed to per-agent
|
|
50
|
+
// rows. `resolveForAgent` joins this table against `policy_agent_categories` at
|
|
51
|
+
// query time to compute inherited policies. [Decision 1 — LAZY]
|
|
52
|
+
//
|
|
53
|
+
// `category_slug` is a LOGICAL reference to the taxonomy-category slug owned by
|
|
54
|
+
// `agent-registry-schema` — plain text, no cross-prefix SQLite FK. [Decision 0]
|
|
55
|
+
// `policy_slug` IS a real in-package FK → policy_policy_templates.slug.
|
|
56
|
+
export const categoryPoliciesTable = sqliteTable('policy_category_policies', {
|
|
57
|
+
// Logical cross-package reference — plain text, no .references().
|
|
58
|
+
categorySlug: text('category_slug').notNull(),
|
|
59
|
+
// In-package FK → policy_policy_templates.slug (real Drizzle FK).
|
|
60
|
+
policySlug: text('policy_slug')
|
|
61
|
+
.notNull()
|
|
62
|
+
.references(() => policyTemplatesTable.slug),
|
|
63
|
+
// SQLite boolean: 1 = this policy is mandatory for every member agent.
|
|
64
|
+
isMandatory: integer('is_mandatory', { mode: 'boolean' })
|
|
65
|
+
.notNull()
|
|
66
|
+
.default(false),
|
|
67
|
+
}, (table) => [
|
|
68
|
+
// Composite PK — one row per (category, policy) pair.
|
|
69
|
+
primaryKey({ columns: [table.categorySlug, table.policySlug] }),
|
|
70
|
+
// Look up all policies for a given category.
|
|
71
|
+
index('idx_category_policies_category_slug').on(table.categorySlug),
|
|
72
|
+
]);
|
|
73
|
+
// ──────────────────────────────────────────────
|
|
74
|
+
// policy_agent_categories (agent↔category membership)
|
|
75
|
+
// ──────────────────────────────────────────────
|
|
76
|
+
// Records which taxonomy categories an agent belongs to. This is the minimal
|
|
77
|
+
// local membership table for the lazy resolver; it does NOT redefine taxonomy
|
|
78
|
+
// tables — `category_slug` and `agent_slug` are both logical (plain text) refs
|
|
79
|
+
// to slugs owned by `agent-registry-schema`. [Decision 0, no cross-prefix FK]
|
|
80
|
+
//
|
|
81
|
+
// The resolver (resolveForAgent) joins this table against
|
|
82
|
+
// `policy_category_policies` at query time to fan category-level policies into
|
|
83
|
+
// per-agent resolved rows, each carrying `inherited_from = category_slug`.
|
|
84
|
+
// A new agent added to a category AFTER the policy was attached inherits
|
|
85
|
+
// automatically on the next `resolveForAgent` call — no re-fanout needed.
|
|
86
|
+
export const agentCategoriesTable = sqliteTable('policy_agent_categories', {
|
|
87
|
+
// Logical cross-package reference — plain text, no .references().
|
|
88
|
+
agentSlug: text('agent_slug').notNull(),
|
|
89
|
+
// Logical cross-package reference — plain text, no .references().
|
|
90
|
+
categorySlug: text('category_slug').notNull(),
|
|
91
|
+
}, (table) => [
|
|
92
|
+
// Composite PK — an agent may belong to a category only once.
|
|
93
|
+
primaryKey({ columns: [table.agentSlug, table.categorySlug] }),
|
|
94
|
+
// Dominant read: "which categories does this agent belong to?"
|
|
95
|
+
index('idx_agent_categories_agent_slug').on(table.agentSlug),
|
|
96
|
+
]);
|
|
97
|
+
// ──────────────────────────────────────────────
|
|
98
|
+
// policy_agent_policies (agent↔policy junction)
|
|
99
|
+
// ──────────────────────────────────────────────
|
|
100
|
+
// Attaches a policy template to an agent (directly or via category inheritance).
|
|
101
|
+
//
|
|
102
|
+
// CRITICAL: `agent_slug` is a LOGICAL reference to the agent-registry package's
|
|
103
|
+
// `registry_agents.slug` column — it is plain text, NOT a SQLite FK. No
|
|
104
|
+
// cross-package foreign keys are allowed. [Decision 0, inv:no-cross-pkg-fk]
|
|
105
|
+
//
|
|
106
|
+
// `policy_slug` IS a real in-package FK → policy_policy_templates.slug.
|
|
107
|
+
//
|
|
108
|
+
// `inherited_from` is the taxonomy category slug a policy cascaded from, or NULL
|
|
109
|
+
// when attached directly to the agent. It is a plain text column (logical ref to
|
|
110
|
+
// agent-registry's taxonomy categories — no cross-prefix FK). [Decision 1]
|
|
111
|
+
//
|
|
112
|
+
// Composite PK uses a real `primaryKey({columns})`, never a non-unique index.
|
|
113
|
+
// Exported as `agentPoliciesTable`; the underlying SQL table name is
|
|
114
|
+
// `policy_agent_policies` (policy_ prefix per package convention).
|
|
115
|
+
// @alias agentPolicy agentPolicies agent_policy_junction
|
|
116
|
+
export const agentPoliciesTable = sqliteTable('policy_agent_policies', {
|
|
117
|
+
// Logical cross-package reference — plain text, no .references().
|
|
118
|
+
agentSlug: text('agent_slug').notNull(),
|
|
119
|
+
// In-package FK → policy_policy_templates.slug (real Drizzle FK).
|
|
120
|
+
policySlug: text('policy_slug')
|
|
121
|
+
.notNull()
|
|
122
|
+
.references(() => policyTemplatesTable.slug),
|
|
123
|
+
// Per-agent JSON customising the template's rules (shallow-merge semantics
|
|
124
|
+
// per Decision 3). NULL means "use the template unchanged."
|
|
125
|
+
overrideConfig: text('override_config', { mode: 'json' }),
|
|
126
|
+
// SQLite boolean: 1 = this policy is mandatory for the agent.
|
|
127
|
+
isMandatory: integer('is_mandatory', { mode: 'boolean' })
|
|
128
|
+
.notNull()
|
|
129
|
+
.default(false),
|
|
130
|
+
// NULL = attached directly; non-NULL = category slug it cascaded from.
|
|
131
|
+
// Plain text (logical cross-package ref) — no .references(). [Decision 1]
|
|
132
|
+
inheritedFrom: text('inherited_from'),
|
|
133
|
+
}, (table) => [
|
|
134
|
+
// Composite PK — one row per (agent, policy) pair.
|
|
135
|
+
primaryKey({ columns: [table.agentSlug, table.policySlug] }),
|
|
136
|
+
// Look up all policies for a given agent (dominant query pattern).
|
|
137
|
+
index('idx_agent_policies_agent_slug').on(table.agentSlug),
|
|
138
|
+
]);
|
|
139
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../../../packages/agent/agent-core-policy/src/db/schema.ts"],"names":[],"mappings":"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"}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { db, sqlite } from './db/client.js';
|
|
2
|
+
export { runMigrations } from './db/migrate.js';
|
|
3
|
+
export * from './db/schema.js';
|
|
4
|
+
export { PolicyTemplateStore, PolicyError, } from './store/policy-template-store.js';
|
|
5
|
+
export type { PolicyTemplate, PolicyTemplateCreateInput, PolicyErrorCode, } from './store/policy-template-store.js';
|
|
6
|
+
export { AgentPolicyStore, AgentPolicyError, resolveEffectiveRules, } from './store/agent-policy-store.js';
|
|
7
|
+
export type { AgentPolicyRow, AgentPolicyAttachInput, AgentPolicyErrorCode, CategoryPolicyAttachInput, CategoryPolicyRow, AgentCategoryInput, } from './store/agent-policy-store.js';
|
|
8
|
+
export { seed, POLICY_TYPES, POLICY_TEMPLATES } from './seed/index.js';
|
|
9
|
+
export { createPlugin, configSchema } from './plugin/index.js';
|
|
10
|
+
export type { RatePolicyConfig } from './plugin/index.js';
|
|
11
|
+
export { evaluateRatePolicy, makeRatePolicyError, } from './plugin/rate-policy.js';
|
|
12
|
+
export type { RatePolicyRules } from './plugin/rate-policy.js';
|
|
13
|
+
export { createPlugin as default } from './plugin/index.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/agent/agent-core-policy/src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,cAAc,gBAAgB,CAAC;AAG/B,OAAO,EACL,mBAAmB,EACnB,WAAW,GACZ,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EACV,cAAc,EACd,yBAAyB,EACzB,eAAe,GAChB,MAAM,kCAAkC,CAAC;AAG1C,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAKvE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,YAAY,IAAI,OAAO,EAAE,MAAM,mBAAmB,CAAC"}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// @adhd/agent-policy — public barrel
|
|
2
|
+
// Policy engine with SQLite/Drizzle persistence.
|
|
3
|
+
// Tables, stores, and the enforcement plugin are exported here as they are
|
|
4
|
+
// added by subsequent plan states (policy-design, policy-store, etc.).
|
|
5
|
+
export { db, sqlite } from './db/client.js';
|
|
6
|
+
export { runMigrations } from './db/migrate.js';
|
|
7
|
+
export * from './db/schema.js';
|
|
8
|
+
// Policy template store + domain types
|
|
9
|
+
export { PolicyTemplateStore, PolicyError, } from './store/policy-template-store.js';
|
|
10
|
+
// Agent↔policy junction store + domain types (including category inheritance)
|
|
11
|
+
export { AgentPolicyStore, AgentPolicyError, resolveEffectiveRules, } from './store/agent-policy-store.js';
|
|
12
|
+
// Policy library seeder — idempotent population of policy_types + policy_templates.
|
|
13
|
+
export { seed, POLICY_TYPES, POLICY_TEMPLATES } from './seed/index.js';
|
|
14
|
+
// Rate-policy enforcement plugin — mirrors @adhd/agent-plugin-budget plugin shape.
|
|
15
|
+
// Registers a throws-propagating handler on "pre:model_request" to enforce
|
|
16
|
+
// rate (model-call count) limits from policy template rules + override_config.
|
|
17
|
+
export { createPlugin, configSchema } from './plugin/index.js';
|
|
18
|
+
export { evaluateRatePolicy, makeRatePolicyError, } from './plugin/rate-policy.js';
|
|
19
|
+
export { createPlugin as default } from './plugin/index.js';
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/agent/agent-core-policy/src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,iDAAiD;AACjD,2EAA2E;AAC3E,uEAAuE;AAEvE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,cAAc,gBAAgB,CAAC;AAE/B,uCAAuC;AACvC,OAAO,EACL,mBAAmB,EACnB,WAAW,GACZ,MAAM,kCAAkC,CAAC;AAO1C,8EAA8E;AAC9E,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAUvC,oFAAoF;AACpF,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,mFAAmF;AACnF,2EAA2E;AAC3E,+EAA+E;AAC/E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE/D,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,YAAY,IAAI,OAAO,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @adhd/agent-policy enforcement plugin.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors @adhd/agent-plugin-budget exactly in plugin shape:
|
|
5
|
+
* - exports configSchema (zod)
|
|
6
|
+
* - exports createPlugin (named) + default createPlugin
|
|
7
|
+
* - install() registers observational handlers (try/caught) AND one
|
|
8
|
+
* hooks.registerEnforcement("pre:model_request", ...) with NO try/catch
|
|
9
|
+
* so the throw propagates to the orchestrator.
|
|
10
|
+
*
|
|
11
|
+
* Enforcement scope: `rate`-type policies — enforces maxModelCalls per task.
|
|
12
|
+
* EnforcementEvent is "pre:model_request"-ONLY (decisions.md Decision 2).
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import type { PluginFactory } from '@adhd/agent-base-types';
|
|
16
|
+
export declare const configSchema: z.ZodObject<{
|
|
17
|
+
maxModelCalls: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
maxToolCalls: z.ZodOptional<z.ZodNumber>;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
export type RatePolicyConfig = z.infer<typeof configSchema>;
|
|
21
|
+
declare const createPlugin: PluginFactory;
|
|
22
|
+
export default createPlugin;
|
|
23
|
+
export { createPlugin };
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/agent/agent-core-policy/src/plugin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAIV,aAAa,EAId,MAAM,wBAAwB,CAAC;AAMhC,eAAO,MAAM,YAAY;;;iBAavB,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAyH5D,QAAA,MAAM,YAAY,EAAE,aAEnB,CAAC;AAEF,eAAe,YAAY,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @adhd/agent-policy enforcement plugin.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors @adhd/agent-plugin-budget exactly in plugin shape:
|
|
5
|
+
* - exports configSchema (zod)
|
|
6
|
+
* - exports createPlugin (named) + default createPlugin
|
|
7
|
+
* - install() registers observational handlers (try/caught) AND one
|
|
8
|
+
* hooks.registerEnforcement("pre:model_request", ...) with NO try/catch
|
|
9
|
+
* so the throw propagates to the orchestrator.
|
|
10
|
+
*
|
|
11
|
+
* Enforcement scope: `rate`-type policies — enforces maxModelCalls per task.
|
|
12
|
+
* EnforcementEvent is "pre:model_request"-ONLY (decisions.md Decision 2).
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import { evaluateRatePolicy } from './rate-policy.js';
|
|
16
|
+
// ── Config schema ─────────────────────────────────────────────────────────────
|
|
17
|
+
export const configSchema = z.object({
|
|
18
|
+
/**
|
|
19
|
+
* Max number of model (LLM) calls per task.
|
|
20
|
+
* Reads from the effective rules after shallow-merging template.rules +
|
|
21
|
+
* override_config (decisions.md Decision 3). Optional — no limit if absent.
|
|
22
|
+
*/
|
|
23
|
+
maxModelCalls: z.number().int().positive().optional(),
|
|
24
|
+
/**
|
|
25
|
+
* Max number of tool calls per task.
|
|
26
|
+
* Mirrors maxModelCalls but for tool-call enforcement.
|
|
27
|
+
* Optional — no limit if absent.
|
|
28
|
+
*/
|
|
29
|
+
maxToolCalls: z.number().int().positive().optional(),
|
|
30
|
+
});
|
|
31
|
+
// ── Plugin class ──────────────────────────────────────────────────────────────
|
|
32
|
+
class RatePolicyPlugin {
|
|
33
|
+
db;
|
|
34
|
+
cfg;
|
|
35
|
+
name = 'agent-policy-rate';
|
|
36
|
+
accumulators = new Map();
|
|
37
|
+
constructor(db, cfg) {
|
|
38
|
+
this.db = db;
|
|
39
|
+
this.cfg = cfg;
|
|
40
|
+
}
|
|
41
|
+
install(hooks) {
|
|
42
|
+
// Observational: initialise the per-task counter on task:start.
|
|
43
|
+
hooks.register('task:start', (p) => {
|
|
44
|
+
try {
|
|
45
|
+
this.onTaskStart(p);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
/* observational — never kill a task */
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
// Observational: increment model-call count after each completed model turn.
|
|
52
|
+
hooks.register('post:model_response', (p) => {
|
|
53
|
+
try {
|
|
54
|
+
this.onPostModelResponse(p);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
/* observational */
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
// Observational: increment tool-call count after each completed tool call.
|
|
61
|
+
hooks.register('post:tool_call', (p) => {
|
|
62
|
+
try {
|
|
63
|
+
this.onPostToolCall(p);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
/* observational */
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
// Observational: clean up accumulator on terminal events.
|
|
70
|
+
hooks.register('task:completed', (p) => {
|
|
71
|
+
try {
|
|
72
|
+
this.onTerminal(p.executionContext.taskId);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
/* observational */
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
hooks.register('task:failed', (p) => {
|
|
79
|
+
try {
|
|
80
|
+
this.onTerminal(p.executionContext.taskId);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
/* observational */
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
hooks.register('task:cancelled', (p) => {
|
|
87
|
+
try {
|
|
88
|
+
this.onTerminal(p.executionContext.taskId);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
/* observational */
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
// Enforcement — throws propagate (NO try/catch wrapper).
|
|
95
|
+
hooks.registerEnforcement('pre:model_request', (p) => this.enforce(p));
|
|
96
|
+
hooks.registerEnforcement('pre:tool_call', (p) => this.enforce(p));
|
|
97
|
+
}
|
|
98
|
+
// ── Observational handlers ────────────────────────────────────────────────
|
|
99
|
+
onTaskStart(p) {
|
|
100
|
+
this.accumulators.set(p.executionContext.taskId, {
|
|
101
|
+
taskId: p.executionContext.taskId,
|
|
102
|
+
modelCalls: 0,
|
|
103
|
+
toolCalls: 0,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
onPostModelResponse(p) {
|
|
107
|
+
const acc = this.accumulators.get(p.executionContext.taskId);
|
|
108
|
+
if (acc)
|
|
109
|
+
acc.modelCalls += 1;
|
|
110
|
+
}
|
|
111
|
+
onPostToolCall(p) {
|
|
112
|
+
const acc = this.accumulators.get(p.executionContext.taskId);
|
|
113
|
+
if (acc)
|
|
114
|
+
acc.toolCalls += 1;
|
|
115
|
+
}
|
|
116
|
+
onTerminal(taskId) {
|
|
117
|
+
this.accumulators.delete(taskId);
|
|
118
|
+
}
|
|
119
|
+
// ── Enforcement ───────────────────────────────────────────────────────────
|
|
120
|
+
enforce(p) {
|
|
121
|
+
const acc = this.accumulators.get(p.executionContext.taskId);
|
|
122
|
+
// No accumulator (task:start not seen) — be permissive, not crashy.
|
|
123
|
+
if (!acc)
|
|
124
|
+
return;
|
|
125
|
+
const rules = {
|
|
126
|
+
maxModelCalls: this.cfg.maxModelCalls,
|
|
127
|
+
maxToolCalls: this.cfg.maxToolCalls,
|
|
128
|
+
};
|
|
129
|
+
const violation = evaluateRatePolicy(rules, acc.modelCalls, acc.toolCalls);
|
|
130
|
+
if (violation !== null)
|
|
131
|
+
throw violation;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// ── Factory ───────────────────────────────────────────────────────────────────
|
|
135
|
+
const createPlugin = ({ db, config }) => {
|
|
136
|
+
return new RatePolicyPlugin(db, config);
|
|
137
|
+
};
|
|
138
|
+
export default createPlugin;
|
|
139
|
+
export { createPlugin };
|
|
140
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/agent/agent-core-policy/src/plugin/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rate-policy.ts — pure helper for evaluating rate-policy limits.
|
|
3
|
+
*
|
|
4
|
+
* Stateless: given an effective rules object and a current model-call count,
|
|
5
|
+
* decides whether the limit is crossed and returns the enforcement error payload.
|
|
6
|
+
* Unit-testable independent of hook wiring.
|
|
7
|
+
*/
|
|
8
|
+
import type { IEnforcementError } from '@adhd/agent-base-types';
|
|
9
|
+
/**
|
|
10
|
+
* The effective rules for a `rate`-type policy after shallow-merging
|
|
11
|
+
* `template.rules` with `override_config` (Decision 3 in decisions.md).
|
|
12
|
+
*
|
|
13
|
+
* All limits are optional; a missing key means "no limit enforced."
|
|
14
|
+
*/
|
|
15
|
+
export interface RatePolicyRules {
|
|
16
|
+
/** Max number of model (LLM) calls per task. */
|
|
17
|
+
maxModelCalls?: number;
|
|
18
|
+
/** Max number of tool calls per task. */
|
|
19
|
+
maxToolCalls?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build an IEnforcementError for a rate-policy violation.
|
|
23
|
+
* Code is "POLICY_VIOLATION" (distinct from budget plugin's "BUDGET_EXCEEDED"
|
|
24
|
+
* so the orchestrator can distinguish enforcement source).
|
|
25
|
+
*/
|
|
26
|
+
export declare function makeRatePolicyError(limitName: string, limit: number, current: number): IEnforcementError;
|
|
27
|
+
/**
|
|
28
|
+
* Evaluate whether the given `modelCalls` count violates the effective rules.
|
|
29
|
+
*
|
|
30
|
+
* Returns an IEnforcementError to throw, or `null` when within limits.
|
|
31
|
+
* Pure function: no side effects, deterministic.
|
|
32
|
+
*/
|
|
33
|
+
export declare function evaluateRatePolicy(rules: RatePolicyRules, modelCalls: number, toolCalls: number): IEnforcementError | null;
|
|
34
|
+
//# sourceMappingURL=rate-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-policy.d.ts","sourceRoot":"","sources":["../../../../../../packages/agent/agent-core-policy/src/plugin/rate-policy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,iBAAiB,CAMnB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,iBAAiB,GAAG,IAAI,CAY1B"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rate-policy.ts — pure helper for evaluating rate-policy limits.
|
|
3
|
+
*
|
|
4
|
+
* Stateless: given an effective rules object and a current model-call count,
|
|
5
|
+
* decides whether the limit is crossed and returns the enforcement error payload.
|
|
6
|
+
* Unit-testable independent of hook wiring.
|
|
7
|
+
*/
|
|
8
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
9
|
+
/**
|
|
10
|
+
* Build an IEnforcementError for a rate-policy violation.
|
|
11
|
+
* Code is "POLICY_VIOLATION" (distinct from budget plugin's "BUDGET_EXCEEDED"
|
|
12
|
+
* so the orchestrator can distinguish enforcement source).
|
|
13
|
+
*/
|
|
14
|
+
export function makeRatePolicyError(limitName, limit, current) {
|
|
15
|
+
return {
|
|
16
|
+
isEnforcementError: true,
|
|
17
|
+
code: 'POLICY_VIOLATION',
|
|
18
|
+
message: `POLICY_VIOLATION: rate policy ${limitName} limit is ${limit}, current value is ${current}`,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Evaluate whether the given `modelCalls` count violates the effective rules.
|
|
23
|
+
*
|
|
24
|
+
* Returns an IEnforcementError to throw, or `null` when within limits.
|
|
25
|
+
* Pure function: no side effects, deterministic.
|
|
26
|
+
*/
|
|
27
|
+
export function evaluateRatePolicy(rules, modelCalls, toolCalls) {
|
|
28
|
+
if (rules.maxModelCalls !== undefined && modelCalls >= rules.maxModelCalls) {
|
|
29
|
+
return makeRatePolicyError('maxModelCalls', rules.maxModelCalls, modelCalls);
|
|
30
|
+
}
|
|
31
|
+
if (rules.maxToolCalls !== undefined && toolCalls >= rules.maxToolCalls) {
|
|
32
|
+
return makeRatePolicyError('maxToolCalls', rules.maxToolCalls, toolCalls);
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=rate-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-policy.js","sourceRoot":"","sources":["../../../../../../packages/agent/agent-core-policy/src/plugin/rate-policy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmBH,iFAAiF;AAEjF;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,KAAa,EACb,OAAe;IAEf,OAAO;QACL,kBAAkB,EAAE,IAAa;QACjC,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,iCAAiC,SAAS,aAAa,KAAK,sBAAsB,OAAO,EAAE;KACrG,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAsB,EACtB,UAAkB,EAClB,SAAiB;IAEjB,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,IAAI,UAAU,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QAC3E,OAAO,mBAAmB,CACxB,eAAe,EACf,KAAK,CAAC,aAAa,EACnB,UAAU,CACX,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,SAAS,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACxE,OAAO,mBAAmB,CAAC,cAAc,EAAE,KAAK,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy library seeder — populates `policy_policy_types` and
|
|
3
|
+
* `policy_policy_templates` idempotently.
|
|
4
|
+
*
|
|
5
|
+
* `seed(db)` is safe to call multiple times on the same database:
|
|
6
|
+
* - Types use `INSERT OR IGNORE` (ON CONFLICT DO NOTHING).
|
|
7
|
+
* - Templates use `INSERT OR IGNORE` (ON CONFLICT DO NOTHING).
|
|
8
|
+
* - A second call is a genuine no-op — no version bump, no duplicate rows,
|
|
9
|
+
* no error. [seed-and-roundtrip.1]
|
|
10
|
+
*
|
|
11
|
+
* The caller is responsible for running migrations BEFORE calling `seed()`.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import Database from "better-sqlite3";
|
|
16
|
+
* import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
17
|
+
* import { runMigrationsOn } from "@adhd/agent-policy/db/migrate-runner";
|
|
18
|
+
* import { seed } from "@adhd/agent-policy";
|
|
19
|
+
* import * as schema from "@adhd/agent-policy/db/schema";
|
|
20
|
+
*
|
|
21
|
+
* const sqlite = new Database("./data/agents.db");
|
|
22
|
+
* const db = drizzle(sqlite, { schema });
|
|
23
|
+
* runMigrationsOn(sqlite, db);
|
|
24
|
+
* seed(db);
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
type AnyBetterSQLite3Database = import('drizzle-orm/better-sqlite3').BetterSQLite3Database<any>;
|
|
28
|
+
/**
|
|
29
|
+
* Idempotently insert all canonical policy types and system templates.
|
|
30
|
+
*
|
|
31
|
+
* Uses `onConflictDoNothing()` (Drizzle's typed wrapper for `INSERT OR IGNORE`)
|
|
32
|
+
* so re-running is always safe: no duplicate rows, no errors, version unchanged.
|
|
33
|
+
*
|
|
34
|
+
* @param db — a Drizzle `BetterSQLite3Database` instance with migrations applied.
|
|
35
|
+
*/
|
|
36
|
+
export declare function seed(db: AnyBetterSQLite3Database): void;
|
|
37
|
+
export { POLICY_TYPES } from './policy-types.js';
|
|
38
|
+
export { POLICY_TEMPLATES } from './policy-templates.js';
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/agent/agent-core-policy/src/seed/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,KAAK,wBAAwB,GAAG,OAAO,4BAA4B,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAC;AAMhG;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,EAAE,EAAE,wBAAwB,GAAG,IAAI,CAsBvD;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy library seeder — populates `policy_policy_types` and
|
|
3
|
+
* `policy_policy_templates` idempotently.
|
|
4
|
+
*
|
|
5
|
+
* `seed(db)` is safe to call multiple times on the same database:
|
|
6
|
+
* - Types use `INSERT OR IGNORE` (ON CONFLICT DO NOTHING).
|
|
7
|
+
* - Templates use `INSERT OR IGNORE` (ON CONFLICT DO NOTHING).
|
|
8
|
+
* - A second call is a genuine no-op — no version bump, no duplicate rows,
|
|
9
|
+
* no error. [seed-and-roundtrip.1]
|
|
10
|
+
*
|
|
11
|
+
* The caller is responsible for running migrations BEFORE calling `seed()`.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import Database from "better-sqlite3";
|
|
16
|
+
* import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
17
|
+
* import { runMigrationsOn } from "@adhd/agent-policy/db/migrate-runner";
|
|
18
|
+
* import { seed } from "@adhd/agent-policy";
|
|
19
|
+
* import * as schema from "@adhd/agent-policy/db/schema";
|
|
20
|
+
*
|
|
21
|
+
* const sqlite = new Database("./data/agents.db");
|
|
22
|
+
* const db = drizzle(sqlite, { schema });
|
|
23
|
+
* runMigrationsOn(sqlite, db);
|
|
24
|
+
* seed(db);
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
import { policyTypesTable, policyTemplatesTable } from '../db/schema.js';
|
|
28
|
+
import { POLICY_TYPES } from './policy-types.js';
|
|
29
|
+
import { POLICY_TEMPLATES } from './policy-templates.js';
|
|
30
|
+
/**
|
|
31
|
+
* Idempotently insert all canonical policy types and system templates.
|
|
32
|
+
*
|
|
33
|
+
* Uses `onConflictDoNothing()` (Drizzle's typed wrapper for `INSERT OR IGNORE`)
|
|
34
|
+
* so re-running is always safe: no duplicate rows, no errors, version unchanged.
|
|
35
|
+
*
|
|
36
|
+
* @param db — a Drizzle `BetterSQLite3Database` instance with migrations applied.
|
|
37
|
+
*/
|
|
38
|
+
export function seed(db) {
|
|
39
|
+
// 1. Policy types first (templates FK into this table).
|
|
40
|
+
for (const typeRow of POLICY_TYPES) {
|
|
41
|
+
db.insert(policyTypesTable).values(typeRow).onConflictDoNothing().run();
|
|
42
|
+
}
|
|
43
|
+
// 2. Policy templates — one upsert per template.
|
|
44
|
+
for (const tmpl of POLICY_TEMPLATES) {
|
|
45
|
+
db.insert(policyTemplatesTable)
|
|
46
|
+
.values({
|
|
47
|
+
slug: tmpl.slug,
|
|
48
|
+
type: tmpl.type,
|
|
49
|
+
description: tmpl.description,
|
|
50
|
+
// drizzle `text({ mode: "json" })` serialises automatically.
|
|
51
|
+
rules: tmpl.rules,
|
|
52
|
+
enforcement: tmpl.enforcement,
|
|
53
|
+
version: tmpl.version,
|
|
54
|
+
isSystem: tmpl.isSystem,
|
|
55
|
+
})
|
|
56
|
+
.onConflictDoNothing()
|
|
57
|
+
.run();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export { POLICY_TYPES } from './policy-types.js';
|
|
61
|
+
export { POLICY_TEMPLATES } from './policy-templates.js';
|
|
62
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/agent/agent-core-policy/src/seed/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAKH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD;;;;;;;GAOG;AACH,MAAM,UAAU,IAAI,CAAC,EAA4B;IAC/C,wDAAwD;IACxD,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;QACnC,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,CAAC;IAC1E,CAAC;IAED,iDAAiD;IACjD,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;QACpC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC;aAC5B,MAAM,CAAC;YACN,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,6DAA6D;YAC7D,KAAK,EAAE,IAAI,CAAC,KAA0B;YACtC,WAAW,EAAE,IAAI,CAAC,WAAgC;YAClD,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC;aACD,mBAAmB,EAAE;aACrB,GAAG,EAAE,CAAC;IACX,CAAC;AACH,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed data for the `policy_policy_templates` table.
|
|
3
|
+
*
|
|
4
|
+
* Every entry carries REAL `rules` JSON from SEED_DATA.md §9. Placeholders
|
|
5
|
+
* defeat idempotency and the round-trip proof. [seed-and-roundtrip.2]
|
|
6
|
+
*
|
|
7
|
+
* Key invariants honoured here:
|
|
8
|
+
* - `enforcement` is ALWAYS a JSON array — never a scalar string.
|
|
9
|
+
* [inv:enforcement-is-array]
|
|
10
|
+
* - `no-credentials` carries `enforcement: ["agent","ci"]` — the multi-value
|
|
11
|
+
* case that round-trip tests must exercise.
|
|
12
|
+
* - `sox-audit-trail` is seeded as `hook_type: "observational"` (Decision 2 —
|
|
13
|
+
* its hook point is TOOL_CALL, not pre:model_request, so it must NOT be
|
|
14
|
+
* registered via registerEnforcement).
|
|
15
|
+
* - All entries are `is_system: true, version: 1`.
|
|
16
|
+
* - `INSERT OR IGNORE` semantics in the seeder keep re-runs as no-ops.
|
|
17
|
+
* [seed-and-roundtrip.1]
|
|
18
|
+
*
|
|
19
|
+
* Source: SEED_DATA.md §9 — Policy Templates.
|
|
20
|
+
*/
|
|
21
|
+
export interface PolicyTemplateSeedRow {
|
|
22
|
+
slug: string;
|
|
23
|
+
type: string;
|
|
24
|
+
description: string;
|
|
25
|
+
rules: Record<string, unknown>;
|
|
26
|
+
enforcement: string[];
|
|
27
|
+
version: number;
|
|
28
|
+
isSystem: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The system policy templates that ship with the agent registry.
|
|
32
|
+
*
|
|
33
|
+
* Includes:
|
|
34
|
+
* - `reviewer-posture` — safety, ["agent"]
|
|
35
|
+
* - `no-credentials` — safety, ["agent","ci"] ← multi-value case
|
|
36
|
+
* - `sox-audit-trail` — audit, ["hook"] ← observational only (Decision 2)
|
|
37
|
+
* - `max-rework-3` — rate, ["runtime"]
|
|
38
|
+
* - `evidence-required` — quality, ["runtime"]
|
|
39
|
+
* - `read-only` — permission, ["settings"]
|
|
40
|
+
* - `phase-gate-required` — compliance, ["runtime","ci"]
|
|
41
|
+
* - `originality-check` — quality, ["ci"]
|
|
42
|
+
* - `allowed-delegation` — permission, ["runtime"]
|
|
43
|
+
*/
|
|
44
|
+
export declare const POLICY_TEMPLATES: readonly PolicyTemplateSeedRow[];
|
|
45
|
+
//# sourceMappingURL=policy-templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-templates.d.ts","sourceRoot":"","sources":["../../../../../../packages/agent/agent-core-policy/src/seed/policy-templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,qBAAqB,EA6KnD,CAAC"}
|