Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This repository follows a harness-oriented workflow: docs first, clear interface

## Fast Map
- Canonical docs index: [docs/README.md](docs/README.md)
- Canonical rearchitecture decision: [docs/architecture/rearchitecture-decision.md](docs/architecture/rearchitecture-decision.md)
- Current execution plan: [docs/plans/active/2026-02-18-cp6-sessions-memory-scaffolding.md](docs/plans/active/2026-02-18-cp6-sessions-memory-scaffolding.md)
- Checkpoint board: [docs/checkpoints/mvp-status.md](docs/checkpoints/mvp-status.md)
- CP10 verification matrix: [docs/checkpoints/cp10-verification.md](docs/checkpoints/cp10-verification.md)
Expand Down
62 changes: 62 additions & 0 deletions agents/capability-catalog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { ResourceKind } from "./resource-kinds.js";
import type { ToolPrimitive } from "./tool-primitives.js";

export type CapabilityDefinition = Readonly<{
resourceSlots: Readonly<Record<string, ResourceKind>>;
skills: readonly string[];
grants: Readonly<{
toolPrimitives: readonly ToolPrimitive[];
}>;
guidance: readonly string[];
}>;

export const capabilityCatalog = {
"query-gravity-v1": {
resourceSlots: {},
skills: ["query-gravity"],
grants: {
toolPrimitives: ["read", "bash"],
},
guidance: [
"- `query-gravity-v1`: inspect Gravity runtime metadata and run logs for debugging and operations evidence.",
],
},
"rollback-v1": {
resourceSlots: {},
skills: ["rollback"],
grants: {
toolPrimitives: ["read", "bash"],
},
guidance: [
"- `rollback-v1`: apply file-scoped rollback procedures using non-destructive git patterns.",
],
},
"duckdb-analyst-v1": {
resourceSlots: {
warehouse: "duckdb",
},
skills: ["duckdb-query"],
grants: {
toolPrimitives: ["read", "bash"],
},
guidance: [
"- `duckdb-analyst-v1`: execute SQL-backed analysis against the bound DuckDB warehouse resource.",
],
},
"knowledge-docs-review-v1": {
resourceSlots: {
docs: "knowledge-docs",
},
skills: ["knowledge-docs-review"],
grants: {
toolPrimitives: ["read"],
},
guidance: [
"- `knowledge-docs-review-v1`: ground policy/process recommendations in the bound knowledge-docs resource.",
],
},
} as const satisfies Record<string, CapabilityDefinition>;

export type CapabilityCatalog = typeof capabilityCatalog;
export type CapabilityId = keyof CapabilityCatalog;
export type CapabilitySkillId = CapabilityCatalog[CapabilityId]["skills"][number];
116 changes: 116 additions & 0 deletions agents/capability-compiler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { capabilityCatalog } from "./capability-catalog.js";
import type {
AgentCapabilityBinding,
AgentResource,
CapabilityId,
CapabilitySkillId,
} from "./contracts.js";
import type { ToolPrimitive } from "./tool-primitives.js";

export type CompiledCapability = Readonly<{
capability: CapabilityId;
bindResources: Readonly<Record<string, AgentResource>>;
skillIds: readonly CapabilitySkillId[];
resourceIds: readonly string[];
grants: Readonly<{
toolPrimitives: readonly ToolPrimitive[];
}>;
guidance: readonly string[];
}>;

export type CompiledAgentCapabilities = Readonly<{
capabilities: readonly CompiledCapability[];
requiredSkillIds: readonly CapabilitySkillId[];
requiredResources: readonly AgentResource[];
toolPrimitives: readonly ToolPrimitive[];
capabilityGuidance: readonly string[];
}>;

function unique<T>(values: readonly T[]): T[] {
return Array.from(new Set(values));
}

function formatBoundResources(bindResources: Record<string, AgentResource>): string {
const entries = Object.entries(bindResources)
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([slot, resource]) => `${slot}=${resource.id}`);

if (entries.length === 0) {
return "(none)";
}

return entries.join(", ");
}

export function compileAgentCapabilities(input: {
resources: readonly AgentResource[];
useCapabilities: readonly AgentCapabilityBinding[];
}): CompiledAgentCapabilities {
const resourcesById = new Map<string, AgentResource>();
for (const resource of input.resources) {
resourcesById.set(resource.id, resource);
}

const compiledCapabilities: CompiledCapability[] = [];

for (const binding of input.useCapabilities) {
const definition = capabilityCatalog[binding.capability];
const bindResources: Record<string, AgentResource> = {};

for (const [slot, resourceId] of Object.entries(binding.bindResources)) {
const resource = resourcesById.get(resourceId);
if (!resource) {
throw new Error(
`Capability ${binding.capability} references unknown resource id: ${resourceId}`,
);
}
bindResources[slot] = resource;
}

const resourceIds = Object.values(bindResources)
.map((resource) => resource.id)
.sort();

const boundResourcesLine = formatBoundResources(bindResources);
const guidance = [
...definition.guidance,
`- Capability \`${binding.capability}\` bound resources: ${boundResourcesLine}`,
];

compiledCapabilities.push({
capability: binding.capability,
bindResources,
skillIds: [...definition.skills],
resourceIds,
grants: {
toolPrimitives: [...definition.grants.toolPrimitives],
},
guidance,
});
}

const requiredSkillIds = unique(
compiledCapabilities.flatMap((capability) => capability.skillIds),
);
const requiredResourceIds = unique(
compiledCapabilities.flatMap((capability) => capability.resourceIds),
);
const requiredResources = requiredResourceIds
.map((resourceId) => resourcesById.get(resourceId))
.filter((resource): resource is AgentResource => Boolean(resource));

const toolPrimitives = unique(
compiledCapabilities.flatMap((capability) => capability.grants.toolPrimitives),
);
const capabilityGuidance = compiledCapabilities.flatMap(
(capability) => capability.guidance,
);

return {
capabilities: compiledCapabilities,
requiredSkillIds,
requiredResources,
toolPrimitives,
capabilityGuidance,
};
}
80 changes: 80 additions & 0 deletions agents/compliance-helper/agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { defineAgent } from "../contracts.js";

export const complianceHelperAgent = defineAgent({
id: "compliance-helper",
name: "Compliance Helper",
description: "Compliance review proof-of-concept agent.",
model: "claude-sonnet-4-5-20250929",
runtime: "host",
resources: [
{
id: "policy-docs",
kind: "knowledge-docs",
},
],
session: {
defaultMode: "thread",
},
listen: [
{
id: "slack-compliance-slash",
kind: "message",
surface: "slack",
entrypoint: "slash_command",
sessionMode: "thread",
match: {
command: "/compliance",
},
enabled: true,
},
{
id: "slack-compliance-mention",
kind: "message",
surface: "slack",
entrypoint: "app_mention",
sessionMode: "thread",
enabled: true,
},
{
id: "slack-compliance-thread",
kind: "message",
surface: "slack",
entrypoint: "thread_reply",
match: {
threadOwnedByAgent: true,
},
sessionMode: "thread",
enabled: true,
},
{
id: "slack-compliance-dm",
kind: "message",
surface: "slack",
entrypoint: "direct_message",
sessionMode: "main",
enabled: true,
},
],
proactive: {
deliveryDefaults: {
surface: "slack",
mode: "channel_thread",
channelId: "C0AFYK6AVQR",
},
triggers: [],
},
useCapabilities: [
{
capability: "query-gravity-v1",
},
{
capability: "rollback-v1",
},
{
capability: "knowledge-docs-review-v1",
bindResources: {
docs: "policy-docs",
},
},
],
});
Loading