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

+34 -14
View File
@@ -5,7 +5,7 @@ import type { DatabaseSync } from "node:sqlite";
import { DatabaseConnection } from "./database/connection";
import { createMainWindow } from "./app/create-window";
import { registerIpcHandlers } from "./app/ipc-handlers";
import { syncSkillsFromDisk } from "./services/skill-discovery";
import { builtinSkillsSourceOverride, importStagedSkills, stageBuiltinSkillsLibrary } from "./services/builtin-skills";
import { SkillService } from "./services/skill-service";
import { startProviderBackgroundWorker } from "./app/provider-background-worker";
import { recoverInterruptedWork } from "./app/startup-recovery";
@@ -35,12 +35,16 @@ if (!app.requestSingleInstanceLock()) {
language,
});
const builtinSkillsSource = resolveBuiltinSkillsSource();
const builtinSkillsLibrary = join(profileDir, "builtin-skills");
registerIpcHandlers({
connection,
mainWindow: win,
artifactRoot: join(profileDir, "artifacts"),
builtinSkillsSource,
builtinSkillsLibrary,
});
syncAllOrganizationSkills(connection.db, join(profileDir, "artifacts"));
syncAllOrganizationSkills(connection, join(profileDir, "artifacts"), builtinSkillsSource, builtinSkillsLibrary);
const stopProviderBackgroundWorker = startProviderBackgroundWorker({
db: connection.db,
mainWindow: win,
@@ -73,19 +77,35 @@ function storedLanguage(db: DatabaseSync): string {
}
/**
* Loads the on-disk skill library for every organization at startup. One
* organization's failure (a broken workspace path, say) must not block the
* rest — or the app.
* The bundled skill catalogue: the repo folder during development, the
* extraResources copy in a packaged build, or an explicit override for
* hermetic tests (same seam pattern as AGENTCOMPANY_NEW_PROFILE_DIR).
*/
function syncAllOrganizationSkills(db: DatabaseSync, artifactRoot: string): void {
const skills = new SkillService(db, artifactRoot);
const orgs = db.prepare("select id from organizations").all() as Array<{ id: string }>;
for (const org of orgs) {
try {
syncSkillsFromDisk(db, skills, org.id);
} catch {
// Broken directories are reported per entry inside the sync; anything
// beyond that is a per-org environment fault that must not stop startup.
function resolveBuiltinSkillsSource(): string {
const override = builtinSkillsSourceOverride();
if (override) return override;
if (app.isPackaged) return join(process.resourcesPath, "built-in-skills");
return join(app.getAppPath(), "built-in skills");
}
/**
* Mirrors the bundled skill catalogue into the profile library and imports it
* for every organization at startup. Per-skill failures are reported inside
* the sync; a broken bundle is loud in the log but must not stop the app.
*/
function syncAllOrganizationSkills(connection: DatabaseConnection, artifactRoot: string, sourceRoot: string, libraryRoot: string): void {
try {
const staged = stageBuiltinSkillsLibrary(sourceRoot, libraryRoot);
const skills = new SkillService(connection.db, artifactRoot);
const orgs = connection.db.prepare("select id from organizations").all() as Array<{ id: string }>;
for (const org of orgs) {
const report = connection.transaction(() => importStagedSkills(skills, org.id, staged));
if (report.imported > 0 || report.failures.length > 0) {
console.info(`[skills] org ${org.id}: imported ${report.imported}, skipped ${report.skipped}, failures ${report.failures.length}`);
for (const failure of report.failures.slice(0, 5)) console.warn(`[skills] ${failure}`);
}
}
} catch (error) {
console.error(`[skills] built-in skill sync failed: ${error instanceof Error ? error.message : String(error)}`);
}
}