Ship skills built-in: bundle the catalogue, assign per hire, force humanizer

Skills no longer come from the user's ~/.agents library - most users have
none, and the CEO branch that compiled the entire catalogue into its
prompt overflowed the model context (1.1MB) and failed every CEO run.

- Bundle "built-in skills/" with the app (extraResources) and stage it
  at startup into <profile>/builtin-skills as one dir-per-skill copy -
  both bundle shapes (SKILL.md dirs and flat category .md files)
  normalize into the same importable layout
- Import the staged catalogue per org at startup and inside onboarding,
  so the CEO's first run already carries it
- Forced house style: resolveRuntimeSnapshot unions the humanizer skill
  into every agent's runtime (CEO included) as a resolution rule - no
  binding row to forget, delete, or bypass; revoke_skill refuses it
- CEO staffs hires with skills: hire_agent accepts a skills array,
  grant_skill/revoke_skill adjust later, list_skills now shows
  descriptions from skill frontmatter
- Kill the c_suite compile-all branch; everyone resolves bindings-only,
  capped at 200k chars with omissions named in the prompt
- Remove the Skills settings page and its import/sync/test IPC surface;
  drop ~/.agents discovery and the AGENTCOMPANY_NEW_SKILLS_ROOT seam in
  favor of AGENTCOMPANY_NEW_BUILTIN_SKILLS_DIR
- Tests: staging/import/forced-resolution/cap units, real-bundle CI
  check, e2e asserts the tab is gone and the catalogue self-imports
This commit is contained in:
ZacharyZhang-NY committed 2026-07-08 21:18:50 -04:00
1 parent 55c043f8b4
commit 86aa6fdb29
318 files changed
+77467 -520

No files matched your search

+14 -9
View File
@@ -28,7 +28,7 @@ import { AutomationService } from "../services/automation-service";
import { MeetingService } from "../services/meeting-service";
import { SprintService } from "../services/sprint-service";
import { ComposioConnectionService } from "../services/composio/composio-connection-service";
import { syncSkillsFromDisk } from "../services/skill-discovery";
import { importStagedSkills, stageBuiltinSkillsLibrary } from "../services/builtin-skills";
import { coalesce } from "./coalesce";
import { normalizeExternalBrowserUrl } from "./external-url";
@@ -36,6 +36,10 @@ export interface IpcDeps {
connection: DatabaseConnection;
mainWindow: BrowserWindow;
artifactRoot: string;
/** Bundled built-in skills source (repo folder in dev, resources when packaged). */
builtinSkillsSource: string;
/** Normalized on-disk skill library under the profile directory. */
builtinSkillsLibrary: string;
}
export function registerIpcHandlers(deps: IpcDeps): void {
@@ -94,9 +98,17 @@ export function registerIpcHandlers(deps: IpcDeps): void {
ipcMain.handle(IPC_CHANNELS.bootstrapOnboarding, (_event, input) => {
try {
let summary;
let summary: { orgId: string } | undefined;
// Staging happens before the transaction (file mirroring), the import
// inside it: the CEO's kickoff run can be claimed within seconds of
// commit and must already find the forced humanizer skill.
const staged = stageBuiltinSkillsLibrary(deps.builtinSkillsSource, deps.builtinSkillsLibrary);
deps.connection.transaction(() => {
summary = onboarding.bootstrap(input);
const report = importStagedSkills(skills, summary.orgId, staged);
if (report.failures.length > 0) {
console.warn(`[skills] onboarding import failures (${report.failures.length}): ${report.failures.slice(0, 3).join("; ")}`);
}
});
notifyDataChanged();
return ok(summary);
@@ -264,13 +276,6 @@ export function registerIpcHandlers(deps: IpcDeps): void {
return fail("provider_cancel_failed", error instanceof Error ? error.message : String(error));
}
});
ipcMain.handle(IPC_CHANNELS.importSkillDirectory, (_event, input) => mutate(() => skills.importDirectory(input)));
ipcMain.handle(IPC_CHANNELS.syncSkillsFromDisk, (_event, input) => mutate(() => {
syncSkillsFromDisk(deps.connection.db, skills, input.orgId);
return null;
}));
ipcMain.handle(IPC_CHANNELS.resolveAgentSkills, (_event, input) => mutate(() => skills.resolveRuntimeSnapshot(input)));
ipcMain.handle(IPC_CHANNELS.runSkillTests, (_event, input) => mutate(() => skills.runTests(input)));
ipcMain.handle(IPC_CHANNELS.createSocialAccount, (_event, input) => mutate(() => social.createAccount(input)));
ipcMain.handle(IPC_CHANNELS.createScheduledPost, (_event, input) => mutate(() => social.createScheduledPost(input)));
ipcMain.handle(IPC_CHANNELS.setScheduledPostState, (_event, input) => mutate(() => social.setScheduledPostState(input)));